php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75079 self keyword leads to incorrectly generated TypeError when in closure in trait
Submitted: 2017-08-16 18:12 UTC Modified: 2017-08-16 18:24 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: aidantwoods at gmail dot com Assigned:
Status: Open Package: Class/Object related
PHP Version: 7.1.8 OS: Tested: OSX; Kali Linux (Debian)
Private report: No CVE-ID:
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: aidantwoods at gmail dot com
New email:
PHP Version: OS:

 

 [2017-08-16 18:12 UTC] aidantwoods at gmail dot com
Description:
------------
Traits are meant to be syntactic sugar for "copy-pasting" things into classes. As such, when the self keyword is used inside a trait, it does not resolve to the name of the trait, but rather resolves to be the name of the class in which the trait was used in.

If the self keyword is used within a type hint in a closure that is used inside a trait, this closure does not appear to be re-resolved per inclusion.

For example, from the test script included, it should not be possible for the closure to throw a TypeError in any circumstance (if a type error is to be thrown, it should be thrown by the outer method)

    public function selfDo(self ...$Selfs)
    {
        array_map(
            function (self $Self) : self
            {
                return $Self;
            },
            $Selfs
        );
    }

As expected, when calling exclusively the following

    $Bar->selfDo($Bar, $Bar);


No TypeError is thrown. Alternatively, when calling exclusively the following

    $Baz->selfDo($Baz, $Baz);

Also no TypeError is thrown.

The problem arises when calling one after the other (does not need to be immediately after).

Depending on the order those last two lines of the test script are called in, you will see a different error thrown. In the order given, the following is generated (trimmed for brevity)

    Fatal error: Uncaught TypeError: Argument 1 passed to Baz::{closure}() must be an instance of Bar, instance of Baz given in[...]

It seems that once the method is initially called, the self type hint in the closure in the trait resolves to be the name of the class in which it was used in (no bug here), the bug is that this initial class name is now permanently resolved as its current value in latter calls to the same method (from a different unrelated class).



Test script:
---------------
<?php

trait Foo
{
    public function selfDo(self ...$Selfs)
    {
        array_map(
            function (self $Self) : self
            {
                return $Self;
            },
            $Selfs
        );
    }
}

class Bar
{
    use Foo;
}

class Baz
{
    use Foo;
}

$Bar = new Bar;
$Baz = new Baz;


$Bar->selfDo($Bar, $Bar);
$Baz->selfDo($Baz, $Baz);

Actual result:
--------------
Fatal error: Uncaught TypeError: Argument 1 passed to Baz::{closure}() must be an instance of Bar, instance of Baz given in /Users/Aidan/traits.php:8
Stack trace:
#0 [internal function]: Baz->{closure}(Object(Baz))
#1 /Users/Aidan/traits.php(12): array_map(Object(Closure), Array)
#2 /Users/Aidan/traits.php(31): Baz->selfDo(Object(Baz), Object(Baz))
#3 {main}
  thrown in /Users/Aidan/traits.php on line 8

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-08-16 18:24 UTC] aidantwoods at gmail dot com
-Summary: self is only resolved once for closure in trait +Summary: self keyword leads to incorrectly generated TypeError when in closure in trait -Operating System: OSX; Kali Linux (Debian) +Operating System: Tested: OSX; Kali Linux (Debian)
 [2017-08-16 18:24 UTC] aidantwoods at gmail dot com
edit: summary
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Tue Aug 29 15:01:52 2017 UTC