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)
Language Features:
* Inheritance: A function that overrides only a single interface function does not require the ``override`` specifier.
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
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
parameter and return types of the function matches the getter function
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.
All functions declared in interfaces are implicitly ``virtual``, which means that
they can be overridden. This does not automatically mean that an overriding function
can be overridden again - this is only possible if the overriding
function is marked ``virtual``.
All functions declared in interfaces are implicitly ``virtual`` and any
functions that override them do not need the ``override`` keyword.
This does not automatically mean that an overriding function can be overridden again -
this is only possible if the overriding function is marked ``virtual``.
Interfaces can inherit from other interfaces. This has the same rules as normal
inheritance.

View File

@ -86,7 +86,8 @@ private:
int currentNode = static_cast<int>(numNodes++);
nodes[_function] = currentNode;
nodeInv[currentNode] = _function;
if (_function.overrides())
if (!_function.baseFunctions().empty())
for (auto const& baseFunction: _function.baseFunctions())
addEdge(currentNode, visit(baseFunction));
else
@ -518,7 +519,7 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
"Override changes modifier signature."
);
if (!_overriding.overrides())
if (!_overriding.overrides() && !(_super.isFunction() && _super.contract().isInterface()))
overrideError(
_overriding,
_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: (647-655): Function needs to specify overridden contracts "SuperA" and "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 {
uint dummy;
function f(uint[] memory) public override pure {}
function g(uint[] memory) public override view { dummy; }
function h(uint[] memory) public override { dummy = 42; }
function i(uint[] memory) public override payable {}
function f(uint[] memory) public pure {}
function g(uint[] memory) public view { dummy; }
function h(uint[] memory) public { dummy = 42; }
function i(uint[] memory) public payable {}
}
// ----

View File

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

View File

@ -9,8 +9,8 @@ interface I {
contract C is I {
uint dummy;
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 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) {}
}
// ----
// TypeError 9456: (182-230): Overriding function is missing "override" specifier.
// TypeError 4822: (182-230): Overriding function return types differ.

View File

@ -3,15 +3,15 @@ interface I {
function g() external;
}
abstract contract A is I {
function f() external override {}
function g() external override virtual;
function f() external {}
function g() external virtual;
}
abstract contract B is I {
function g() external override {}
function f() external override virtual;
function g() external {}
function f() external virtual;
}
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: (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 "f". 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;
}
abstract contract A is I {
function f() external override {}
function f() external {}
}
abstract contract B is I {
function g() external override {}
function g() external {}
}
contract C is A, B {
}

View File

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

View File

@ -3,12 +3,12 @@ interface I {
}
contract A is I
{
uint public override f;
uint public f;
}
abstract contract B is I
{
function f() external virtual override returns (uint);
function f() external virtual returns (uint);
}
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
{
uint public override f;
uint public f;
}
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 {}
// ----
// 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); }
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); }
contract Y is X {
uint256 public override test = 42;
uint256 public test = 42;
}
contract T {
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 {
function test() external returns (uint256);
function test2() external returns (uint256);
function test3() external returns (uint256);
}
contract X is A {
function test() external override 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) {}
}
abstract contract T is A {
function foo() external virtual override returns (uint);
function goo() external virtual override returns (uint);
function foo() external virtual returns (uint);
function goo() external virtual returns (uint);
}
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: (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 "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 "goo". Two or more base classes define function with same name and parameter types.