On Tue, Sep 22, 2020 at 2:58 PM Nikita Popov <nikita....@gmail.com> wrote:

> Hi internals,
>
> I would like to clarify how attributes are supposed to interact with
> strict_types. Consider the following code, split up into three files to
> make it clear that each one could have their own strict_types mode:
>
> MyAttribute.php
> <?php
> #[Attribute]
> class MyAttribute {
>     public function __construct(string $a) {}
> }
>
> UseOfMyAttribute.php
> <?php
> declare(strict_types=1);
> #[MyAttribute(42)]
> class Test {}
>
> AccessOfAttribute.php
> <?php
> var_dump((new
> ReflectionClass(Test::class'))->getAttributes()[0]->newInstance());
>
> Currently, what happens is that this code will construct the attribute,
> converting int 42 into string "42", even though UseOfMyAttribute.php has
> strict_types=1.
>
> My intuitive expectation here would be that we should be following the
> strict_types mode of wherever the attribute is being used (i.e.
> UseOfMyAttribute.php, not MyAttribute.php or AccessOfAttribute.php).
> Currently, we always assume strict_types=0.
>
> Is my expectation correct?
>
> Regards,
> Nikita
>

As we seem to have an agreement that strict_types of UseOfMyAttribute.php
should be respected, I've created an implementation for this at
https://github.com/php/php-src/pull/6201.

Partway through I realized that the root problem is really that we want the
constructor call to happen "as if" it was caused by the use-site of the
attribute. This affects not just strict_types=1, but also backtrace and
error information. In particular, this means that the backtrace now also
points you to which attribute use-site resulted in an exception, which
seems like rather useful information to have, as the same attribute might
be used in many places.

This does mean we have to store the line number of the attribute
internally. We could also expose that information via ReflectionAttribute
now, if we wanted.

Regards,
Nikita

Reply via email to