-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[RFC] Implement constants in traits #8888
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--TEST-- | ||
Enum can use traits having constants | ||
--FILE-- | ||
<?php | ||
|
||
trait Rectangle { | ||
private const MESSAGE_RECTANGLE = 'Rectangle'; | ||
|
||
public function shape(): string { | ||
return self::MESSAGE_RECTANGLE; | ||
} | ||
} | ||
|
||
enum Suit { | ||
use Rectangle; | ||
|
||
case Hearts; | ||
case Diamonds; | ||
case Clubs; | ||
case Spades; | ||
} | ||
|
||
echo Suit::Hearts->shape() . PHP_EOL; | ||
echo Suit::Diamonds->shape() . PHP_EOL; | ||
echo Suit::Clubs->shape() . PHP_EOL; | ||
echo Suit::Spades->shape() . PHP_EOL; | ||
|
||
?> | ||
--EXPECT-- | ||
Rectangle | ||
Rectangle | ||
Rectangle | ||
Rectangle |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--TEST-- | ||
Trying to access a constant on Trait via a Class | ||
--FILE-- | ||
<?php | ||
|
||
trait Foo { | ||
public const PUBLIC = 'public'; | ||
protected const PROTECTED = 'protected'; | ||
private const PRIVATE = 'private'; | ||
|
||
public function f1(): void { | ||
echo self::PUBLIC, ' via self', PHP_EOL; | ||
echo static::PUBLIC, ' via static', PHP_EOL; | ||
echo $this::PUBLIC, ' via $this', PHP_EOL; | ||
} | ||
} | ||
|
||
class Base { | ||
use Foo; | ||
|
||
public function f2(): void { | ||
echo self::PRIVATE, ' via self', PHP_EOL; | ||
echo static::PRIVATE, ' via static', PHP_EOL; | ||
} | ||
} | ||
|
||
class Derived extends Base { | ||
public function f3(): void { | ||
echo self::PROTECTED, ' via self', PHP_EOL; | ||
echo static::PROTECTED, ' via static', PHP_EOL; | ||
echo parent::PROTECTED, ' via parent', PHP_EOL; | ||
} | ||
} | ||
|
||
echo Base::PUBLIC, ' via class name', PHP_EOL; | ||
echo (new Base)::PUBLIC, ' via object', PHP_EOL; | ||
(new Base)->f1(); | ||
(new Base)->f2(); | ||
echo Derived::PUBLIC, ' via derived class name', PHP_EOL; | ||
echo (new Derived)::PUBLIC, ' via derived class object', PHP_EOL; | ||
(new Derived)->f3(); | ||
?> | ||
--EXPECTF-- | ||
public via class name | ||
public via object | ||
public via self | ||
public via static | ||
public via $this | ||
private via self | ||
private via static | ||
public via derived class name | ||
public via derived class object | ||
protected via self | ||
protected via static | ||
protected via parent |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--TEST-- | ||
Defining a constant in both trait and its composing class with the same name, visibility, finality and value is allowed | ||
--FILE-- | ||
<?php | ||
|
||
trait TestTrait1 { | ||
public const A = 42; | ||
} | ||
|
||
trait TestTrait2 { | ||
public const A = 42; | ||
} | ||
|
||
trait TestTrait3 { | ||
use TestTrait2; | ||
public const A = 42; | ||
} | ||
|
||
class ComposingClass1 { | ||
use TestTrait1; | ||
use TestTrait2; | ||
} | ||
|
||
class ComposingClass2 { | ||
use TestTrait1; | ||
use TestTrait3; | ||
} | ||
|
||
class ComposingClass3 { | ||
use TestTrait1; | ||
use TestTrait3; | ||
public const A = 42; | ||
} | ||
|
||
echo ComposingClass1::A, PHP_EOL; | ||
echo ComposingClass2::A, PHP_EOL; | ||
echo ComposingClass3::A, PHP_EOL; | ||
?> | ||
--EXPECTF-- | ||
42 | ||
42 | ||
42 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
--TEST-- | ||
Non-final Constants in traits can be overridden in derived classes | ||
--FILE-- | ||
<?php | ||
|
||
trait Foo { | ||
public const A = 123; | ||
} | ||
|
||
class Base { | ||
use Foo; | ||
} | ||
|
||
class Derived extends Base { | ||
public const A = 456; | ||
} | ||
|
||
echo Derived::A, PHP_EOL; | ||
?> | ||
--EXPECTF-- | ||
456 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
--TEST-- | ||
Trying to access a constant on trait via the name of trait causes a Fatal error | ||
--FILE-- | ||
<?php | ||
trait Foo { | ||
const A = 42; | ||
} | ||
|
||
class Bar { | ||
use Foo; | ||
} | ||
|
||
echo Foo::A, PHP_EOL; | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Uncaught Error: Cannot access trait constant Foo::A directly in %s:%d | ||
Stack trace: | ||
#0 {main} | ||
thrown in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
Conflicting constants in composing classes with different visibility modifiers should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait TestTrait { | ||
public const Constant = 42; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class ComposingClass { | ||
use TestTrait; | ||
private const Constant = 42; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
Conflicting constants in composing classes with different values should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait TestTrait { | ||
public const Constant = 123; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class ComposingClass { | ||
use TestTrait; | ||
public const Constant = 456; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
Conflicting constants in composing classes with different finality should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait TestTrait { | ||
public const Constant = 42; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class ComposingClass { | ||
use TestTrait; | ||
public final const Constant = 42; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
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. | ||
--FILE-- | ||
<?php | ||
|
||
trait Trait1 { | ||
public const Constant = 42; | ||
} | ||
|
||
trait Trait2 { | ||
private const Constant = 42; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class TraitsTest { | ||
use Trait1; | ||
use Trait2; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
--TEST-- | ||
Conflicting constants in another traits in same composing classes with different values should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait Trait1 { | ||
public const Constant = 123; | ||
} | ||
|
||
trait Trait2 { | ||
public const Constant = 456; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class TraitsTest { | ||
use Trait1; | ||
use Trait2; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
--TEST-- | ||
Conflicting constants in another traits in same composing classes with different finality should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait TestTrait { | ||
public const Constant = 42; | ||
} | ||
|
||
echo "PRE-CLASS-GUARD\n"; | ||
|
||
class ComposingClass { | ||
use TestTrait; | ||
public final const Constant = 42; | ||
} | ||
|
||
echo "POST-CLASS-GUARD\n"; | ||
?> | ||
--EXPECTF-- | ||
PRE-CLASS-GUARD | ||
|
||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--TEST-- | ||
Conflicting constants in a trait and another trait using it with different visibility modifiers should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait Trait1 { | ||
public const Constant = 42; | ||
} | ||
|
||
trait Trait2 { | ||
use Trait1; | ||
private const Constant = 42; | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Trait2 and Trait1 define the same constant (Constant) in the composition of Trait2. However, the definition differs and is considered incompatible. Class was composed in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--TEST-- | ||
Conflicting constants in a trait and another trait using it with different values should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait Trait1 { | ||
public const Constant = 123; | ||
} | ||
|
||
trait Trait2 { | ||
use Trait1; | ||
public const Constant = 456; | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Trait2 and Trait1 define the same constant (Constant) in the composition of Trait2. However, the definition differs and is considered incompatible. Class was composed in %s on line %d |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--TEST-- | ||
Conflicting constants in a trait and another trait using it with different finality should result in a fatal error, since this indicates that the code is incompatible. | ||
--FILE-- | ||
<?php | ||
|
||
trait Trait1 { | ||
public const Constant = 123; | ||
} | ||
|
||
trait Trait2 { | ||
use Trait1; | ||
public const Constant = 456; | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Trait2 and Trait1 define the same constant (Constant) in the composition of Trait2. However, the definition differs and is considered incompatible. Class was composed in %s on line %d |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Commentary
This part is needed to prevent accessing trait constants directly when opcache is enabled.
The checking is usually done on the handler of ZEND_FETCH_CLASS_CONSTANT at runtime.