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

Reply via email to