On Tue, Jul 6, 2021 at 2:30 PM Nicolas Grekas <nicolas.grekas+...@gmail.com>
wrote:

>
> > > This is not 100% correct, you can have an attribte #[Foo(Foo::class)]
>> and
>> > > then calling ReflectionAttribute::getArguments would also require to
>> > > resolve the type Foo. So this is not different than what could happen
>> > right
>> > > now already.
>> >
>> >
>> > Despite its name, "::class" doesn't care about class definitions, it
>> > just performs a string substitution based on the "namespace" and "use"
>> > statements in the current file.
>> >
>> > In most cases, that happens entirely at compile time, so the following
>> > two source files compile identically:
>> >
>>
>> Hah, I realized after sending the example was bad :) I should have used an
>> example using actual constants (vs magic ones):
>>
>> #[Foo(Foo::BAR)]
>>
>> This would trigger autoloading and resolving during getArguments()
>>
>
>
> Right!
>
> Extending on my proposal, getUninitializedArguments() could return a
> ReflectionConstant in place of such values.
>

This doesn't extend to any more complex scenario: It's not just
#[Foo(A::B)], it could also be #[Foo(A::FLAG_1 | A::FLAG_2)] and so on. The
only way to do this is to go all the way back to Dmitry's attribute
proposal (https://wiki.php.net/rfc/attributes) which allows fetching the
AST of attribute arguments. That could represent arbitrary arguments
without evaluating them. (In fact, that proposal also allowed attribute
arguments that PHP cannot constant-evaluate at all.)

I also think that viewing this as "nested attributes" is not quite the
right way to think about it. Yes, the Assert\All use case is nested
attributes, but that's just a special case. More generally this just allows
you to use an object as an attribute argument, and that object does not
necessarily have to be an attribute itself. To give a silly example, if we
were to write argument and return types as attributes, you could have
something like #[ReturnType(new IntersectionType(Foo::class, Bar::class))],
where IntersectionType is just the representation of a particular type, but
is not (and shouldn't be) an attribute itself.

Regards,
Nikita

Reply via email to