Skip to content

Commit 49ef6e2

Browse files
authored
RFC: Add #[Override] attribute (#9836)
* Add #[Override] attribute * Move #[\Override] tests into Zend/tests/attributes/override/ * Check `check_only` before removing `ZEND_ACC_OVERRIDE` * NEWS/UPGRADING for #[\Override]
1 parent b406f7c commit 49ef6e2

33 files changed

+591
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ PHP NEWS
99
(ilutov)
1010
. Fixed GH-11488 (Missing "Optional parameter before required" deprecation on
1111
union null type). (ilutov)
12+
. Implement the #[\Override] attribute RFC. (timwolla)
1213

1314
- DOM:
1415
. Fixed bug GH-11500 (Namespace reuse in createElementNS() generates wrong

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ PHP 8.3 UPGRADE NOTES
8383
declarations. RFC: https://wiki.php.net/rfc/typed_class_constants
8484
. Closures created from magic methods can now accept named arguments.
8585
. The final modifier may now be used when using a method from a trait.
86+
. Added the #[\Override] attribute to check that a method exists
87+
in a parent class or implemented interface.
88+
RFC: https://wiki.php.net/rfc/marking_overriden_methods
8689

8790
- Posix
8891
. posix_getrlimit() now takes an optional $res parameter to allow fetching a
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
--TEST--
2+
#[\Override]
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function i();
8+
}
9+
10+
interface II extends I {
11+
#[\Override]
12+
public function i();
13+
}
14+
15+
class P {
16+
public function p1() {}
17+
public function p2() {}
18+
public function p3() {}
19+
public function p4() {}
20+
}
21+
22+
class PP extends P {
23+
#[\Override]
24+
public function p1() {}
25+
public function p2() {}
26+
#[\Override]
27+
public function p3() {}
28+
}
29+
30+
class C extends PP implements I {
31+
#[\Override]
32+
public function i() {}
33+
#[\Override]
34+
public function p1() {}
35+
#[\Override]
36+
public function p2() {}
37+
public function p3() {}
38+
#[\Override]
39+
public function p4() {}
40+
public function c() {}
41+
}
42+
43+
echo "Done";
44+
45+
?>
46+
--EXPECT--
47+
Done
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
#[\Override]: Valid native interface.
3+
--FILE--
4+
<?php
5+
6+
class Foo implements IteratorAggregate
7+
{
8+
#[\Override]
9+
public function getIterator(): Traversable
10+
{
11+
yield from [];
12+
}
13+
}
14+
15+
echo "Done";
16+
17+
?>
18+
--EXPECT--
19+
Done
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
#[\Override]: No parent class.
3+
--FILE--
4+
<?php
5+
6+
class C
7+
{
8+
#[\Override]
9+
public function c(): void {}
10+
}
11+
12+
echo "Done";
13+
14+
?>
15+
--EXPECTF--
16+
Fatal error: C::c() has #[\Override] attribute, but no matching parent method exists in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
#[\Override]: No parent class, but child implements matching interface.
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function i(): void;
8+
}
9+
10+
class P {
11+
#[\Override]
12+
public function i(): void {}
13+
}
14+
15+
class C extends P implements I {}
16+
17+
echo "Done";
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: P::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
#[\Override]: No parent class, but child implements matching interface (2).
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
public function i(): void;
8+
}
9+
10+
class C extends P implements I {}
11+
12+
class P {
13+
#[\Override]
14+
public function i(): void {}
15+
}
16+
17+
echo "Done";
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: P::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
#[\Override]: No parent interface.
3+
--FILE--
4+
<?php
5+
6+
interface I {
7+
#[\Override]
8+
public function i(): void;
9+
}
10+
11+
interface II extends I {}
12+
13+
14+
class C implements II {
15+
public function i(): void {}
16+
}
17+
18+
class C2 implements I {
19+
public function i(): void {}
20+
}
21+
22+
echo "Done";
23+
24+
?>
25+
--EXPECTF--
26+
Fatal error: I::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
#[\Override]: On trait.
3+
--FILE--
4+
<?php
5+
6+
trait T {
7+
#[\Override]
8+
public function t(): void {}
9+
}
10+
11+
echo "Done";
12+
13+
?>
14+
--EXPECT--
15+
Done
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
#[\Override]: On used trait without parent method.
3+
--FILE--
4+
<?php
5+
6+
trait T {
7+
#[\Override]
8+
public function t(): void {}
9+
}
10+
11+
class Foo {
12+
use T;
13+
}
14+
15+
echo "Done";
16+
17+
?>
18+
--EXPECTF--
19+
Fatal error: Foo::t() has #[\Override] attribute, but no matching parent method exists in %s on line %d

0 commit comments

Comments
 (0)