mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5817 from ethereum/refactoring
Refactoring in TypeChecker and ContractDefinition
This commit is contained in:
commit
7b759866cb
@ -262,7 +262,7 @@ bool SyntaxChecker::visit(PlaceholderStatement const&)
|
||||
|
||||
bool SyntaxChecker::visit(ContractDefinition const& _contract)
|
||||
{
|
||||
m_isInterface = _contract.contractKind() == ContractDefinition::ContractKind::Interface;
|
||||
m_isInterface = _contract.isInterface();
|
||||
|
||||
ASTString const& contractName = _contract.name();
|
||||
for (FunctionDefinition const* function: _contract.definedFunctions())
|
||||
|
@ -236,7 +236,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
auto base = dynamic_cast<ContractDefinition const*>(&dereference(_inheritance.name()));
|
||||
solAssert(base, "Base contract not available.");
|
||||
|
||||
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
|
||||
if (m_scope->isInterface())
|
||||
m_errorReporter.typeError(_inheritance.location(), "Interfaces cannot inherit.");
|
||||
|
||||
if (base->isLibrary())
|
||||
@ -244,7 +244,7 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
|
||||
auto const& arguments = _inheritance.arguments();
|
||||
TypePointers parameterTypes;
|
||||
if (base->contractKind() != ContractDefinition::ContractKind::Interface)
|
||||
if (!base->isInterface())
|
||||
// Interfaces do not have constructors, so there are zero parameters.
|
||||
parameterTypes = ContractType(*base).newExpressionType()->parameterTypes();
|
||||
|
||||
@ -331,33 +331,40 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
if (!_function.isConstructor() && !_function.isFallback() && !_function.isPartOfExternalInterface())
|
||||
m_errorReporter.typeError(_function.location(), "Internal functions cannot be payable.");
|
||||
}
|
||||
for (ASTPointer<VariableDeclaration> const& var: _function.parameters() + _function.returnParameters())
|
||||
{
|
||||
if (type(*var)->category() == Type::Category::Mapping)
|
||||
auto checkArgumentAndReturnParameter = [&](VariableDeclaration const& var) {
|
||||
if (type(var)->category() == Type::Category::Mapping)
|
||||
{
|
||||
if (!type(*var)->dataStoredIn(DataLocation::Storage))
|
||||
m_errorReporter.typeError(var->location(), "Mapping types can only have a data location of \"storage\"." );
|
||||
if (!type(var)->dataStoredIn(DataLocation::Storage))
|
||||
m_errorReporter.typeError(var.location(), "Mapping types can only have a data location of \"storage\"." );
|
||||
else if (!isLibraryFunction && _function.isPublic())
|
||||
m_errorReporter.typeError(var->location(), "Mapping types for parameters or return variables can only be used in internal or library functions.");
|
||||
m_errorReporter.typeError(var.location(), "Mapping types for parameters or return variables can only be used in internal or library functions.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!type(*var)->canLiveOutsideStorage() && _function.isPublic())
|
||||
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
|
||||
if (_function.isPublic() && !(type(*var)->interfaceType(isLibraryFunction)))
|
||||
m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions.");
|
||||
if (!type(var)->canLiveOutsideStorage() && _function.isPublic())
|
||||
m_errorReporter.typeError(var.location(), "Type is required to live outside storage.");
|
||||
if (_function.isPublic() && !(type(var)->interfaceType(isLibraryFunction)))
|
||||
m_errorReporter.fatalTypeError(var.location(), "Internal or recursive type is not allowed for public or external functions.");
|
||||
}
|
||||
if (
|
||||
_function.isPublic() &&
|
||||
!_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
||||
!typeSupportedByOldABIEncoder(*type(*var))
|
||||
!typeSupportedByOldABIEncoder(*type(var))
|
||||
)
|
||||
m_errorReporter.typeError(
|
||||
var->location(),
|
||||
var.location(),
|
||||
"This type is only supported in the new experimental ABI encoder. "
|
||||
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
|
||||
);
|
||||
|
||||
};
|
||||
for (ASTPointer<VariableDeclaration> const& var: _function.parameters())
|
||||
{
|
||||
checkArgumentAndReturnParameter(*var);
|
||||
var->accept(*this);
|
||||
}
|
||||
for (ASTPointer<VariableDeclaration> const& var: _function.returnParameters())
|
||||
{
|
||||
checkArgumentAndReturnParameter(*var);
|
||||
var->accept(*this);
|
||||
}
|
||||
set<Declaration const*> modifiers;
|
||||
@ -378,7 +385,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
else
|
||||
modifiers.insert(decl);
|
||||
}
|
||||
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
|
||||
if (m_scope->isInterface())
|
||||
{
|
||||
if (_function.isImplemented())
|
||||
m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation.");
|
||||
@ -407,7 +414,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
// * a function's input/output parameters,
|
||||
// * or inside of a struct definition.
|
||||
if (
|
||||
m_scope->contractKind() == ContractDefinition::ContractKind::Interface
|
||||
m_scope->isInterface()
|
||||
&& !_variable.isCallableParameter()
|
||||
&& !m_insideStruct
|
||||
)
|
||||
@ -1906,7 +1913,7 @@ void TypeChecker::endVisit(NewExpression const& _newExpression)
|
||||
|
||||
if (!contract)
|
||||
m_errorReporter.fatalTypeError(_newExpression.location(), "Identifier is not a contract.");
|
||||
if (contract->contractKind() == ContractDefinition::ContractKind::Interface)
|
||||
if (contract->isInterface())
|
||||
m_errorReporter.fatalTypeError(_newExpression.location(), "Cannot instantiate an interface.");
|
||||
if (!contract->annotation().unimplementedFunctions.empty())
|
||||
{
|
||||
|
@ -394,6 +394,7 @@ public:
|
||||
std::vector<FunctionDefinition const*> definedFunctions() const { return filteredNodes<FunctionDefinition>(m_subNodes); }
|
||||
std::vector<EventDefinition const*> events() const { return filteredNodes<EventDefinition>(m_subNodes); }
|
||||
std::vector<EventDefinition const*> const& interfaceEvents() const;
|
||||
bool isInterface() const { return m_contractKind == ContractKind::Interface; }
|
||||
bool isLibrary() const { return m_contractKind == ContractKind::Library; }
|
||||
|
||||
/// @returns a map of canonical function signatures to FunctionDefinitions
|
||||
|
@ -2525,7 +2525,7 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c
|
||||
strings parameterNames;
|
||||
StateMutability stateMutability = StateMutability::NonPayable;
|
||||
|
||||
solAssert(_contract.contractKind() != ContractDefinition::ContractKind::Interface, "");
|
||||
solAssert(!_contract.isInterface(), "");
|
||||
|
||||
if (constructor)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user