Skip to content

Attributes that target functions are not valid for anonymous functions defined within a method #8421

Closed
@ollieread

Description

@ollieread

Description

If an anonymous function is defined inside a method, attempting to create a new instance of any attribute attached to it, through reflection, that only targets functions (#[Attribute(Attribute::TARGET_FUNCTION)]) will cause an error with the message.

Fatal error: Uncaught Error: Attribute "AttributeName" cannot target method (allowed targets: function)

This happens in both object and static contexts. Changing the attribute to work with methods instead will cause an inverted error if the closure is defined outside of a method within the global context.

Examples

This code works fine and gives no output, as expected. (https://3v4l.org/iDuIL#v8.1.4)

<?php

#[Attribute(Attribute::TARGET_FUNCTION)]
class FunctionAttribute
{
}

$closure = #[FunctionAttribute]
fn() => true;

class Something
{
    public function get(Closure $closure)
    {
        return (new ReflectionFunction($closure))
                   ->getAttributes(FunctionAttribute::class)[0]
            ->newInstance();
    }
}

(new Something)->get($closure);

This code gives an error. (https://3v4l.org/Clenb#v8.1.4)

<?php

#[Attribute(Attribute::TARGET_FUNCTION)]
class FunctionAttribute
{
}

class Something
{
    public function get()
    {
        $closure = #[FunctionAttribute]
        fn() => true;
        return (new ReflectionFunction($closure))
                   ->getAttributes(FunctionAttribute::class)[0]
            ->newInstance();
    }
}

(new Something)->get();

Its output is:

Fatal error: Uncaught Error: Attribute "FunctionAttribute" cannot target method (allowed targets: function) in /in/Clenb:16
Stack trace:
#0 /in/Clenb(16): ReflectionAttribute->newInstance()
#1 /in/Clenb(20): Something->get()
#2 {main}
  thrown in /in/Clenb on line 16

Process exited with code 255.

As does this same code, but using a static method instead. (https://3v4l.org/s4Gk0#v8.1.4)

<?php

#[Attribute(Attribute::TARGET_FUNCTION)]
class FunctionAttribute
{
}

class Something
{
    public static function get()
    {
        $closure = #[FunctionAttribute]
        fn() => true;
        return (new ReflectionFunction($closure))
                   ->getAttributes(FunctionAttribute::class)[0]
            ->newInstance();
    }
}

Something::get();

Which also outputs:

Fatal error: Uncaught Error: Attribute "FunctionAttribute" cannot target method (allowed targets: function) in /in/s4Gk0:16
Stack trace:
#0 /in/s4Gk0(16): ReflectionAttribute->newInstance()
#1 /in/s4Gk0(20): Something::get()
#2 {main}
  thrown in /in/s4Gk0 on line 16

Process exited with code 255.

PHP Version

8.1.4

Operating System

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions