-
Notifications
You must be signed in to change notification settings - Fork 7.9k
RFC: Static class #14861
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
base: master
Are you sure you want to change the base?
RFC: Static class #14861
Changes from all commits
8b13efc
3ed2d03
b6d0a30
f6916fe
23d0272
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,11 @@ | ||
--TEST-- | ||
Tests that a non-static class cannot inherit from a static class | ||
--FILE-- | ||
<?php | ||
|
||
static class C {} | ||
|
||
class C2 extends C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Non-static class C2 cannot extend static class C in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Tests that a static class cannot inherit from a non-static class | ||
--FILE-- | ||
<?php | ||
|
||
class C {} | ||
|
||
static class C2 extends C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Static class C2 cannot extend non-static class C in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--TEST-- | ||
Tests that a static class can inherit from another static class | ||
--FILE-- | ||
<?php | ||
|
||
static class C { | ||
static function F() { | ||
echo 'OK'; | ||
} | ||
} | ||
|
||
static class C2 extends C {} | ||
|
||
C2::F(); | ||
?> | ||
--EXPECT-- | ||
OK |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Tests that a static class can inherit static members from a trait | ||
--FILE-- | ||
<?php | ||
|
||
trait T { | ||
static $P = 'OK'; | ||
|
||
static function F() { | ||
echo self::$P; | ||
} | ||
} | ||
|
||
static class C { | ||
use T; | ||
} | ||
|
||
C::F(); | ||
?> | ||
--EXPECT-- | ||
OK |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Tests that a static class cannot inherit an instance method from a trait | ||
--FILE-- | ||
<?php | ||
|
||
trait T { | ||
function F() {} | ||
} | ||
|
||
static class C { | ||
use T; | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Static class C cannot use trait with a non-static method T::F in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Tests that a static class cannot inherit an instance property from a trait | ||
--FILE-- | ||
<?php | ||
|
||
trait T { | ||
var $V; | ||
} | ||
|
||
static class C { | ||
use T; | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Static class C cannot use trait with a non-static property T::$V in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Tests that a static class cannot be instantiated | ||
--FILE-- | ||
<?php | ||
|
||
static class C {} | ||
|
||
new C; | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Uncaught Error: Cannot instantiate static class C in %s:%d | ||
Stack trace:%a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Tests that a static class cannot be instantiated via reflection | ||
--FILE-- | ||
<?php | ||
|
||
static class C {} | ||
|
||
new ReflectionClass('C')->newInstance(); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Uncaught Error: Cannot instantiate static class C in %s:%d | ||
Stack trace:%a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--TEST-- | ||
Tests that a static class can be marked abstract | ||
--FILE-- | ||
<?php | ||
|
||
abstract static class C { | ||
abstract static function F(); | ||
} | ||
|
||
static class C2 extends C { | ||
static function F() { | ||
echo 'OK'; | ||
} | ||
} | ||
|
||
C2::F(); | ||
?> | ||
--EXPECT-- | ||
OK |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--TEST-- | ||
Tests that an anonymous class cannot be marked static | ||
--FILE-- | ||
<?php | ||
|
||
new static class C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot use the static modifier on an anonymous class in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
--TEST-- | ||
Tests that a class can be marked static and functions as a static class | ||
--FILE-- | ||
<?php | ||
|
||
static class C { | ||
static $P = 'OK'; | ||
|
||
static function F() { | ||
echo self::$P; | ||
} | ||
} | ||
|
||
C::F(); | ||
?> | ||
--EXPECT-- | ||
OK |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--TEST-- | ||
Tests that the AST export of a static class includes the static modifier | ||
--FILE-- | ||
<?php | ||
|
||
assert(false && function () { | ||
static class C {} | ||
}); | ||
?> | ||
--EXPECTF-- | ||
%a | ||
%wstatic class C {%w} | ||
%a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--TEST-- | ||
Tests that a static class allows __callStatic() magic method | ||
--FILE-- | ||
<?php | ||
|
||
static class C { | ||
static function __callStatic(string $name, array $arguments) { | ||
echo $name; | ||
} | ||
} | ||
|
||
C::F(); | ||
?> | ||
--EXPECT-- | ||
F |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Tests that a static class cannot contain an instance method | ||
--FILE-- | ||
<?php | ||
|
||
static class C { | ||
function F() {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Class method C::F() must be declared static in a static class in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--TEST-- | ||
Tests that a static class can be marked final | ||
--FILE-- | ||
<?php | ||
|
||
final static class C {} | ||
|
||
static class C2 extends C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Class C2 cannot extend final class C in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--TEST-- | ||
Tests that an interface cannot be declared static | ||
--FILE-- | ||
<?php | ||
|
||
static interface I {} | ||
?> | ||
--EXPECTF-- | ||
Parse error: syntax error, unexpected token "interface" in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--TEST-- | ||
Tests that a static class cannot be marked readonly | ||
--FILE-- | ||
<?php | ||
|
||
static readonly class C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Cannot use the static modifier on a readonly class in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--TEST-- | ||
Tests that a static class cannot be so marked more than once | ||
--FILE-- | ||
<?php | ||
|
||
static static class C {} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Multiple static modifiers are not allowed in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--TEST-- | ||
Tests that a trait cannot be declared static | ||
--FILE-- | ||
<?php | ||
|
||
static trait T {} | ||
?> | ||
--EXPECTF-- | ||
Parse error: syntax error, unexpected token "trait" in %s on line %d |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--TEST-- | ||
Tests that a static class cannot be created via unserialize() | ||
--FILE-- | ||
<?php | ||
|
||
static class C {} | ||
|
||
unserialize('O:1:"C":0:{}'); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Uncaught Error: Cannot instantiate static class C in %s:%d | ||
Stack trace:%a |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1795,13 +1795,15 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) | |
* calling zend_merge_properties(). */ | ||
static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */ | ||
{ | ||
if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) { | ||
if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_STATIC|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) { | ||
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 is repeated often enough to where it probably makes sense to extract it into a new macro. E.g. 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. Would you perhaps agree this is best left for a separate refactoring PR? |
||
if (class_type->ce_flags & ZEND_ACC_INTERFACE) { | ||
zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name)); | ||
} else if (class_type->ce_flags & ZEND_ACC_TRAIT) { | ||
zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name)); | ||
} else if (class_type->ce_flags & ZEND_ACC_ENUM) { | ||
zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name)); | ||
} else if (class_type->ce_flags & ZEND_ACC_STATIC) { | ||
zend_throw_error(NULL, "Cannot instantiate static class %s", ZSTR_VAL(class_type->name)); | ||
} else { | ||
zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name)); | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.