diff --git a/Changelog.md b/Changelog.md index 25a4b1a32..def68a275 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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: diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index 24d2fd2ff..b77feda0a 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -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: diff --git a/docs/contracts/interfaces.rst b/docs/contracts/interfaces.rst index bfaf1bf2e..ae5a15e99 100644 --- a/docs/contracts/interfaces.rst +++ b/docs/contracts/interfaces.rst @@ -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. diff --git a/libsolidity/analysis/OverrideChecker.cpp b/libsolidity/analysis/OverrideChecker.cpp index 18a40be40..6f44f92ac 100644 --- a/libsolidity/analysis/OverrideChecker.cpp +++ b/libsolidity/analysis/OverrideChecker.cpp @@ -86,7 +86,8 @@ private: int currentNode = static_cast(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, diff --git a/test/libsolidity/syntaxTests/inheritance/interface/overrides_multiple.sol b/test/libsolidity/syntaxTests/inheritance/interface/overrides_multiple.sol index 96f741471..9c2f39bd9 100644 --- a/test/libsolidity/syntaxTests/inheritance/interface/overrides_multiple.sol +++ b/test/libsolidity/syntaxTests/inheritance/interface/overrides_multiple.sol @@ -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". diff --git a/test/libsolidity/syntaxTests/inheritance/interface/overrides_single.sol b/test/libsolidity/syntaxTests/inheritance/interface/overrides_single.sol index 106fb8975..bed7026dd 100644 --- a/test/libsolidity/syntaxTests/inheritance/interface/overrides_single.sol +++ b/test/libsolidity/syntaxTests/inheritance/interface/overrides_single.sol @@ -11,4 +11,3 @@ interface Sub is Super { } // ---- -// TypeError 9456: (197-241): Overriding function is missing "override" specifier. diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol index 33b66a86f..7be022c02 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface.sol @@ -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 {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol index 1a1ec2971..2c1045802 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_instantiate.sol @@ -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 { diff --git a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol index e77836724..1ba73bb97 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/calldata_memory_interface_struct.sol @@ -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 {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol index 8a477b70d..2ac2734c5 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/change_return_types_in_interface.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_implementation.sol b/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_implementation.sol index 0164d4dd1..cc065bbee 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_implementation.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_implementation.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_mention.sol b/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_mention.sol index c258bd219..7a4244941 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_mention.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/common_base_and_unique_mention.sol @@ -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 { } diff --git a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable.sol index 1903f08ae..7d0a0740c 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable.sol @@ -3,7 +3,7 @@ interface I { } abstract contract A is I { - uint public override f; + uint public f; } abstract contract B is I { diff --git a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function.sol b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function.sol index 90c747dc4..4ea1ab4c0 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function_implemented.sol b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function_implemented.sol index add03e5cb..90efce554 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function_implemented.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/diamond_interface_intermediate_public_state_variable_and_function_implemented.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol index d1e5eb306..ccb567099 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/function_state_variable.sol @@ -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; } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol index 5f493f515..d98e253c5 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol @@ -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(); } diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol new file mode 100644 index 000000000..97290af9c --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/abstract_needed.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol new file mode 100644 index 000000000..6c46e0a8b --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/diamond_needed.sol @@ -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". diff --git a/test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol new file mode 100644 index 000000000..b2f1d7c13 --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/interface_exception/regular_optional.sol @@ -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) {} +} +// ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol index 8b70bdbb6..9f2635511 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/override_interface.sol @@ -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) {} } // ---- diff --git a/test/libsolidity/syntaxTests/inheritance/override/public_var_implements_parallel_interface.sol b/test/libsolidity/syntaxTests/inheritance/override/public_var_implements_parallel_interface.sol index dc2f7b16a..eeb2574d5 100644 --- a/test/libsolidity/syntaxTests/inheritance/override/public_var_implements_parallel_interface.sol +++ b/test/libsolidity/syntaxTests/inheritance/override/public_var_implements_parallel_interface.sol @@ -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.