-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Feature/class name as scalar #256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword | ||
--FILE-- | ||
<?php | ||
|
||
namespace Foo\Bar { | ||
class One { | ||
// compile time constants | ||
const A = self::class; | ||
const B = Two::class; | ||
} | ||
class Two extends One { | ||
public static function run() { | ||
var_dump(self::class); // self compile time lookup | ||
var_dump(static::class); // runtime lookup | ||
var_dump(parent::class); // runtime lookup | ||
var_dump(Baz::class); // default compile time lookup | ||
} | ||
} | ||
class Three extends Two { | ||
// compile time static lookups | ||
public static function checkCompileTime( | ||
$one = self::class, | ||
$two = Baz::class, | ||
$three = One::A, | ||
$four = self::B | ||
) { | ||
var_dump($one, $two, $three, $four); | ||
} | ||
} | ||
echo "In NS\n"; | ||
var_dump(Moo::CLASS); // resolve in namespace | ||
} | ||
|
||
namespace { | ||
use Bee\Bop as Moo, | ||
Foo\Bar\One; | ||
echo "Top\n"; | ||
var_dump(One::class); // resolve from use | ||
var_dump(Boo::class); // resolve in global namespace | ||
var_dump(Moo::CLASS); // resolve from use as | ||
var_dump(\Moo::Class); // resolve fully qualified | ||
$class = One::class; // assign class as scalar to var | ||
$x = new $class; // create new class from original scalar assignment | ||
var_dump($x); | ||
Foo\Bar\Two::run(); // resolve runtime lookups | ||
echo "Parent\n"; | ||
Foo\Bar\Three::run(); // resolve runtime lookups with inheritance | ||
echo "Compile Check\n"; | ||
Foo\Bar\Three::checkCompileTime(); | ||
} | ||
|
||
?> | ||
--EXPECTF-- | ||
In NS | ||
string(11) "Foo\Bar\Moo" | ||
Top | ||
string(11) "Foo\Bar\One" | ||
string(3) "Boo" | ||
string(7) "Bee\Bop" | ||
string(3) "Moo" | ||
object(Foo\Bar\One)#1 (0) { | ||
} | ||
string(11) "Foo\Bar\Two" | ||
string(11) "Foo\Bar\Two" | ||
string(11) "Foo\Bar\One" | ||
string(11) "Foo\Bar\Baz" | ||
Parent | ||
string(11) "Foo\Bar\Two" | ||
string(13) "Foo\Bar\Three" | ||
string(11) "Foo\Bar\One" | ||
string(11) "Foo\Bar\Baz" | ||
Compile Check | ||
string(13) "Foo\Bar\Three" | ||
string(11) "Foo\Bar\Baz" | ||
string(11) "Foo\Bar\One" | ||
string(11) "Foo\Bar\Two" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using static in class constant | ||
--FILE-- | ||
<?php | ||
|
||
namespace Foo\Bar { | ||
class One { | ||
const Baz = static::class; | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using parent in class constant | ||
--FILE-- | ||
<?php | ||
|
||
namespace Foo\Bar { | ||
class One { | ||
const Baz = parent::class; | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using static in method signature | ||
--FILE-- | ||
<?php | ||
|
||
namespace Foo\Bar { | ||
class One { | ||
public function baz($x = static::class) {} | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using parent in method signature | ||
--FILE-- | ||
<?php | ||
|
||
namespace Foo\Bar { | ||
class One { | ||
public function baz($x = parent::class) {} | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using static non class context | ||
--FILE-- | ||
<?php | ||
|
||
$x = static::class; | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot access static::class when no class scope is active in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--TEST-- | ||
class name as scalar from ::class keyword error using parent in non class context | ||
--FILE-- | ||
<?php | ||
|
||
$x = parent::class; | ||
|
||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot access parent::class when no class scope is active in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3567,6 +3567,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) | |
} | ||
ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value); | ||
zval_copy_ctor(&EX_T(opline->result.var).tmp_var); | ||
} else if (Z_STRLEN_P(opline->op2.zv) == sizeof("class")-1 && strcmp(Z_STRVAL_P(opline->op2.zv), "class") == 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tokens in PHP are case-insensitive, so the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This particular reference to "class" was provided from inside zend_do_resolve_class_name, so it will always be "class" and never any other variation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, you're right, didn't notice that :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I added a comment to that effect in my latest commit). Let me know if there is anything more in this patch that needs to be addressed :) Thanks again for taking the time. |
||
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */ | ||
ZVAL_STRINGL(&EX_T(opline->result.var).tmp_var, ce->name, ce->name_length, 1); | ||
} else { | ||
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv)); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is not covered by tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am adding the error tests tonight.