Handle not unique operators for user-defined type.

This commit is contained in:
wechman 2022-07-12 12:23:41 +02:00
parent 8272da0aea
commit 8307b670cb
4 changed files with 35 additions and 16 deletions

View File

@ -1790,18 +1790,18 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
_operation.annotation().isConstant = false;
// Check if the operator is built-in or user-defined.
FunctionDefinition const* userDefinedOperator = leftType->userDefinedOperator(
FunctionDefinitionResult userDefinedOperatorResult = leftType->userDefinedOperator(
_operation.getOperator(),
*currentDefinitionScope(),
false // _unaryOperation
);
_operation.annotation().userDefinedFunction = userDefinedOperator;
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
FunctionType const* userDefinedFunctionType = nullptr;
if (userDefinedOperator)
if (userDefinedOperatorResult)
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
userDefinedOperator->libraryFunction() ?
*userDefinedOperator->typeViaContractName() :
*userDefinedOperator->type()
userDefinedOperatorResult.get()->libraryFunction() ?
*userDefinedOperatorResult.get()->typeViaContractName() :
*userDefinedOperatorResult.get()->type()
);
_operation.annotation().isPure =
*_operation.leftExpression().annotation().isPure &&
@ -1812,9 +1812,9 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
Type const* commonType = leftType;
// Either the operator is user-defined or built-in.
solAssert(!userDefinedOperator || !builtinResult);
solAssert(!userDefinedOperatorResult || !builtinResult);
if (!builtinResult && !userDefinedOperator)
if (!builtinResult && !userDefinedOperatorResult)
m_errorReporter.typeError(
2271_error,
_operation.location(),
@ -1824,12 +1824,13 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
leftType->humanReadableName() +
" and " +
rightType->humanReadableName() + "." +
(!builtinResult.message().empty() ? " " + builtinResult.message() : "")
(!builtinResult.message().empty() ? " " + builtinResult.message() : "") +
(!userDefinedOperatorResult.message().empty() ? " " + userDefinedOperatorResult.message() : "")
);
if (builtinResult)
commonType = builtinResult.get();
else if (userDefinedOperator)
else if (userDefinedOperatorResult)
{
solAssert(
userDefinedFunctionType->parameterTypes().size() == 2 &&
@ -1845,7 +1846,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
TypeProvider::boolean() :
commonType;
if (userDefinedOperator)
if (userDefinedOperatorResult)
solAssert(
userDefinedFunctionType->returnParameterTypes().size() == 1 &&
*userDefinedFunctionType->returnParameterTypes().front() == *_operation.annotation().type

View File

@ -384,9 +384,8 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
}
FunctionDefinition const* Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const
FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const
{
// Check if it is a user-defined type.
if (!typeDefinition())
return nullptr;
@ -409,11 +408,12 @@ FunctionDefinition const* Type::userDefinedOperator(Token _token, ASTNode const&
seenFunctions.insert(&function);
}
// TODO proper error handling.
if (seenFunctions.size() == 1)
return *seenFunctions.begin();
else if (seenFunctions.size() == 0)
return FunctionDefinitionResult::err("A user-defined operator not found.");
else
return nullptr;
return FunctionDefinitionResult::err("A user-defined operator not unique.");
}

View File

@ -54,6 +54,7 @@ using TypePointers = std::vector<Type const*>;
using rational = boost::rational<bigint>;
using TypeResult = util::Result<Type const*>;
using BoolResult = util::Result<bool>;
using FunctionDefinitionResult = util::Result<FunctionDefinition const*>;
}
@ -377,7 +378,7 @@ public:
/// Clears all internally cached values (if any).
virtual void clearCache() const;
FunctionDefinition const* userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const;
FunctionDefinitionResult userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const;
private:
/// @returns a member list containing all members added to this type by `using for` directives.

View File

@ -0,0 +1,17 @@
type Int is uint128;
using {add as +, sub as +} for Int;
function add(Int, Int) returns (Int) {
return Int.wrap(0);
}
function sub(Int, Int) returns (Int) {
return Int.wrap(0);
}
function test() {
Int.wrap(0) + Int.wrap(1);
}
// ----
// TypeError 2271: (213-238): Operator + not compatible with types Int and Int. A user-defined operator not unique.