Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3b62d66

Browse files
authored
Implement constants in traits (#8888)
RFC: https://wiki.php.net/rfc/constants_in_traits
1 parent a191710 commit 3b62d66

29 files changed

+722
-47
lines changed

‎Zend/Optimizer/pass1.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
164164
if (ce) {
165165
zend_class_constant *cc = zend_hash_find_ptr(
166166
&ce->constants_table, Z_STR(ZEND_OP2_LITERAL(opline)));
167-
if (cc && (ZEND_CLASS_CONST_FLAGS(cc) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
167+
if (cc && (ZEND_CLASS_CONST_FLAGS(cc) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC&& !(ce->ce_flags&ZEND_ACC_TRAIT)) {
168168
zval *c = &cc->value;
169169
if (Z_TYPE_P(c) == IS_CONSTANT_AST) {
170170
zend_ast *ast = Z_ASTVAL_P(c);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Enum can use traits having constants
3+
--FILE--
4+
<?php
5+
6+
trait Rectangle {
7+
private const MESSAGE_RECTANGLE = 'Rectangle';
8+
9+
public function shape(): string {
10+
return self::MESSAGE_RECTANGLE;
11+
}
12+
}
13+
14+
enum Suit {
15+
use Rectangle;
16+
17+
case Hearts;
18+
case Diamonds;
19+
case Clubs;
20+
case Spades;
21+
}
22+
23+
echo Suit::Hearts->shape() . PHP_EOL;
24+
echo Suit::Diamonds->shape() . PHP_EOL;
25+
echo Suit::Clubs->shape() . PHP_EOL;
26+
echo Suit::Spades->shape() . PHP_EOL;
27+
28+
?>
29+
--EXPECT--
30+
Rectangle
31+
Rectangle
32+
Rectangle
33+
Rectangle

‎Zend/tests/traits/constant_001.phpt‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Trying to access a constant on Trait via a Class
3+
--FILE--
4+
<?php
5+
6+
trait Foo {
7+
public const PUBLIC = 'public';
8+
protected const PROTECTED = 'protected';
9+
private const PRIVATE = 'private';
10+
11+
public function f1(): void {
12+
echo self::PUBLIC, ' via self', PHP_EOL;
13+
echo static::PUBLIC, ' via static', PHP_EOL;
14+
echo $this::PUBLIC, ' via $this', PHP_EOL;
15+
}
16+
}
17+
18+
class Base {
19+
use Foo;
20+
21+
public function f2(): void {
22+
echo self::PRIVATE, ' via self', PHP_EOL;
23+
echo static::PRIVATE, ' via static', PHP_EOL;
24+
}
25+
}
26+
27+
class Derived extends Base {
28+
public function f3(): void {
29+
echo self::PROTECTED, ' via self', PHP_EOL;
30+
echo static::PROTECTED, ' via static', PHP_EOL;
31+
echo parent::PROTECTED, ' via parent', PHP_EOL;
32+
}
33+
}
34+
35+
echo Base::PUBLIC, ' via class name', PHP_EOL;
36+
echo (new Base)::PUBLIC, ' via object', PHP_EOL;
37+
(new Base)->f1();
38+
(new Base)->f2();
39+
echo Derived::PUBLIC, ' via derived class name', PHP_EOL;
40+
echo (new Derived)::PUBLIC, ' via derived class object', PHP_EOL;
41+
(new Derived)->f3();
42+
?>
43+
--EXPECTF--
44+
public via class name
45+
public via object
46+
public via self
47+
public via static
48+
public via $this
49+
private via self
50+
private via static
51+
public via derived class name
52+
public via derived class object
53+
protected via self
54+
protected via static
55+
protected via parent

‎Zend/tests/traits/constant_002.phpt‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Defining a constant in both trait and its composing class with the same name, visibility, finality and value is allowed
3+
--FILE--
4+
<?php
5+
6+
trait TestTrait1 {
7+
public const A = 42;
8+
}
9+
10+
trait TestTrait2 {
11+
public const A = 42;
12+
}
13+
14+
trait TestTrait3 {
15+
use TestTrait2;
16+
public const A = 42;
17+
}
18+
19+
class ComposingClass1 {
20+
use TestTrait1;
21+
use TestTrait2;
22+
}
23+
24+
class ComposingClass2 {
25+
use TestTrait1;
26+
use TestTrait3;
27+
}
28+
29+
class ComposingClass3 {
30+
use TestTrait1;
31+
use TestTrait3;
32+
public const A = 42;
33+
}
34+
35+
echo ComposingClass1::A, PHP_EOL;
36+
echo ComposingClass2::A, PHP_EOL;
37+
echo ComposingClass3::A, PHP_EOL;
38+
?>
39+
--EXPECTF--
40+
42
41+
42
42+
42

‎Zend/tests/traits/constant_003.phpt‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Non-final Constants in traits can be overridden in derived classes
3+
--FILE--
4+
<?php
5+
6+
trait Foo {
7+
public const A = 123;
8+
}
9+
10+
class Base {
11+
use Foo;
12+
}
13+
14+
class Derived extends Base {
15+
public const A = 456;
16+
}
17+
18+
echo Derived::A, PHP_EOL;
19+
?>
20+
--EXPECTF--
21+
456

‎Zend/tests/traits/constant_004.phpt‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Trying to access a constant on trait via the name of trait causes a Fatal error
3+
--FILE--
4+
<?php
5+
trait Foo {
6+
const A = 42;
7+
}
8+
9+
class Bar {
10+
use Foo;
11+
}
12+
13+
echo Foo::A, PHP_EOL;
14+
?>
15+
--EXPECTF--
16+
Fatal error: Uncaught Error: Cannot access trait constant Foo::A directly in %s:%d
17+
Stack trace:
18+
#0 {main}
19+
thrown in %s on line %d

‎Zend/tests/traits/constant_005.phpt‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Conflicting constants in composing classes with different visibility modifiers should result in a fatal error, since this indicates that the code is incompatible.
3+
--FILE--
4+
<?php
5+
6+
trait TestTrait {
7+
public const Constant = 42;
8+
}
9+
10+
echo "PRE-CLASS-GUARD\n";
11+
12+
class ComposingClass {
13+
use TestTrait;
14+
private const Constant = 42;
15+
}
16+
17+
echo "POST-CLASS-GUARD\n";
18+
?>
19+
--EXPECTF--
20+
PRE-CLASS-GUARD
21+
22+
Fatal error: ComposingClass and TestTrait define the same constant (Constant) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

‎Zend/tests/traits/constant_006.phpt‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Conflicting constants in composing classes with different values should result in a fatal error, since this indicates that the code is incompatible.
3+
--FILE--
4+
<?php
5+
6+
trait TestTrait {
7+
public const Constant = 123;
8+
}
9+
10+
echo "PRE-CLASS-GUARD\n";
11+
12+
class ComposingClass {
13+
use TestTrait;
14+
public const Constant = 456;
15+
}
16+
17+
echo "POST-CLASS-GUARD\n";
18+
?>
19+
--EXPECTF--
20+
PRE-CLASS-GUARD
21+
22+
Fatal error: ComposingClass and TestTrait define the same constant (Constant) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

‎Zend/tests/traits/constant_007.phpt‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Conflicting constants in composing classes with different finality should result in a fatal error, since this indicates that the code is incompatible.
3+
--FILE--
4+
<?php
5+
6+
trait TestTrait {
7+
public const Constant = 42;
8+
}
9+
10+
echo "PRE-CLASS-GUARD\n";
11+
12+
class ComposingClass {
13+
use TestTrait;
14+
public final const Constant = 42;
15+
}
16+
17+
echo "POST-CLASS-GUARD\n";
18+
?>
19+
--EXPECTF--
20+
PRE-CLASS-GUARD
21+
22+
Fatal error: ComposingClass and TestTrait define the same constant (Constant) in the composition of ComposingClass. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

‎Zend/tests/traits/constant_008.phpt‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Conflicting constants in another traits in same composing classes with different visibility modifiers should result in a fatal error, since this indicates that the code is incompatible.
3+
--FILE--
4+
<?php
5+
6+
trait Trait1 {
7+
public const Constant = 42;
8+
}
9+
10+
trait Trait2 {
11+
private const Constant = 42;
12+
}
13+
14+
echo "PRE-CLASS-GUARD\n";
15+
16+
class TraitsTest {
17+
use Trait1;
18+
use Trait2;
19+
}
20+
21+
echo "POST-CLASS-GUARD\n";
22+
?>
23+
--EXPECTF--
24+
PRE-CLASS-GUARD
25+
26+
Fatal error: Trait1 and Trait2 define the same constant (Constant) in the composition of TraitsTest. However, the definition differs and is considered incompatible. Class was composed in %s on line %d

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /