On Mon, Oct 5, 2020 at 9:24 AM Nicolas Grekas <nicolas.gre...@gmail.com> wrote:

>> 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)].
>
> Nikita

Back when the original `<<>>` attribute syntax was being implemented,
there was an attempt to do just this. But it turned out to be very
difficult to implement, and it was ultimately given up on since it
required significant changes to const expressions. Earlier this year
there was also a poll to gauge interest in supporting function calls
in constant expressions, but most voters opposed it. [1]

Even if a proposal for relaxing constraints on constant expressions
gains enough support, it's not clear this is the ideal path forward
for nested attributes, since as Nicolas pointed out this wouldn't
have the same lazy-loading semantics as existing attributes.

Straightforward support for nested attributes was one of my main
motivations for proposing the `@@` syntax in the Shorter Attribute
Syntax RFC, [2] and I had hoped to collaborate on a follow-up RFC to
support nested attributes with the AT-AT syntax. This would allow
existing nested docblock annotations such as Nicolas's example to
translate intuitively to native attributes:

    @@Assert\All([
        @@Assert\Email,
        @@Assert\NotBlank,
        @@Assert\Length(max: 100)
    ])

This would also preserve the lazy-loading feature where these
attribute classes aren't loaded until code calls `newInstance`
on one of the `ReflectionAttribute` objects.

But then the Shorter Attribute Syntax Change RFC [3] came along and
derailed this plan...

In theory nested attributes could be supported in the same way with
the `#[]` syntax, but it's more verbose and I think less intuitive
(e.g. people may try to use the grouped syntax in this context, but
it wouldn't work). Also the combination of brackets delineating both
arrays and attributes reduces readability:

    #[Assert\All([
        #[Assert\Email],
        #[Assert\NotBlank],
        #[Assert\Length(max: 100)]
    ])]

But at this point I assume this is the most viable path forward for
nested attributes (barring another syntax re-vote and delay of PHP 8).
I know Derick and Benjamin have stated they aren't in favor of nested
attributes and didn't put any thought into the syntax for them, but I
feel this is unfortunate since nested attributes are an established
pattern with legitimate use cases in existing libraries.

Best regards,  
Theodore

[1]: https://wiki.php.net/rfc/calls_in_constant_expressions_poll
[2]: https://wiki.php.net/rfc/shorter_attribute_syntax
[3]: https://wiki.php.net/rfc/shorter_attribute_syntax_change
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to