Le mar. 6 juil. 2021 à 15:38, Nikita Popov <nikita....@gmail.com> a écrit :

> 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.
>

Types are a good example of a structure that the language already knows how
to parse without actually requiring all symbols to be loaded: Foo|Bar
doesn't require having both types loaded to work.

I think we don't need to account for constants in my scenario.

ReflectionAttribute::getUninitializedArguments() would then only replace
objects with uninitialized placeholders that represent their class and
arguments.

That should cover the need.

Reply via email to