-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Override static in return types with self in final classes #17724
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
Closed
rekmixa
wants to merge
23
commits into
php:master
from
rekmixa:feature/override_static_with_self_in_final_classes
Closed
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
79e4f25
add override_static_type_with_self_in_final_class.phpt
rekmixa 4ec78c1
allow to override static return types with self in final classes
rekmixa 27f8e02
fix checking covariant on override static with self & add tests for o…
rekmixa 218d03d
change test override_static_type_with_self_in_final_class.phpt
rekmixa f2a4a2d
fix tests for overriding static with self in non-final classes
rekmixa ceb8396
fix tests for overriding static with self in non-final classes
rekmixa 7fe477d
#17725 add more tests
6b3ca17
#17725 change way to checking availability to replace static with sel…
rekmixa 31c53e4
#17725 add more tests for union types
rekmixa baa7b49
#17725 fix checking inheritance while replacing static with self in f…
rekmixa 1d353f8
#17725 fix checking inheritance while replacing static with self in f…
rekmixa 9369f53
#17725 add additional check for mask MAY_BE_STATIC
rekmixa 8b5f894
#17725 optimize getting proto_type full mask in zend_is_class_subtype…
rekmixa 573b8de
#17725 add brackets
rekmixa 2f4bbcb
#17725 remove unnecessary tests & change test descriptions & move tes…
rekmixa 8740b58
#17725 change tests & change comparing instance of while checking abi…
25184ce
#17725 fix test override_static_type_with_self_in_final_class_with_un…
a77482d
#17725 rollback moving ZEND_TYPE_FULL_MASK to variable
a957dbf
#17725 remove redundand checking for is_intersection & move checking …
1b95868
#17725 change checking ability to replace static with self & update t…
rekmixa 66df47f
#17725 remove unlinked_instanceof
rekmixa de34c3e
#17725 update comment
rekmixa 1dc2def
#17725 remove redundant whitespace change
rekmixa 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
20 changes: 20 additions & 0 deletions
20
...iance/override_static_with_self/override_another_type_in_final_class_with_union_type.phpt
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,20 @@ | ||
--TEST-- | ||
Overriding return type with type that is not in the interface in final class with union types | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): array { return []; } | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): array must be compatible with A::methodScalar1(): static|bool in %s on line %d |
20 changes: 20 additions & 0 deletions
20
...nce/override_static_with_self/override_another_type_in_final_class_with_union_type_2.phpt
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,20 @@ | ||
--TEST-- | ||
Overriding static with self and add a type that is not in the interface in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): self|array { return []; } | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): B|array must be compatible with A::methodScalar1(): static|bool in %s on line %d |
25 changes: 25 additions & 0 deletions
25
...nce/override_static_with_self/override_another_type_in_final_class_with_union_type_3.phpt
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,25 @@ | ||
--TEST-- | ||
Override static with another implementation of interface in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): C { return new C(); } | ||
} | ||
|
||
final class C implements A | ||
{ | ||
public function methodScalar1(): self { return $this; } | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): C must be compatible with A::methodScalar1(): static|bool in %s on line %d |
25 changes: 25 additions & 0 deletions
25
...nce/override_static_with_self/override_another_type_in_final_class_with_union_type_4.phpt
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,25 @@ | ||
--TEST-- | ||
Override static with another implementation of interface and add a type that is not in the interface in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): C|array { return []; } | ||
} | ||
|
||
final class C implements A | ||
{ | ||
public function methodScalar1(): self { return $this; } | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): C|array must be compatible with A::methodScalar1(): static|bool in %s on line %d |
24 changes: 24 additions & 0 deletions
24
...nce/override_static_with_self/override_another_type_in_final_class_with_union_type_5.phpt
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,24 @@ | ||
--TEST-- | ||
Override static with class that is even not an implementation of interface in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): C { return new C(); } | ||
} | ||
|
||
final class C | ||
{ | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): C must be compatible with A::methodScalar1(): static|bool in %s on line %d |
24 changes: 24 additions & 0 deletions
24
...nce/override_static_with_self/override_another_type_in_final_class_with_union_type_6.phpt
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,24 @@ | ||
--TEST-- | ||
Override static with class that is even not an implementation of interface and add a type that is not in the interface in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): C|array { return []; } | ||
} | ||
|
||
final class C | ||
{ | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of B::methodScalar1(): C|array must be compatible with A::methodScalar1(): static|bool in %s on line %d |
85 changes: 85 additions & 0 deletions
85
...ons/variance/override_static_with_self/override_static_type_with_self_in_final_class.phpt
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,85 @@ | ||
--TEST-- | ||
Overriding static return types with self in final class | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function method1(): static; | ||
} | ||
|
||
abstract class B | ||
{ | ||
abstract public function method2(): static; | ||
} | ||
|
||
trait C | ||
{ | ||
abstract public function method3(): static; | ||
} | ||
|
||
final class Foo extends B implements A | ||
{ | ||
use C; | ||
|
||
public function method1(): self | ||
{ | ||
return $this; | ||
} | ||
|
||
public function method2(): self | ||
{ | ||
return $this; | ||
} | ||
|
||
public function method3(): self | ||
{ | ||
return $this; | ||
} | ||
} | ||
|
||
final class Bar extends B implements A | ||
{ | ||
use C; | ||
|
||
public function method1(): Bar | ||
{ | ||
return $this; | ||
} | ||
|
||
public function method2(): Bar | ||
{ | ||
return $this; | ||
} | ||
|
||
public function method3(): Bar | ||
{ | ||
return $this; | ||
} | ||
} | ||
|
||
$foo = new Foo(); | ||
|
||
var_dump($foo->method1()); | ||
var_dump($foo->method2()); | ||
var_dump($foo->method3()); | ||
|
||
$bar = new Bar(); | ||
|
||
var_dump($bar->method1()); | ||
var_dump($bar->method2()); | ||
var_dump($bar->method3()); | ||
?> | ||
--EXPECTF-- | ||
object(Foo)#1 (0) { | ||
} | ||
object(Foo)#1 (0) { | ||
} | ||
object(Foo)#1 (0) { | ||
} | ||
object(Bar)#2 (0) { | ||
} | ||
object(Bar)#2 (0) { | ||
} | ||
object(Bar)#2 (0) { | ||
} |
151 changes: 151 additions & 0 deletions
151
...ride_static_with_self/override_static_type_with_self_in_final_class_with_union_types.phpt
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,151 @@ | ||
--TEST-- | ||
Overriding static return types with self in final class with union types | ||
--FILE-- | ||
<?php | ||
|
||
interface A | ||
{ | ||
public function methodScalar1(): static|bool; | ||
public function methodScalar2(): static|bool; | ||
public function methodScalar3(): static|false; | ||
public function methodScalar4(): static|true; | ||
public function methodScalar5(): static|bool; | ||
public function methodScalar6(): static|bool; | ||
public function methodScalar7(): static|string; | ||
public function methodScalar8(): static|string; | ||
public function methodScalar9(): static|string; | ||
public function methodScalar10(): static|int; | ||
public function methodScalar11(): static|int; | ||
public function methodScalar12(): static|int; | ||
public function methodScalar13(): static|float; | ||
public function methodScalar14(): static|float; | ||
public function methodScalar15(): static|float; | ||
public function methodIterable1(): static|iterable; | ||
public function methodIterable2(): static|iterable; | ||
public function methodIterable3(): static|array; | ||
public function methodObject1(): static|A; | ||
public function methodObject2(): static|B; | ||
public function methodObject3(): static|C; | ||
public function methodObject4(): static|self; | ||
public function methodObject5(): static|self; | ||
public function methodNullable1(): ?static; | ||
public function methodNullable2(): ?static; | ||
public function methodNullable3(): static|null; | ||
public function methodNullable4(): static|null; | ||
public function methodNullable5(): null; | ||
} | ||
|
||
final class B implements A | ||
{ | ||
public function methodScalar1(): self|false { return $this; } | ||
public function methodScalar2(): self|true { return $this; } | ||
public function methodScalar3(): false { return false; } | ||
public function methodScalar4(): true { return true; } | ||
public function methodScalar5(): bool { return false; } | ||
public function methodScalar6(): self { return $this; } | ||
public function methodScalar7(): self|string { return $this; } | ||
public function methodScalar8(): string { return ''; } | ||
public function methodScalar9(): self { return $this; } | ||
public function methodScalar10(): self|int { return $this; } | ||
public function methodScalar11(): int { return 0; } | ||
public function methodScalar12(): self { return $this; } | ||
public function methodScalar13(): self|float { return $this; } | ||
public function methodScalar14(): float { return 0.0; } | ||
public function methodScalar15(): self { return $this; } | ||
public function methodIterable1(): self|iterable { return $this; } | ||
public function methodIterable2(): self|array { return $this; } | ||
public function methodIterable3(): array { return []; } | ||
public function methodObject1(): self { return $this; } | ||
public function methodObject2(): B { return $this; } | ||
public function methodObject3(): C { return new C(); } | ||
public function methodObject4(): self { return $this; } | ||
public function methodObject5(): B { return $this; } | ||
public function methodNullable1(): ?static { return $this; } | ||
public function methodNullable2(): ?static { return null; } | ||
public function methodNullable3(): static|null { return null; } | ||
public function methodNullable4(): static|null { return $this; } | ||
public function methodNullable5(): null { return null; } | ||
} | ||
|
||
class C | ||
{ | ||
} | ||
|
||
$b = new B(); | ||
var_dump($b->methodScalar1()); | ||
var_dump($b->methodScalar2()); | ||
var_dump($b->methodScalar3()); | ||
var_dump($b->methodScalar4()); | ||
var_dump($b->methodScalar5()); | ||
var_dump($b->methodScalar6()); | ||
var_dump($b->methodScalar7()); | ||
var_dump($b->methodScalar8()); | ||
var_dump($b->methodScalar9()); | ||
var_dump($b->methodScalar10()); | ||
var_dump($b->methodScalar11()); | ||
var_dump($b->methodScalar12()); | ||
var_dump($b->methodScalar13()); | ||
var_dump($b->methodScalar14()); | ||
var_dump($b->methodScalar15()); | ||
var_dump($b->methodIterable1()); | ||
var_dump($b->methodIterable2()); | ||
var_dump($b->methodIterable3()); | ||
var_dump($b->methodObject1()); | ||
var_dump($b->methodObject2()); | ||
var_dump($b->methodObject3()); | ||
var_dump($b->methodObject4()); | ||
var_dump($b->methodObject5()); | ||
var_dump($b->methodNullable1()); | ||
var_dump($b->methodNullable2()); | ||
var_dump($b->methodNullable3()); | ||
var_dump($b->methodNullable4()); | ||
var_dump($b->methodNullable5()); | ||
?> | ||
--EXPECTF-- | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
bool(false) | ||
bool(true) | ||
bool(false) | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
string(0) "" | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
int(0) | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
float(0) | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
array(0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
object(C)#2 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
object(B)#1 (0) { | ||
} | ||
NULL | ||
NULL | ||
object(B)#1 (0) { | ||
} | ||
NULL |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.