mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5485 from ethereum/refactorCallableFunction
Refactor callable function
This commit is contained in:
commit
bc137c2eeb
@ -400,42 +400,42 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, FunctionDefinition const& super)
|
void TypeChecker::checkFunctionOverride(FunctionDefinition const& _function, FunctionDefinition const& _super)
|
||||||
{
|
{
|
||||||
FunctionType functionType(function);
|
FunctionType functionType(_function);
|
||||||
FunctionType superType(super);
|
FunctionType superType(_super);
|
||||||
|
|
||||||
if (!functionType.hasEqualParameterTypes(superType))
|
if (!functionType.hasEqualParameterTypes(superType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!function.annotation().superFunction)
|
if (!_function.annotation().superFunction)
|
||||||
function.annotation().superFunction = &super;
|
_function.annotation().superFunction = &_super;
|
||||||
|
|
||||||
if (function.visibility() != super.visibility())
|
if (_function.visibility() != _super.visibility())
|
||||||
{
|
{
|
||||||
// visibility is enforced to be external in interfaces, but a contract can override that with public
|
// visibility is enforced to be external in interfaces, but a contract can override that with public
|
||||||
if (
|
if (
|
||||||
super.inContractKind() == ContractDefinition::ContractKind::Interface &&
|
_super.inContractKind() == ContractDefinition::ContractKind::Interface &&
|
||||||
function.inContractKind() != ContractDefinition::ContractKind::Interface &&
|
_function.inContractKind() != ContractDefinition::ContractKind::Interface &&
|
||||||
function.visibility() == FunctionDefinition::Visibility::Public
|
_function.visibility() == FunctionDefinition::Visibility::Public
|
||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
overrideError(function, super, "Overriding function visibility differs.");
|
overrideError(_function, _super, "Overriding function visibility differs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (function.stateMutability() != super.stateMutability())
|
else if (_function.stateMutability() != _super.stateMutability())
|
||||||
overrideError(
|
overrideError(
|
||||||
function,
|
_function,
|
||||||
super,
|
_super,
|
||||||
"Overriding function changes state mutability from \"" +
|
"Overriding function changes state mutability from \"" +
|
||||||
stateMutabilityToString(super.stateMutability()) +
|
stateMutabilityToString(_super.stateMutability()) +
|
||||||
"\" to \"" +
|
"\" to \"" +
|
||||||
stateMutabilityToString(function.stateMutability()) +
|
stateMutabilityToString(_function.stateMutability()) +
|
||||||
"\"."
|
"\"."
|
||||||
);
|
);
|
||||||
|
|
||||||
else if (functionType != superType)
|
else if (functionType != superType)
|
||||||
overrideError(function, super, "Overriding function return types differ.");
|
overrideError(_function, _super, "Overriding function return types differ.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message)
|
void TypeChecker::overrideError(FunctionDefinition const& function, FunctionDefinition const& super, string message)
|
||||||
|
@ -442,10 +442,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
|
|||||||
if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function))
|
if (!function->isVisibleAsLibraryMember() || seenFunctions.count(function))
|
||||||
continue;
|
continue;
|
||||||
seenFunctions.insert(function);
|
seenFunctions.insert(function);
|
||||||
FunctionType funType(*function, false);
|
if (function->parameters().empty())
|
||||||
if (auto fun = funType.asMemberFunction(true, true))
|
continue;
|
||||||
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
|
FunctionTypePointer fun = FunctionType(*function, false).asCallableFunction(true, true);
|
||||||
members.push_back(MemberList::Member(function->name(), fun, function));
|
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
|
||||||
|
members.push_back(MemberList::Member(function->name(), fun, function));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return members;
|
return members;
|
||||||
@ -1970,7 +1971,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con
|
|||||||
for (auto const& it: m_contract.interfaceFunctions())
|
for (auto const& it: m_contract.interfaceFunctions())
|
||||||
members.push_back(MemberList::Member(
|
members.push_back(MemberList::Member(
|
||||||
it.second->declaration().name(),
|
it.second->declaration().name(),
|
||||||
it.second->asMemberFunction(m_contract.isLibrary()),
|
it.second->asCallableFunction(m_contract.isLibrary()),
|
||||||
&it.second->declaration()
|
&it.second->declaration()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -3059,10 +3060,10 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound) const
|
FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const
|
||||||
{
|
{
|
||||||
if (_bound && m_parameterTypes.empty())
|
if (_bound)
|
||||||
return FunctionTypePointer();
|
solAssert(!m_parameterTypes.empty(), "");
|
||||||
|
|
||||||
TypePointers parameterTypes;
|
TypePointers parameterTypes;
|
||||||
for (auto const& t: m_parameterTypes)
|
for (auto const& t: m_parameterTypes)
|
||||||
@ -3201,7 +3202,7 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
|
|||||||
if (function->isVisibleAsLibraryMember())
|
if (function->isVisibleAsLibraryMember())
|
||||||
members.push_back(MemberList::Member(
|
members.push_back(MemberList::Member(
|
||||||
function->name(),
|
function->name(),
|
||||||
FunctionType(*function).asMemberFunction(true),
|
FunctionType(*function).asCallableFunction(true),
|
||||||
function
|
function
|
||||||
));
|
));
|
||||||
if (isBase)
|
if (isBase)
|
||||||
|
@ -1154,14 +1154,13 @@ public:
|
|||||||
/// of the parameters to false.
|
/// of the parameters to false.
|
||||||
TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const;
|
TypePointer copyAndSetGasOrValue(bool _setGas, bool _setValue) const;
|
||||||
|
|
||||||
/// @returns a copy of this function type where all return parameters of dynamic size are
|
/// @returns a copy of this function type where the location of reference types is changed
|
||||||
/// removed and the location of reference types is changed from CallData to Memory.
|
/// from CallData to Memory. This is the type that would be used when the function is
|
||||||
/// This is needed if external functions are called on other contracts, as they cannot return
|
/// called, as opposed to the parameter types that are available inside the function body.
|
||||||
/// dynamic values.
|
/// Also supports variants to be used for library or bound calls.
|
||||||
/// Returns empty shared pointer on a failure. Namely, if a bound function has no parameters.
|
|
||||||
/// @param _inLibrary if true, uses DelegateCall as location.
|
/// @param _inLibrary if true, uses DelegateCall as location.
|
||||||
/// @param _bound if true, the arguments are placed as `arg1.functionName(arg2, ..., argn)`.
|
/// @param _bound if true, the function type is set to be bound.
|
||||||
FunctionTypePointer asMemberFunction(bool _inLibrary, bool _bound = false) const;
|
FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TypePointers parseElementaryTypeVector(strings const& _types);
|
static TypePointers parseElementaryTypeVector(strings const& _types);
|
||||||
|
@ -414,7 +414,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction(
|
|||||||
if (
|
if (
|
||||||
function->name() == name &&
|
function->name() == name &&
|
||||||
!function->isConstructor() &&
|
!function->isConstructor() &&
|
||||||
FunctionType(*function).hasEqualParameterTypes(functionType)
|
FunctionType(*function).asCallableFunction(false)->hasEqualParameterTypes(functionType)
|
||||||
)
|
)
|
||||||
return *function;
|
return *function;
|
||||||
solAssert(false, "Super function " + name + " not found.");
|
solAssert(false, "Super function " + name + " not found.");
|
||||||
|
Loading…
Reference in New Issue
Block a user