Possible Bug with Interface, Constants and Inheritance

php.internals

(Karl Pflästerer)

10 years ago
Hi, I'm not sure if it's a bug or not. Consider these simple script: <?php interface I1 { const C1 = '';} class C3 implements I1 { const C1 = 'c2';} $c3 = new C3; var_dump($c3::C1); That gives a fatal error with mod_php and PHP CLI if I call the CLI version with a file name: PHP Fatal error: Cannot inherit previously-inherited or override constant C1 from interface I1 in If I use the CLI and enter the code directly it works: ~> php -v PHP 7.0.7 (cli) (built: May 27 2016 15:22:32) ( NTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies ~> php -a -ddispplay_errors=On Interactive shell php > interface I1 { const C1 = '';} php > class C3 implements I1 { const C1 = 'c2';} php > $c3 = new C3; php > var_dump($c3::C1); string(2) "c2" Is this always the correkt behaviour? KP

Andreas Heigl

10 years ago
Am 27.06.16 um 15:01 schrieb Karl Pflästerer:
> interface I1 { const C1 = '';} > class C3 implements I1 { const C1 = 'c2';} > $c3 = new C3; > var_dump($c3::C1);
According to https://3v4l.org/jIcs6 it looks like that's intended behaviour ;) Cheers Andreas
-- ,,, (o o) +---------------------------------------------------------ooO-(_)-Ooo-+ | Andreas Heigl | | mailto:andreas@heigl.org N 50°22'59.5" E 08°23'58" | | http://andreas.heigl.org http://hei.gl/wiFKy7 | +---------------------------------------------------------------------+ | http://hei.gl/root-ca | +---------------------------------------------------------------------+

(Karl Pflästerer)

10 years ago
Andreas Heigl <andreas@heigl.org> writes:
> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >> interface I1 { const C1 = '';} >> class C3 implements I1 { const C1 = 'c2';} >> $c3 = new C3; >> var_dump($c3::C1); > > According to https://3v4l.org/jIcs6 it looks like that's intended > behaviour ;)
But why does it work in the CLI if I write the code (instead of using a script)? That's my question. KP

Christoph Becker

10 years ago
On 27.06.2016 at 15:28, (Karl Pflästerer ) wrote:
> Andreas Heigl <andreas@heigl.org> writes: > >> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >>> interface I1 { const C1 = '';} >>> class C3 implements I1 { const C1 = 'c2';} >>> $c3 = new C3; >>> var_dump($c3::C1); >> >> According to https://3v4l.org/jIcs6 it looks like that's intended >> behaviour ;) > > But why does it work in the CLI if I write the code (instead of using a > script)? That's my question.
Have you tried with and without OPcache?
-- Christoph M. Becker

(Karl Pflästerer)

10 years ago
Am 27.06.16 um 17:04 schrieb Christoph Becker:
> On 27.06.2016 at 15:28, (Karl Pflästerer ) wrote: > >> Andreas Heigl <andreas@heigl.org> writes: >> >>> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >>>> interface I1 { const C1 = '';} >>>> class C3 implements I1 { const C1 = 'c2';} >>>> $c3 = new C3; >>>> var_dump($c3::C1); >>> >>> According to https://3v4l.org/jIcs6 it looks like that's intended >>> behaviour ;) >> >> But why does it work in the CLI if I write the code (instead of using a >> script)? That's my question. > > Have you tried with and without OPcache? >
There is no opcache in use. (Don't know if the message can be seen on the list; I only could read it in my mailbox; I could'nt see it in Gmane). KP

Andreas Heigl

10 years ago
Am 27.06.16 um 15:28 schrieb Karl Pflästerer:
> Andreas Heigl <andreas@heigl.org> writes: > >> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >>> interface I1 { const C1 = '';} >>> class C3 implements I1 { const C1 = 'c2';} >>> $c3 = new C3; >>> var_dump($c3::C1); >> >> According to https://3v4l.org/jIcs6 it looks like that's intended >> behaviour ;) > > But why does it work in the CLI if I write the code (instead of using a > script)? That's my question.
It doesn't. At least not on my machine. This is the output I get: $ php -v PHP 7.1.0alpha2 (cli) (built: Jun 24 2016 13:50:28) ( NTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies $ php -a Interactive shell php > interface I1 { const C1 = '';} php > class C3 implements I1 { const C1 = 'c2';} PHP Fatal error: Cannot inherit previously-inherited or override constant C1 from interface I1 in php shell code on line 1 Fatal error: Cannot inherit previously-inherited or override constant C1 from interface I1 in php shell code on line 1 php > $c3 = new C3; php > var_dump($c3::C1); string(2) "c2" php > So it crashes with a fatal error when Implementing the interface. It'S interesting though that the script allows me to instantiate the class nonetheless. That's right. Perhaps some C-Guru can shed some light here? Cheers Andreas
-- ,,, (o o) +---------------------------------------------------------ooO-(_)-Ooo-+ | Andreas Heigl | | mailto:andreas@heigl.org N 50°22'59.5" E 08°23'58" | | http://andreas.heigl.org http://hei.gl/wiFKy7 | +---------------------------------------------------------------------+ | http://hei.gl/root-ca | +---------------------------------------------------------------------+

Bishop Bettini

10 years ago
On Mon, Jun 27, 2016 at 11:31 AM, Andreas Heigl <andreas@heigl.org> wrote:
> Am 27.06.16 um 15:28 schrieb Karl Pflästerer: > > Andreas Heigl <andreas@heigl.org> writes: > > > >> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: > >>> interface I1 { const C1 = '';} > >>> class C3 implements I1 { const C1 = 'c2';} > >>> $c3 = new C3; > >>> var_dump($c3::C1); > >> > >> According to https://3v4l.org/jIcs6 it looks like that's intended > >> behaviour ;) > > > > But why does it work in the CLI if I write the code (instead of using a > > script)? That's my question. > > It doesn't. At least not on my machine. This is the output I get: > > $ php -v > PHP 7.1.0alpha2 (cli) (built: Jun 24 2016 13:50:28) ( NTS ) > Copyright (c) 1997-2016 The PHP Group > Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies >
Technically, this is a different version than reported. Nonetheless, on the same version my REPL complains as well, I suspect because the original report misspelled the INI setting ("-ddispplay_errors=On", notice the double "p"): $ php -v PHP 7.0.7 (cli) (built: May 28 2016 08:26:36) ( NTS ) Copyright (c) 1997-2016 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans $ php -a Interactive shell php > interface I1 { const C1 = ''; } php > class C3 implements I1 { const C1 = 'c2'; } PHP Fatal error: Cannot inherit previously-inherited or override constant C1 from interface I1 in php shell code on line 1 PHP Stack trace: PHP 1. {main}() php shell code:0
> So it crashes with a fatal error when Implementing the interface. It'S > interesting though that the script allows me to instantiate the class > nonetheless. That's right. >
Under normal interpretive operation, the Fatal terminates the script. But in the case of the REPL command line, those are swallowed up and you can keep going. Same as like: php > foo(); PHP Warning: Uncaught Error: Call to undefined function foo() in php shell code:1 Stack trace: #0 {main} thrown in php shell code on line 1 PHP Stack trace: PHP 1. {main}() php shell code:0 php > echo 'hi'; hi I'm not seeing any bugs here. bishop

Andreas Heigl

10 years ago
Am 27.06.16 um 17:41 schrieb Bishop Bettini:
> On Mon, Jun 27, 2016 at 11:31 AM, Andreas Heigl <andreas@heigl.org> wrote: > >> Am 27.06.16 um 15:28 schrieb Karl Pflästerer: >>> Andreas Heigl <andreas@heigl.org> writes: >>> >>>> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >>>>> interface I1 { const C1 = '';} >>>>> class C3 implements I1 { const C1 = 'c2';} >>>>> $c3 = new C3; >>>>> var_dump($c3::C1); >>>> >>>> According to https://3v4l.org/jIcs6 it looks like that's intended >>>> behaviour ;) >>> >>> But why does it work in the CLI if I write the code (instead of using a >>> script)? That's my question. >> >> It doesn't. At least not on my machine. This is the output I get: >> >> $ php -v >> PHP 7.1.0alpha2 (cli) (built: Jun 24 2016 13:50:28) ( NTS ) >> Copyright (c) 1997-2016 The PHP Group >> Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies >> > > Technically, this is a different version than reported. Nonetheless, on the > same version my REPL complains as well, I suspect because the original > report misspelled the INI setting ("-ddispplay_errors=On", notice the > double "p"): > > $ php -v > PHP 7.0.7 (cli) (built: May 28 2016 08:26:36) ( NTS ) > Copyright (c) 1997-2016 The PHP Group > Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies > with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend > Technologies > with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans > > $ php -a > Interactive shell > > php > interface I1 { const C1 = ''; } > php > class C3 implements I1 { const C1 = 'c2'; } > PHP Fatal error: Cannot inherit previously-inherited or override constant > C1 from interface I1 in php shell code on line 1 > PHP Stack trace: > PHP 1. {main}() php shell code:0 > > > >> So it crashes with a fatal error when Implementing the interface. It'S >> interesting though that the script allows me to instantiate the class >> nonetheless. That's right. >> > > Under normal interpretive operation, the Fatal terminates the script. But > in the case of the REPL command line, those are swallowed up and you can > keep going. Same as like: > > php > foo(); > PHP Warning: Uncaught Error: Call to undefined function foo() in php shell > code:1 > Stack trace: > #0 {main} > thrown in php shell code on line 1 > PHP Stack trace: > PHP 1. {main}() php shell code:0 > php > echo 'hi'; > hi > > I'm not seeing any bugs here.
Thanks for the info. What I find strange is that I can instantiate the class "C3" even though the declaration of the class is broken. I wouldn't say it's a bug, but interesting. Cheers Andreas
-- ,,, (o o) +---------------------------------------------------------ooO-(_)-Ooo-+ | Andreas Heigl | | mailto:andreas@heigl.org N 50°22'59.5" E 08°23'58" | | http://andreas.heigl.org http://hei.gl/wiFKy7 | +---------------------------------------------------------------------+ | http://hei.gl/root-ca | +---------------------------------------------------------------------+

(Karl Pflästerer)

10 years ago
Bishop Bettini <bishop@php.net> writes:
> On Mon, Jun 27, 2016 at 11:31 AM, Andreas Heigl <andreas@heigl.org> wrote: > >> Am 27.06.16 um 15:28 schrieb Karl Pflästerer: >> > Andreas Heigl <andreas@heigl.org> writes: >> > >> >> Am 27.06.16 um 15:01 schrieb Karl Pflästerer: >> >>> interface I1 { const C1 = '';} >> >>> class C3 implements I1 { const C1 = 'c2';} >> >>> $c3 = new C3; >> >>> var_dump($c3::C1); >> >> >> >> According to https://3v4l.org/jIcs6 it looks like that's intended >> >> behaviour ;) >> > >> > But why does it work in the CLI if I write the code (instead of using a >> > script)? That's my question. >> >> It doesn't. At least not on my machine. This is the output I get: >> >> $ php -v >> PHP 7.1.0alpha2 (cli) (built: Jun 24 2016 13:50:28) ( NTS ) >> Copyright (c) 1997-2016 The PHP Group >> Zend Engine v3.1.0-dev, Copyright (c) 1998-2016 Zend Technologies >> > > Technically, this is a different version than reported. Nonetheless, on the > same version my REPL complains as well, I suspect because the original > report misspelled the INI setting ("-ddispplay_errors=On", notice the > double "p"):
[...] Thanks; that explains why I didn't see the error message.
> > Under normal interpretive operation, the Fatal terminates the script. But > in the case of the REPL command line, those are swallowed up and you can > keep going. Same as like: >
And that explains why I was able to instantiate a broken class (with a overriden constant). So no bug but an interesting edge case. KP

Rowan Collins

10 years ago
On 27/06/2016 16:31, Andreas Heigl wrote:
> So it crashes with a fatal error when Implementing the interface. It'S > interesting though that the script allows me to instantiate the class > nonetheless.
It sounds to me like the ability of the interactive shell to catch fatal errors and continue allows you to execute code with the engine in a bogus state. It's possible to do all sorts of wacky things that way: php > class Bogus implements NonExistent {} PHP Fatal error: Interface 'NonExistent' not found in php shell code on line 1 Fatal error: Interface 'NonExistent' not found in php shell code on line 1 php > $b = new Bogus; php > var_dump($b); object(Bogus)#1 (0) { } php > var_dump($b instanceOf NonExistent); bool(false) php > var_dump($b instanceOf Bogus); bool(true)
> PHP Fatal error: Cannot inherit previously-inherited or override > constant C1 from interface I1 in
Can I just say this is a positively hideous error message. I can't actually figure out how to parse its grammar: is it (inherit previously-inherited) OR (override)? If so, what does "inherit previously-inherited" mean?

Bishop Bettini

10 years ago
On Mon, Jun 27, 2016 at 11:44 AM, Rowan Collins <rowan.collins@gmail.com> wrote:
> > PHP Fatal error: Cannot inherit previously-inherited or override >> constant C1 from interface I1 in >> > > Can I just say this is a positively hideous error message. I can't > actually figure out how to parse its grammar: is it (inherit > previously-inherited) OR (override)? If so, what does "inherit > previously-inherited" mean? > >
+1 on hideous. From this test <https://github.com/php/php-src/blob/master/Zend/tests/errmsg_025.phpt>, I believe "previously-inherited" refers to this situation: interface I1 { const BAR = 242; } interface I2 { const BAR = 242; } class Foo implements I1, I2 { };