Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112007 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 68883 invoked from network); 5 Oct 2020 15:11:14 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 5 Oct 2020 15:11:14 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id E8EBD180511 for ; Mon, 5 Oct 2020 07:24:23 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.45]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 5 Oct 2020 07:24:23 -0700 (PDT) Received: by mail-ed1-f45.google.com with SMTP id g4so9564964edk.0 for ; Mon, 05 Oct 2020 07:24:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=AIa+scNKCs1gsUJOmHMQfDWUs1wFUX2Zd3V6eJFYXhE=; b=FnOh3QxcZtILPmBNAwbnpanWLc7spQRRBYJNEOoZ1iayDBNVD8h5PanLdD5xWoTjyD GbLGz5GObcb3NYTSJltqzJ6DIysXS0hCB/Uu/KDl9SM4quBwprIquW1MZiLCULwTx7pk ue3FuxBl4IPgjGBaI84v27QJ1mZbhUThouWM7W0kvr4nz+jLMJH0POu+XnGvOq/XUxXo Db0tok5XJHE6loAoRLjcAKOqR/hnfT+lNhV2PwKwDMEMcd+eWl8L6+QxOtgCjd8seeri icQHAoJFsVhj2muJE0ToE04mLkIDToTQrm2hvhpx623IXVSMwNKDvkfAmslfWHTdwi02 PI5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=AIa+scNKCs1gsUJOmHMQfDWUs1wFUX2Zd3V6eJFYXhE=; b=mYXWXGRN7JP0FhT1bLBlJoVT+oea3wsptfOv72AgQLxzZlvJZkqGqfK3gdK4xZZnYf DRMJsiKUN4FoDEGQ4bX+quOU9bEFlaK1lQwCqPcwjfFE7L4Ym3FZ7XUTbsPWqDmMQEA9 O40lOqPnr91hTvKkv5zPKo6wuBHwaBkhOZ8kaDZgAprIayhUN49A0noGnFLyfQ4Xq2OJ DMMm9L9A7mvhiML/g1zaOgbQonsUrbz6rH+ncm5pnZ1YsOPAVUwkUHA+2DysB6b8siNG Qhs0jY6rgZdUtemBLmbHhkEZsferbqkjFYpDGSVRhNa/KcBhAM3ICHZBwqj1h/am7mNq 0HvQ== X-Gm-Message-State: AOAM532z9jOB8BT+qkQHsT2EA35Wl8RX50mcXYbQro0za3qSUtbyb4Fm KXtJWwhop2daeP4+nCGUZ2hgJP9kw4i+QW5Nt3c= X-Google-Smtp-Source: ABdhPJy2seh+VleMvAeA9MfZPtM1y7kNo++rPoxjfOo2ECRPIahEpsQj42MJfEgAzoixu7nXgh5ArYantpwx7z4EOVc= X-Received: by 2002:aa7:c491:: with SMTP id m17mr6804383edq.299.1601907860582; Mon, 05 Oct 2020 07:24:20 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: Date: Mon, 5 Oct 2020 16:24:09 +0200 Message-ID: To: Benjamin Eberlei Cc: Nikita Popov , PHP Internals List Content-Type: multipart/alternative; boundary="000000000000fe356105b0ed3c2c" Subject: Re: [PHP-DEV] List of attributes From: nicolas.grekas@gmail.com (Nicolas Grekas) --000000000000fe356105b0ed3c2c Content-Type: text/plain; charset="UTF-8" > > Hi Benjamin, hi everyone >>>> >>>> I'm wondering if the syntax that allows for several attributes is really >>>> future-proof when considering nested attributes: >>>> >>>> >>>> *1.* >>>> #[foo] >>>> #[bar] >>>> >>>> VS >>>> >>>> >>>> *2.* >>>> #[foo, bar] >>>> >>>> Add nested attributes to the mix, here are two possible ways: >>>> >>>> >>>> *A.* >>>> #[foo( >>>> #[bar] >>>> )] >>>> >>>> or >>>> >>>> >>>> *B.* >>>> #[foo( >>>> bar >>>> )] >>>> >>>> The A. syntax is consistent with the 1. list. >>>> I feel like syntax B is not desired and could be confusing from a >>>> grammar >>>> pov. >>>> BUT in syntax 2., we allow an attribute to be unprefixed (bar), so that >>>> syntax B is consistent with 2. >>>> >>>> Shouldn't we remove syntax 2. in 8.0 and consider it again when nested >>>> attributes are introduced? >>>> >>>> I voted yes for syntax 2. when the attributes were using << >>. I would >>>> vote NO now with the new syntax. >>>> >>>> Nicolas >>>> >>> >>> As far as my understanding goes, if we introduce "nested" attributes, it >>> will be in the form of relaxing constraints on constant expressions, i.e. >>> by allowing you to write #[Attr(new NestedAttr)]. >>> >> >> That's what I've read in previous discussions and in other replies in >> this thread. >> This would break the possibility to read annotations without failing hard >> when a class is missing. >> >> I would much prefer a solution that preserves this capability (which is >> the reason why we have ReflectionAttribute::newInstance(): unless this one >> is called, no autoloading happens. >> >> To me, this means that "new Foo()" nested in an attribute can't be a >> solution. >> Neither should we be able to nest PHP constants there btw. >> > > Can you clarify your reasoning here to get to this conclusion? because > with #[Foo(Foo::BAR)] we also not trigger autoloading right now until > newInstance() > or getArguments() is called. This is the way it is working right now: > https://gist.github.com/beberlei/8150f60abaab3b0a70ebb76ce6a379b0 > > Attributes allow constant expressions as arguments, the same which you can > do in constant or property declarations for the default value. > > An approach with new NestedAttr() would work the same, only triggering > autoload when argument needs to be evaluated for use. > My bad about constants, I was wrong, they already work as part of constant expressions as you highlighted. I was propagating this laziness requirement to nested attributes: they should also be represented as instances of ReflectionAttribute to me at some point. It would look important to me to be able to inspect a tree of attributes and decide what to do with each of them before actually instantiating them (and triggering the autoload cascade). I'm not convinced that nested attributes should be brought to us via an improvement of constant-expressions: first because that would break this laziness requirement, second because I just doubt that constant-expressions should support objects. About providing laziness for attributes, this could be done by ReflectionAttribute::getAttributes(): #[Foo(bar())] could lead to getAttribute returning an array containing a ReflectionAttribute instance for attribute "bar". Of course, this has many consequences and also many alternatives that'd need to be evaluated. I won't be able to lead an effort towards nested attributes in the short term, so I'll just let this on the table here :) Cheers, Nicolas > >> Since we borrowed the syntax to Rust, here is the syntax they use: >> >> > #[validate(length(min = 1), custom = "validate_unique_username")] >> >> I think this would fit quite nicely for us too, by turning eg length into >> an instance of ReflectionAttribute. >> >> Note that a use case for nested attributes is discussed in >> https://github.com/symfony/symfony/pull/38309, to replace things like: >> /** >> @Assert\All([ >> @Assert\Email, >> @Assert\NotBlank, >> @Assert\Length(max=100) >> ]) >> */ >> >> We can work around of course, and we will for 8.0, but it would be nice >> to have a plan forward because similar use cases (grouping attributes in a >> wrapper attribute) are going to be pretty common IMHO. >> >> But we're getting a bit of topic. I'm fine keeping things as is for 8.0. >> I just wanted to raise a point about the syntax for list of attributes but >> it didn't get traction apparently. >> >> Cheers, >> Nicolas >> > --000000000000fe356105b0ed3c2c--