From: vovan-ve at yandex dot ru Operating system: PHP version: Irrelevant Package: Class/Object related Bug Type: Bug Bug description:Type hint 'self' means plain 'self' instead of original target class
Description: ------------ It seems to me, there is some unclear situation with keywords «self» (and «parent»). At least this keywords has no detailed documentation. Imaging following interface: interface IFoo { public function lorem(IFoo $foo); public function ipsum(self $foo); } The first method lorem() wants an implementation of IFoo as argument. The one problem here is a duplication of the name IFoo inside itself. Usage of keyword «self» should prevent this "problem", but in theory only. The second method ipsum() extects an instance of... of what? In fact, it wants an instance of «self» - that is an instance of implementation class, which implements or even overrides the method later. The problem is the fact, that keyword «self» means SELF, not a class or an interface, there it is writen. We cannot change «self» to «IFoo» in implementation: interface IFoo { public function ipsum(self $foo); } class Fail implements IFoo { public function ipsum(IFoo $foo) { } } // Error: Fail::ipsum() must be compatible with IFoo::ipsum() The ReflectionClass shows «IFoo», «self» and «parent» for corresponding methods: interface IFoo { public function lorem(IFoo $foo); public function ipsum(self $foo); public function dolor(parent $foo); } $ref = new ReflectionClass('IFoo'); echo $ref; Output: Method [ <user> abstract public method lorem ] { - Parameters [1] { Parameter #0 [ <required> IFoo $foo ] } } Method [ <user> abstract public method ipsum ] { - Parameters [1] { Parameter #0 [ <required> self $foo ] } } Method [ <user> abstract public method dolor ] { - Parameters [1] { Parameter #0 [ <required> parent $foo ] } } When we write «self» somewhere, we mean that thing, where «self» is writen. I think, that method ipsum() should be compiled to receive instance of IFoo and nothing else. The method dolor() shoult to emit fatal error, because IFoo has no parent. If I mistake with that deep meaning if the keywords «self» and «parent», and this isn't a bug, I sure this keywords should be documented properly. Test script: --------------- interface IFoo { public function ipsum(self $foo); } class Bar implements IFoo { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } class Baz extends Bar { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } class Lol implements IFoo { public function ipsum(self $foo) { echo __METHOD__, "(", get_class($foo), ")\n"; } } # test objects $bar = new Bar(); $baz = new Baz(); $lol = new Lol(); # lets try everything # IFoo::ipsum(self $foo) # Bar::ipsum(self $foo) $bar->ipsum($bar); # Bar::ipsum(Bar) $bar->ipsum($baz); # Bar::ipsum(Baz) $bar->ipsum($lol); # Error: Bar::ipsum() extects Bar, but Lol given # Baz::ipsum(self $foo) $baz->ipsum($bar); # Error: Baz::ipsum() extects Baz, but Bar given $baz->ipsum($baz); # Baz::ipsum(Baz) $baz->ipsum($lol); # Error: Baz::ipsum() extects Baz, but Lol given # Lol::ipsum(self $foo) $lol->ipsum($bar); # Error: Lol::ipsum() extects Lol, but Bar given $lol->ipsum($baz); # Error: Lol::ipsum() extects Lol, but Baz given $lol->ipsum($lol); # Lol::ipsum(Lol) Expected result: ---------------- Bar::ipsum(Bar) Bar::ipsum(Baz) Bar::ipsum(Lol) Baz::ipsum(Bar) Baz::ipsum(Baz) Baz::ipsum(Lol) Lol::ipsum(Bar) Lol::ipsum(Baz) Lol::ipsum(Lol) Actual result: -------------- Bar::ipsum(Bar) Bar::ipsum(Baz) Catchable fatal error: Argument 1 passed to Bar::ipsum() must be an instance of Bar, instance of Lol given, called in ... and defined ... -- Edit bug report at https://bugs.php.net/bug.php?id=63659&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=63659&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=63659&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=63659&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=63659&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=63659&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=63659&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=63659&r=needscript Try newer version: https://bugs.php.net/fix.php?id=63659&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=63659&r=support Expected behavior: https://bugs.php.net/fix.php?id=63659&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=63659&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=63659&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=63659&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=63659&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=63659&r=dst IIS Stability: https://bugs.php.net/fix.php?id=63659&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=63659&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=63659&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=63659&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=63659&r=mysqlcfg