-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[RFC] Ensure correct magic methods' signatures when typed #4177
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
carusogabriel
wants to merge
1
commit into
php:master
from
carusogabriel:bug/nonsensical-return-types-69718
Closed
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--TEST-- | ||
__set first parameter should be a string when typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __set(\Countable $name, $value) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__set(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__get first parameter should be a string when typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __get(int $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__get(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__isset first parameter should be a string when typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __isset(\stdClass $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__isset(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__unset first parameter should be a string when typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __unset(array $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__unset(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__call first parameter should be a string typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __call(int $name, array $arguments) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__call(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__call second parameter should be an array when typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __call(string $name, \Arguments $arguments) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__call(): Parameter #2 ($arguments) must be of type array when declared 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,10 @@ | ||
--TEST-- | ||
__callStatic first parameter should be a string typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
static function __callStatic(int $name, array $arguments) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__callStatic(): Parameter #1 ($name) must be of type string when declared 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,10 @@ | ||
--TEST-- | ||
__callStatic second parameter should be an array typed | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
static function __callStatic(string $name, \Arguments $args) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__callStatic(): Parameter #2 ($args) must be of type array when declared 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,10 @@ | ||
--TEST-- | ||
__unserialize first parameter must be an array | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __unserialize(string $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__unserialize(): Parameter #1 ($name) must be of type array when declared 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,70 @@ | ||
--TEST-- | ||
Magic Methods inheritance rules | ||
--FILE-- | ||
<?php | ||
class ValidMagicMethods { | ||
public function __call(string $name, array $arguments): mixed {} | ||
|
||
public static function __callStatic(string $name, array $arguments): mixed {} | ||
|
||
public function __clone(): void {} | ||
|
||
public function __debugInfo(): ?array {} | ||
|
||
public function __get(string $name): mixed {} | ||
|
||
public function __invoke(mixed $arguments): mixed {} | ||
|
||
public function __isset(string $name): bool {} | ||
|
||
public function __serialize(): array {} | ||
|
||
public function __set(string $name, mixed $value): void {} | ||
|
||
public static function __set_state(array $properties): object {} | ||
|
||
public function __sleep(): array {} | ||
|
||
public function __toString(): string {} | ||
|
||
public function __unserialize(array $data): void {} | ||
|
||
public function __unset(string $name): void {} | ||
|
||
public function __wakeup(): void {} | ||
} | ||
|
||
class NarrowedReturnType extends ValidMagicMethods { | ||
public function __call(string $name, array $arguments): string|float|null {} | ||
|
||
public static function __callStatic(string $name, array $arguments): ?array {} | ||
|
||
public function __debugInfo(): array {} | ||
|
||
public function __get(string $name): int|string {} | ||
|
||
public function __invoke(mixed $arguments): object {} | ||
} | ||
|
||
class WidenedArgumentType extends NarrowedReturnType { | ||
public function __call(string|array $name, array|string $arguments): string|float|null {} | ||
|
||
public static function __callStatic(string|object $name, array|object $arguments): ?array {} | ||
|
||
public function __get(string|array $name): int|string {} | ||
|
||
public function __isset(string|bool $name): bool {} | ||
|
||
public function __set(string|bool|float $name, mixed $value): void {} | ||
|
||
public static function __set_state(string|array $properties): object {} | ||
|
||
public function __unserialize(array|string $data): void {} | ||
|
||
public function __unset(string|array $name): void {} | ||
} | ||
|
||
echo 'No problems!'; | ||
?> | ||
--EXPECT-- | ||
No problems! |
18 changes: 18 additions & 0 deletions
18
Zend/tests/magic_methods_inheritance_rules_non_trivial_01.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,18 @@ | ||
--TEST-- | ||
Magic Methods inheritance rules on a non-trivial class hierarchy | ||
--FILE-- | ||
<?php | ||
class A { | ||
public function __get(string|array $name): mixed {} // valid | ||
} | ||
|
||
class B extends A { | ||
public function __get(string|array|object $name): int {} // also valid | ||
} | ||
|
||
class C extends B { | ||
public function __get(string|array $name): int {} // this is invalid | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of C::__get(array|string $name): int must be compatible with B::__get(object|array|string $name): int in %s on line %d |
18 changes: 18 additions & 0 deletions
18
Zend/tests/magic_methods_inheritance_rules_non_trivial_02.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,18 @@ | ||
--TEST-- | ||
Magic Methods inheritance rules on a non-trivial class hierarchy | ||
--FILE-- | ||
<?php | ||
class A { | ||
public function __get(string|array $name): mixed {} // valid | ||
} | ||
|
||
class B extends A { | ||
public function __get(string|array|object $name): int {} // also valid | ||
} | ||
|
||
class C extends B { | ||
public function __get(string|array|object $name): int|float {} // this is invalid | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of C::__get(object|array|string $name): int|float must be compatible with B::__get(object|array|string $name): int 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,10 @@ | ||
--TEST-- | ||
__sleep cannot take arguments | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __sleep(string $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Method Foo::__sleep() cannot take arguments 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,10 @@ | ||
--TEST-- | ||
__wakeup cannot take arguments | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __wakeup(string $name) {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Method Foo::__wakeup() cannot take arguments 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 |
---|---|---|
@@ -1,10 +1,11 @@ | ||
--TEST-- | ||
__clone cannot declare a return type | ||
__clone can only declare void return | ||
--FILE-- | ||
<?php | ||
|
||
class Foo { | ||
function __clone() : Foo {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: %s::%s() cannot declare a return type in %s on line %d | ||
Fatal error: Foo::__clone(): Return type must be void when declared 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,10 @@ | ||
--TEST-- | ||
__set can only declare void return | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __set($name, $value) : string {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__set(): Return type must be void when declared 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,10 @@ | ||
--TEST-- | ||
__isset can only declare a boolean return type | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __isset($name) : \stdClass|bool {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__isset(): Return type must be bool when declared 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,10 @@ | ||
--TEST-- | ||
__unset can only declare void return | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
function __unset($name) : bool {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__unset(): Return type must be void when declared 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,11 @@ | ||
--TEST-- | ||
__toString can only declare string return type | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __toString(): bool { | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Declaration of Foo::__toString(): bool must be compatible with Stringable::__toString(): string 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,11 @@ | ||
--TEST-- | ||
__debugInfo can only declare array as return type | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __debugInfo(): bool { | ||
} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__debugInfo(): Return type must be ?array when declared 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,10 @@ | ||
--TEST-- | ||
__serialize can only declare array as return type | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __serialize(): \stdClass {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__serialize(): Return type must be array when declared 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,10 @@ | ||
--TEST-- | ||
__unserialize can only declare void return | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __unserialize(array $data): array {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__unserialize(): Return type must be void when declared 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,10 @@ | ||
--TEST-- | ||
__sleep can only declare return as array | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __sleep(): bool|int {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__sleep(): Return type must be array when declared 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,10 @@ | ||
--TEST-- | ||
__wakeup can only declare return void | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __wakeup(): bool {} | ||
} | ||
?> | ||
--EXPECTF-- | ||
Fatal error: Foo::__wakeup(): Return type must be void when declared 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,24 @@ | ||
--TEST-- | ||
__debugInfo can declare union return type | ||
--FILE-- | ||
<?php | ||
class UnionType { | ||
public function __debugInfo(): array|null {} | ||
} | ||
|
||
class UnionType2 { | ||
public function __debugInfo(): null|array {} | ||
} | ||
|
||
class UnionTypeOldStyle { | ||
public function __debugInfo(): ?array {} | ||
} | ||
|
||
class JustAnArray { | ||
public function __debugInfo(): array {} | ||
} | ||
|
||
echo 'No problems!'; | ||
?> | ||
--EXPECT-- | ||
No problems! |
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,29 @@ | ||
--TEST-- | ||
Some magic methods can declare mixed return type | ||
--FILE-- | ||
<?php | ||
class Foo { | ||
public function __get($name): bool {} | ||
public function __call($name, $args): string {} | ||
public static function __callStatic($name, $args): self {} | ||
public function __invoke(): self {} | ||
} | ||
|
||
class Bar { | ||
public function __get($name): string|array {} | ||
public function __call($name, $args): int|float {} | ||
public static function __callStatic($name, $args): ?object {} | ||
public function __invoke(): Foo|int {} | ||
} | ||
|
||
class Baz { | ||
public function __get($name): mixed {} | ||
public function __call($name, $args): mixed {} | ||
public static function __callStatic($name, $args): mixed {} | ||
public function __invoke(): mixed {} | ||
} | ||
|
||
echo 'Okay!'; | ||
?> | ||
--EXPECT-- | ||
Okay! |
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.