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