From 0f0e466d36a3e09c4c5873998b5dd32dbe8025d6 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 15:04:43 +0100 Subject: [PATCH 1/2] Allow visibility change from external to public. --- libsolidity/analysis/TypeChecker.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index a6c23ada7..d503b9ec9 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -413,16 +413,14 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun if (_function.visibility() != _super.visibility()) { - // visibility is enforced to be external in interfaces, but a contract can override that with public - if ( - _super.inContractKind() == ContractDefinition::ContractKind::Interface && - _function.inContractKind() != ContractDefinition::ContractKind::Interface && + // Visibility change from external to public is fine. + // Any other change is disallowed. + if (!( + _super.visibility() == FunctionDefinition::Visibility::External && _function.visibility() == FunctionDefinition::Visibility::Public - ) - return; - overrideError(_function, _super, "Overriding function visibility differs."); + )) + overrideError(_function, _super, "Overriding function visibility differs."); } - else if (_function.stateMutability() != _super.stateMutability()) overrideError( _function, @@ -433,7 +431,6 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, Fun stateMutabilityToString(_function.stateMutability()) + "\"." ); - else if (functionType != superType) overrideError(_function, _super, "Overriding function return types differ."); } From ac5803bf3e5dc43adf8bf64c1041603259e8a16f Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 22 Nov 2018 17:38:12 +0100 Subject: [PATCH 2/2] Changelog entry and tests. --- Changelog.md | 1 + test/libsolidity/SolidityEndToEndTest.cpp | 15 +++++++++++++++ .../override/external_turns_public_no_params.sol | 7 +++++++ .../syntaxTests/inheritance/super_on_external.sol | 10 ++++++++++ .../nameAndTypeResolution/182_equal_overload.sol | 1 - 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol create mode 100644 test/libsolidity/syntaxTests/inheritance/super_on_external.sol diff --git a/Changelog.md b/Changelog.md index ff26882d8..e6f015537 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ ### 0.5.1 (unreleased) Language Features: + * Allow public functions to override external functions. Compiler Features: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index e591432a3..e9667483f 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -14062,6 +14062,21 @@ BOOST_AUTO_TEST_CASE(flipping_sign_tests) ABI_CHECK(callContractFunction("f()"), encodeArgs(true)); } +BOOST_AUTO_TEST_CASE(external_public_override) +{ + char const* sourceCode = R"( + contract A { + function f() external returns (uint) { return 1; } + } + contract B is A { + function f() public returns (uint) { return 2; } + function g() public returns (uint) { return f(); } + } + )"; + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f()"), encodeArgs(2)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(2)); +} BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol new file mode 100644 index 000000000..3d0394f5e --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/override/external_turns_public_no_params.sol @@ -0,0 +1,7 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + } +} diff --git a/test/libsolidity/syntaxTests/inheritance/super_on_external.sol b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol new file mode 100644 index 000000000..21f3b1c2e --- /dev/null +++ b/test/libsolidity/syntaxTests/inheritance/super_on_external.sol @@ -0,0 +1,10 @@ +contract A { + function f() external pure {} +} +contract B is A { + function f() public pure { + super.f(); + } +} +// ---- +// TypeError: (106-113): Member "f" not found or not visible after argument-dependent lookup in contract super B. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol index cb9eb3fa8..6f0c7df79 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/182_equal_overload.sol @@ -4,4 +4,3 @@ contract C { } // ---- // DeclarationError: (17-66): Function with same name and arguments defined twice. -// TypeError: (17-66): Overriding function visibility differs.