Skip to content

RFC: Add #[Override] attribute #9836

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 5 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ PHP NEWS
(ilutov)
. Fixed GH-11488 (Missing "Optional parameter before required" deprecation on
union null type). (ilutov)
. Implement the #[\Override] attribute RFC. (timwolla)

- DOM:
. Fixed bug GH-11500 (Namespace reuse in createElementNS() generates wrong
Expand Down
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ PHP 8.3 UPGRADE NOTES
declarations. RFC: https://wiki.php.net/rfc/typed_class_constants
. Closures created from magic methods can now accept named arguments.
. The final modifier may now be used when using a method from a trait.
. Added the #[\Override] attribute to check that a method exists
in a parent class or implemented interface.
RFC: https://wiki.php.net/rfc/marking_overriden_methods

- Posix
. posix_getrlimit() now takes an optional $res parameter to allow fetching a
Expand Down
47 changes: 47 additions & 0 deletions Zend/tests/attributes/override/001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--TEST--
#[\Override]
--FILE--
<?php

interface I {
public function i();
}

interface II extends I {
#[\Override]
public function i();
}

class P {
public function p1() {}
public function p2() {}
public function p3() {}
public function p4() {}
}

class PP extends P {
#[\Override]
public function p1() {}
public function p2() {}
#[\Override]
public function p3() {}
}

class C extends PP implements I {
#[\Override]
public function i() {}
#[\Override]
public function p1() {}
#[\Override]
public function p2() {}
public function p3() {}
#[\Override]
public function p4() {}
public function c() {}
}

echo "Done";

?>
--EXPECT--
Done
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: Valid native interface.
--FILE--
<?php

class Foo implements IteratorAggregate
{
#[\Override]
public function getIterator(): Traversable
{
yield from [];
}
}

echo "Done";

?>
--EXPECT--
Done
16 changes: 16 additions & 0 deletions Zend/tests/attributes/override/003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
#[\Override]: No parent class.
--FILE--
<?php

class C
{
#[\Override]
public function c(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: C::c() has #[\Override] attribute, but no matching parent method exists in %s on line %d
21 changes: 21 additions & 0 deletions Zend/tests/attributes/override/004.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
#[\Override]: No parent class, but child implements matching interface.
--FILE--
<?php

interface I {
public function i(): void;
}

class P {
#[\Override]
public function i(): void {}
}

class C extends P implements I {}

echo "Done";

?>
--EXPECTF--
Fatal error: P::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
21 changes: 21 additions & 0 deletions Zend/tests/attributes/override/005.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
#[\Override]: No parent class, but child implements matching interface (2).
--FILE--
<?php

interface I {
public function i(): void;
}

class C extends P implements I {}

class P {
#[\Override]
public function i(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: P::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
26 changes: 26 additions & 0 deletions Zend/tests/attributes/override/006.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--TEST--
#[\Override]: No parent interface.
--FILE--
<?php

interface I {
#[\Override]
public function i(): void;
}

interface II extends I {}


class C implements II {
public function i(): void {}
}

class C2 implements I {
public function i(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: I::i() has #[\Override] attribute, but no matching parent method exists in %s on line %d
15 changes: 15 additions & 0 deletions Zend/tests/attributes/override/007.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
#[\Override]: On trait.
--FILE--
<?php

trait T {
#[\Override]
public function t(): void {}
}

echo "Done";

?>
--EXPECT--
Done
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/008.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: On used trait without parent method.
--FILE--
<?php

trait T {
#[\Override]
public function t(): void {}
}

class Foo {
use T;
}

echo "Done";

?>
--EXPECTF--
Fatal error: Foo::t() has #[\Override] attribute, but no matching parent method exists in %s on line %d
23 changes: 23 additions & 0 deletions Zend/tests/attributes/override/009.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
#[\Override]: On used trait with interface method.
--FILE--
<?php

trait T {
#[\Override]
public function i(): void {}
}

interface I {
public function i(): void;
}

class Foo implements I {
use T;
}

echo "Done";

?>
--EXPECT--
Done
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/010.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: Parent method is private.
--FILE--
<?php

class P {
private function p(): void {}
}

class C extends P {
#[\Override]
public function p(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: C::p() has #[\Override] attribute, but no matching parent method exists in %s on line %d
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/011.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: Parent method is private (2).
--FILE--
<?php

class P {
private function p(): void {}
}

class C extends P {
#[\Override]
private function p(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: C::p() has #[\Override] attribute, but no matching parent method exists in %s on line %d
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/012.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: Parent method is protected.
--FILE--
<?php

class P {
protected function p(): void {}
}

class C extends P {
#[\Override]
public function p(): void {}
}

echo "Done";

?>
--EXPECT--
Done
19 changes: 19 additions & 0 deletions Zend/tests/attributes/override/013.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
#[\Override]: Parent method is protected (2).
--FILE--
<?php

class P {
protected function p(): void {}
}

class C extends P {
#[\Override]
protected function p(): void {}
}

echo "Done";

?>
--EXPECT--
Done
18 changes: 18 additions & 0 deletions Zend/tests/attributes/override/014.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--TEST--
#[\Override]: enum without interface.
--FILE--
<?php

enum E {
case One;
case Two;

#[\Override]
public function e(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: E::e() has #[\Override] attribute, but no matching parent method exists in %s on line %d
22 changes: 22 additions & 0 deletions Zend/tests/attributes/override/015.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
#[\Override]: enum with matching interface.
--FILE--
<?php

interface I {
public function e(): void;
}

enum E implements I {
case One;
case Two;

#[\Override]
public function e(): void {}
}

echo "Done";

?>
--EXPECT--
Done
21 changes: 21 additions & 0 deletions Zend/tests/attributes/override/016.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
#[\Override]: Declared abstract trait method.
--FILE--
<?php

trait T {
public abstract function t(): void;
}

class C {
use T;

#[\Override]
public function t(): void {}
}

echo "Done";

?>
--EXPECT--
Done
21 changes: 21 additions & 0 deletions Zend/tests/attributes/override/017.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
#[\Override]: Redeclared trait method.
--FILE--
<?php

trait T {
public function t(): void {}
}

class C {
use T;

#[\Override]
public function t(): void {}
}

echo "Done";

?>
--EXPECTF--
Fatal error: C::t() has #[\Override] attribute, but no matching parent method exists in %s on line %d
Loading