Merge pull request #11628 from ethereum/noOverrideForInterface

Add override exception for interface functions.
This commit is contained in:
chriseth 2021-08-31 10:45:57 +02:00 committed by GitHub
commit 13691dfbaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 83 additions and 38 deletions

View File

@ -1,6 +1,7 @@
### 0.8.8 (unreleased) ### 0.8.8 (unreleased)
Language Features: Language Features:
* Inheritance: A function that overrides only a single interface function does not require the ``override`` specifier.
Compiler Features: Compiler Features:

View File

@ -303,6 +303,13 @@ contracts can no longer change the behaviour of that function.
outside of interfaces. In interfaces, all functions are outside of interfaces. In interfaces, all functions are
automatically considered ``virtual``. automatically considered ``virtual``.
.. note::
Starting from Solidity 0.8.8, the ``override`` keyword is not
required when overriding an interface function, except for the
case where the function is defined in multiple bases.
Public state variables can override external functions if the Public state variables can override external functions if the
parameter and return types of the function matches the getter function parameter and return types of the function matches the getter function
of the variable: of the variable:

View File

@ -33,10 +33,10 @@ Interfaces are denoted by their own keyword:
Contracts can inherit interfaces as they would inherit other contracts. Contracts can inherit interfaces as they would inherit other contracts.
All functions declared in interfaces are implicitly ``virtual``, which means that All functions declared in interfaces are implicitly ``virtual`` and any
they can be overridden. This does not automatically mean that an overriding function functions that override them do not need the ``override`` keyword.
can be overridden again - this is only possible if the overriding This does not automatically mean that an overriding function can be overridden again -
function is marked ``virtual``. this is only possible if the overriding function is marked ``virtual``.
Interfaces can inherit from other interfaces. This has the same rules as normal Interfaces can inherit from other interfaces. This has the same rules as normal
inheritance. inheritance.

View File

@ -86,7 +86,8 @@ private:
int currentNode = static_cast<int>(numNodes++); int currentNode = static_cast<int>(numNodes++);
nodes[_function] = currentNode; nodes[_function] = currentNode;
nodeInv[currentNode] = _function; nodeInv[currentNode] = _function;
if (_function.overrides())
if (!_function.baseFunctions().empty())
for (auto const& baseFunction: _function.baseFunctions()) for (auto const& baseFunction: _function.baseFunctions())
addEdge(currentNode, visit(baseFunction)); addEdge(currentNode, visit(baseFunction));
else else
@ -518,7 +519,7 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
"Override changes modifier signature." "Override changes modifier signature."
); );
if (!_overriding.overrides()) if (!_overriding.overrides() && !(_super.isFunction() && _super.contract().isInterface()))
overrideError( overrideError(
_overriding, _overriding,
_super, _super,

View File

@ -23,8 +23,6 @@ interface Sub is SuperA, SuperB {
} }
// ---- // ----
// TypeError 9456: (572-616): Overriding function is missing "override" specifier.
// TypeError 9456: (572-616): Overriding function is missing "override" specifier.
// TypeError 4327: (572-616): Function needs to specify overridden contracts "SuperA" and "SuperB". // TypeError 4327: (572-616): Function needs to specify overridden contracts "SuperA" and "SuperB".
// TypeError 4327: (647-655): Function needs to specify overridden contracts "SuperA" and "SuperB". // TypeError 4327: (647-655): Function needs to specify overridden contracts "SuperA" and "SuperB".
// TypeError 4327: (705-721): Function needs to specify overridden contract "SuperB". // TypeError 4327: (705-721): Function needs to specify overridden contract "SuperB".

View File

@ -11,4 +11,3 @@ interface Sub is Super {
} }
// ---- // ----
// TypeError 9456: (197-241): Overriding function is missing "override" specifier.

View File

@ -6,9 +6,9 @@ interface I {
} }
contract C is I { contract C is I {
uint dummy; uint dummy;
function f(uint[] memory) public override pure {} function f(uint[] memory) public pure {}
function g(uint[] memory) public override view { dummy; } function g(uint[] memory) public view { dummy; }
function h(uint[] memory) public override { dummy = 42; } function h(uint[] memory) public { dummy = 42; }
function i(uint[] memory) public override payable {} function i(uint[] memory) public payable {}
} }
// ---- // ----

View File

@ -2,7 +2,7 @@ interface I {
function f(uint[] calldata) external pure; function f(uint[] calldata) external pure;
} }
contract A is I { contract A is I {
function f(uint[] memory) public override pure {} function f(uint[] memory) public pure {}
} }
contract C { contract C {
function f() public { function f() public {

View File

@ -9,8 +9,8 @@ interface I {
contract C is I { contract C is I {
uint dummy; uint dummy;
function f(S memory) public override pure {} function f(S memory) public override pure {}
function g(S memory) public override view { dummy; } function g(S memory) public view { dummy; }
function h(S memory) public override { dummy = 42; } function h(S memory) public override { dummy = 42; }
function i(S memory) public override payable {} function i(S memory) public payable {}
} }
// ---- // ----

View File

@ -7,5 +7,4 @@ contract B is I {
function f() public pure returns (uint, uint) {} function f() public pure returns (uint, uint) {}
} }
// ---- // ----
// TypeError 9456: (182-230): Overriding function is missing "override" specifier.
// TypeError 4822: (182-230): Overriding function return types differ. // TypeError 4822: (182-230): Overriding function return types differ.

View File

@ -3,15 +3,15 @@ interface I {
function g() external; function g() external;
} }
abstract contract A is I { abstract contract A is I {
function f() external override {} function f() external {}
function g() external override virtual; function g() external virtual;
} }
abstract contract B is I { abstract contract B is I {
function g() external override {} function g() external {}
function f() external override virtual; function f() external virtual;
} }
contract C is A, B { contract C is A, B {
} }
// ---- // ----
// TypeError 6480: (292-314): Derived contract must override function "f". Two or more base classes define function with same name and parameter types. // TypeError 6480: (256-278): Derived contract must override function "f". Two or more base classes define function with same name and parameter types.
// TypeError 6480: (292-314): Derived contract must override function "g". Two or more base classes define function with same name and parameter types. // TypeError 6480: (256-278): Derived contract must override function "g". Two or more base classes define function with same name and parameter types.

View File

@ -3,10 +3,10 @@ interface I {
function g() external; function g() external;
} }
abstract contract A is I { abstract contract A is I {
function f() external override {} function f() external {}
} }
abstract contract B is I { abstract contract B is I {
function g() external override {} function g() external {}
} }
contract C is A, B { contract C is A, B {
} }

View File

@ -3,7 +3,7 @@ interface I {
} }
abstract contract A is I abstract contract A is I
{ {
uint public override f; uint public f;
} }
abstract contract B is I abstract contract B is I
{ {

View File

@ -3,12 +3,12 @@ interface I {
} }
contract A is I contract A is I
{ {
uint public override f; uint public f;
} }
abstract contract B is I abstract contract B is I
{ {
function f() external virtual override returns (uint); function f() external virtual returns (uint);
} }
abstract contract C is A, B {} abstract contract C is A, B {}
// ---- // ----
// TypeError 6480: (185-215): Derived contract must override function "f". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions. // TypeError 6480: (167-197): Derived contract must override function "f". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions.

View File

@ -3,12 +3,12 @@ interface I {
} }
contract A is I contract A is I
{ {
uint public override f; uint public f;
} }
abstract contract B is I abstract contract B is I
{ {
function f() external virtual override returns (uint) { return 2; } function f() external virtual returns (uint) { return 2; }
} }
abstract contract C is A, B {} abstract contract C is A, B {}
// ---- // ----
// TypeError 6480: (198-228): Derived contract must override function "f". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions. // TypeError 6480: (180-210): Derived contract must override function "f". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions.

View File

@ -1,3 +1,3 @@
interface ERC20 { function x() external returns (uint); } interface ERC20 { function x() external returns (uint); }
contract C is ERC20 { uint public override x; } contract C is ERC20 { uint public x; }
// ---- // ----

View File

@ -1,6 +1,6 @@
interface X { function test() external returns (uint256); } interface X { function test() external returns (uint256); }
contract Y is X { contract Y is X {
uint256 public override test = 42; uint256 public test = 42;
} }
contract T { contract T {
constructor() { new Y(); } constructor() { new Y(); }

View File

@ -0,0 +1,8 @@
abstract contract I {
function f() external virtual;
}
contract C is I {
function f() external {}
}
// ----
// TypeError 9456: (75-99): Overriding function is missing "override" specifier.

View File

@ -0,0 +1,19 @@
interface I {
function f() external;
function g() external;
function h() external;
}
interface J {
function f() external;
function g() external;
function h() external;
}
contract C is I, J {
function f() external {}
function g() external override {}
function h() external override(I) {}
}
// ----
// TypeError 4327: (198-222): Function needs to specify overridden contracts "I" and "J".
// TypeError 4327: (246-254): Function needs to specify overridden contracts "I" and "J".
// TypeError 4327: (281-292): Function needs to specify overridden contract "J".

View File

@ -0,0 +1,11 @@
interface I {
function f() external;
function g() external;
function h() external;
}
contract C is I {
function f() external {}
function g() external override {}
function h() external override(I) {}
}
// ----

View File

@ -1,9 +1,11 @@
interface A { interface A {
function test() external returns (uint256); function test() external returns (uint256);
function test2() external returns (uint256); function test2() external returns (uint256);
function test3() external returns (uint256);
} }
contract X is A { contract X is A {
function test() external override returns (uint256) {} function test() external override returns (uint256) {}
function test2() external override(A) returns (uint256) {} function test2() external override(A) returns (uint256) {}
function test3() external returns (uint256) {}
} }
// ---- // ----

View File

@ -11,11 +11,11 @@ contract X is A, B {
function goo() external virtual override(A, B) returns (uint) {} function goo() external virtual override(A, B) returns (uint) {}
} }
abstract contract T is A { abstract contract T is A {
function foo() external virtual override returns (uint); function foo() external virtual returns (uint);
function goo() external virtual override returns (uint); function goo() external virtual returns (uint);
} }
contract Y is X, T { contract Y is X, T {
} }
// ---- // ----
// TypeError 6480: (484-506): Derived contract must override function "foo". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions. // TypeError 6480: (466-488): Derived contract must override function "foo". Two or more base classes define function with same name and parameter types. Since one of the bases defines a public state variable which cannot be overridden, you have to change the inheritance layout or the names of the functions.
// TypeError 6480: (484-506): Derived contract must override function "goo". Two or more base classes define function with same name and parameter types. // TypeError 6480: (466-488): Derived contract must override function "goo". Two or more base classes define function with same name and parameter types.