mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11628 from ethereum/noOverrideForInterface
Add override exception for interface functions.
This commit is contained in:
commit
13691dfbaa
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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".
|
||||||
|
@ -11,4 +11,3 @@ interface Sub is Super {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
// TypeError 9456: (197-241): Overriding function is missing "override" specifier.
|
|
||||||
|
@ -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 {}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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; }
|
||||||
// ----
|
// ----
|
||||||
|
@ -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(); }
|
||||||
|
@ -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.
|
@ -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".
|
@ -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) {}
|
||||||
|
}
|
||||||
|
// ----
|
@ -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) {}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user