diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst index eaed14757..497936f31 100644 --- a/docs/050-breaking-changes.rst +++ b/docs/050-breaking-changes.rst @@ -345,7 +345,7 @@ commandline compiler for linking): :: - // This will not compile with 0.6.0 anymore. + // This will not compile after 0.6.0 pragma solidity >=0.5.0 <0.5.99; library OldLibrary { diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 47a220466..be4eca4b6 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -134,8 +134,8 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract) checkDuplicateEvents(_contract); checkIllegalOverrides(_contract); checkAmbiguousOverrides(_contract); - checkAbstractFunctions(_contract); checkBaseConstructorArguments(_contract); + checkAbstractFunctions(_contract); checkExternalTypeClashes(_contract); checkHashCollisions(_contract); checkLibraryRequirements(_contract); @@ -395,6 +395,8 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con } // Set to not fully implemented if at least one flag is false. + // Note that `_contract.annotation().unimplementedFunctions` has already been + // pre-filled by `checkBaseConstructorArguments`. for (auto const& it: functions) for (auto const& funAndFlag: it.second) if (!funAndFlag.second) @@ -405,13 +407,22 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con break; } - if (_contract.abstract() && _contract.contractKind() != ContractDefinition::ContractKind::Contract) - m_errorReporter.typeError(_contract.location(), "Only contracts can be abstract."); + if (_contract.abstract()) + { + if (_contract.contractKind() == ContractDefinition::ContractKind::Interface) + m_errorReporter.typeError(_contract.location(), "Interfaces do not need the \"abstract\" keyword, they are abstract implicitly."); + else if (_contract.contractKind() == ContractDefinition::ContractKind::Library) + m_errorReporter.typeError(_contract.location(), "Libraries cannot be abstract."); + else + solAssert(_contract.contractKind() == ContractDefinition::ContractKind::Contract, ""); + } + // For libraries, we emit errors on function-level, so this is fine as long as we do + // not have inheritance for libraries. if ( _contract.contractKind() == ContractDefinition::ContractKind::Contract && - !_contract.annotation().unimplementedFunctions.empty() && - !_contract.abstract() + !_contract.abstract() && + !_contract.annotation().unimplementedFunctions.empty() ) m_errorReporter.typeError( _contract.location(), diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index e4374ce14..5f3c7e9d6 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -77,6 +77,8 @@ private: void overrideListError(FunctionDefinition const& function, std::set _secondary, std::string const& _message1, std::string const& _message2); void overrideError(CallableDeclaration const& function, CallableDeclaration const& super, std::string message); void checkAbstractFunctions(ContractDefinition const& _contract); + /// Checks that the base constructor arguments are properly provided. + /// Fills the list of unimplemented functions in _contract's annotations. void checkBaseConstructorArguments(ContractDefinition const& _contract); void annotateBaseConstructorArguments( ContractDefinition const& _currentContract, diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index bd5a91250..83da543fa 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -423,8 +423,8 @@ bool TypeChecker::visit(FunctionDefinition const& _function) _function.body().accept(*this); else if (_function.isConstructor()) m_errorReporter.typeError(_function.location(), "Constructor must be implemented if declared."); - else if (isLibraryFunction && _function.visibility() <= FunctionDefinition::Visibility::Internal) - m_errorReporter.typeError(_function.location(), "Internal library function must be implemented if declared."); + else if (isLibraryFunction) + m_errorReporter.typeError(_function.location(), "Library functions must be implemented if declared."); if (_function.isFallback()) @@ -2228,7 +2228,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) m_errorReporter.fatalTypeError(_newExpression.location(), "Cannot instantiate an interface."); if (!contract->constructorIsPublic()) m_errorReporter.typeError(_newExpression.location(), "Contract with internal constructor cannot be created directly."); - if (contract->abstract() || !contract->annotation().unimplementedFunctions.empty()) + if (contract->abstract()) m_errorReporter.typeError(_newExpression.location(), "Cannot instantiate an abstract contract."); solAssert(!!m_scope, ""); diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index b75f485a5..deedffb48 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -151,7 +151,7 @@ bool ContractDefinition::constructorIsPublic() const bool ContractDefinition::canBeDeployed() const { - return constructorIsPublic() && annotation().unimplementedFunctions.empty() && !abstract(); + return constructorIsPublic() && !abstract() && !isInterface(); } FunctionDefinition const* ContractDefinition::fallbackFunction() const diff --git a/test/libsolidity/syntaxTests/abstract/interface.sol b/test/libsolidity/syntaxTests/abstract/interface.sol index c3b977a41..215657cab 100644 --- a/test/libsolidity/syntaxTests/abstract/interface.sol +++ b/test/libsolidity/syntaxTests/abstract/interface.sol @@ -1,3 +1,4 @@ +interface B { } abstract interface A { } // ---- -// TypeError: (0-24): Only contracts can be abstract. +// TypeError: (16-40): Interfaces do not need the "abstract" keyword, they are abstract implicitly. diff --git a/test/libsolidity/syntaxTests/abstract/library.sol b/test/libsolidity/syntaxTests/abstract/library.sol index 569758986..c2bd40edb 100644 --- a/test/libsolidity/syntaxTests/abstract/library.sol +++ b/test/libsolidity/syntaxTests/abstract/library.sol @@ -1,3 +1,3 @@ abstract library A { } // ---- -// TypeError: (0-22): Only contracts can be abstract. +// TypeError: (0-22): Libraries cannot be abstract. diff --git a/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol index a4ea8f40e..668b2d477 100644 --- a/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol +++ b/test/libsolidity/syntaxTests/constructor/abstract_creation_forward_reference.sol @@ -12,4 +12,4 @@ contract Parent { contract Child is Parent { } // ---- -// TypeError: (146-155): Cannot instantiate an abstract contract. +// TypeError: (233-261): Contract "Child" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol index f9c4b9b98..ab2d82d56 100644 --- a/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol +++ b/test/libsolidity/syntaxTests/constructor/constructor_visibility.sol @@ -9,4 +9,5 @@ contract B is A { } } // ---- +// TypeError: (131-301): Contract "B" should be marked as abstract. // TypeError: (250-254): Explicit type conversion not allowed from "string memory" to "contract A". diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol index 818b6a205..1a910d99e 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/unimplemented_library.sol @@ -1,4 +1,15 @@ +// This used to work pre-0.6.0. library L { function f() public returns(uint[] storage); function g() public returns(uint[] storage s); } +abstract library T { + function f() public returns(uint[] storage); + function g() public returns(uint[] storage s); +} +// ---- +// TypeError: (146-268): Libraries cannot be abstract. +// TypeError: (48-92): Library functions must be implemented if declared. +// TypeError: (97-143): Library functions must be implemented if declared. +// TypeError: (171-215): Library functions must be implemented if declared. +// TypeError: (220-266): Library functions must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol index d3ac2accb..6df4d10c9 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_calldata.sol @@ -1,3 +1,4 @@ library test { - function f(bytes calldata) external; + function f(bytes calldata) external {} } +// ---- diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol index 2de0082ac..8dd898452 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_memory.sol @@ -1,5 +1,5 @@ library test { - function f(bytes memory) external; + function f(bytes memory) external {} } // ---- // TypeError: (30-42): Data location must be "storage" or "calldata" for parameter in external function, but "memory" was given. diff --git a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol index 2ee68ef9c..942cfa1ed 100644 --- a/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol +++ b/test/libsolidity/syntaxTests/dataLocations/libraryExternalFunction/function_argument_location_specifier_test_external_storage.sol @@ -1,3 +1,3 @@ library test { - function f(bytes storage) external; + function f(bytes storage) external {} } diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol index 049c47667..ba901a358 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/029_create_abstract_contract.sol @@ -5,4 +5,3 @@ contract derived { } // ---- // TypeError: (0-40): Contract "base" should be marked as abstract. -// TypeError: (104-112): Cannot instantiate an abstract contract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol index 31be70cad..062c4318f 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/061_missing_base_constructor_arguments.sol @@ -1,3 +1,4 @@ contract A { constructor(uint a) public { } } contract B is A { } // ---- +// TypeError: (46-65): Contract "B" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol index 31be70cad..062c4318f 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/062_base_constructor_arguments_override.sol @@ -1,3 +1,4 @@ contract A { constructor(uint a) public { } } contract B is A { } // ---- +// TypeError: (46-65): Contract "B" should be marked as abstract. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol index c007d9a15..4846bb0f6 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/229_call_to_library_function.sol @@ -1,3 +1,4 @@ +// This used to work in pre-0.6.0. library Lib { function min(uint, uint) public returns (uint); } @@ -7,4 +8,4 @@ contract Test { } } // ---- -// Warning: (118-124): Unused local variable. +// TypeError: (53-100): Library functions must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol index fe5e49556..ab30c5999 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/511_library_function_without_implementation_public.sol @@ -1,4 +1,7 @@ +// This used to work pre-0.6.0. library L { // This can be used as an "interface", hence it is allowed. function f() public; } +// ---- +// TypeError: (112-132): Library functions must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol index d5dfb260c..812cf6137 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/512_library_function_without_implementation_internal.sol @@ -2,4 +2,4 @@ library L { function f() internal; } // ---- -// TypeError: (16-38): Internal library function must be implemented if declared. +// TypeError: (16-38): Library functions must be implemented if declared. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol index 70585e8c5..3fe6eb0dd 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/513_library_function_without_implementation_private.sol @@ -2,4 +2,4 @@ library L { function f() private; } // ---- -// TypeError: (16-37): Internal library function must be implemented if declared. +// TypeError: (16-37): Library functions must be implemented if declared.