mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Handle not unique operators for user-defined type.
This commit is contained in:
parent
8272da0aea
commit
8307b670cb
@ -1790,18 +1790,18 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
_operation.annotation().isConstant = false;
|
_operation.annotation().isConstant = false;
|
||||||
|
|
||||||
// Check if the operator is built-in or user-defined.
|
// Check if the operator is built-in or user-defined.
|
||||||
FunctionDefinition const* userDefinedOperator = leftType->userDefinedOperator(
|
FunctionDefinitionResult userDefinedOperatorResult = leftType->userDefinedOperator(
|
||||||
_operation.getOperator(),
|
_operation.getOperator(),
|
||||||
*currentDefinitionScope(),
|
*currentDefinitionScope(),
|
||||||
false // _unaryOperation
|
false // _unaryOperation
|
||||||
);
|
);
|
||||||
_operation.annotation().userDefinedFunction = userDefinedOperator;
|
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
|
||||||
FunctionType const* userDefinedFunctionType = nullptr;
|
FunctionType const* userDefinedFunctionType = nullptr;
|
||||||
if (userDefinedOperator)
|
if (userDefinedOperatorResult)
|
||||||
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
||||||
userDefinedOperator->libraryFunction() ?
|
userDefinedOperatorResult.get()->libraryFunction() ?
|
||||||
*userDefinedOperator->typeViaContractName() :
|
*userDefinedOperatorResult.get()->typeViaContractName() :
|
||||||
*userDefinedOperator->type()
|
*userDefinedOperatorResult.get()->type()
|
||||||
);
|
);
|
||||||
_operation.annotation().isPure =
|
_operation.annotation().isPure =
|
||||||
*_operation.leftExpression().annotation().isPure &&
|
*_operation.leftExpression().annotation().isPure &&
|
||||||
@ -1812,9 +1812,9 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
Type const* commonType = leftType;
|
Type const* commonType = leftType;
|
||||||
|
|
||||||
// Either the operator is user-defined or built-in.
|
// Either the operator is user-defined or built-in.
|
||||||
solAssert(!userDefinedOperator || !builtinResult);
|
solAssert(!userDefinedOperatorResult || !builtinResult);
|
||||||
|
|
||||||
if (!builtinResult && !userDefinedOperator)
|
if (!builtinResult && !userDefinedOperatorResult)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
2271_error,
|
2271_error,
|
||||||
_operation.location(),
|
_operation.location(),
|
||||||
@ -1824,12 +1824,13 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
leftType->humanReadableName() +
|
leftType->humanReadableName() +
|
||||||
" and " +
|
" and " +
|
||||||
rightType->humanReadableName() + "." +
|
rightType->humanReadableName() + "." +
|
||||||
(!builtinResult.message().empty() ? " " + builtinResult.message() : "")
|
(!builtinResult.message().empty() ? " " + builtinResult.message() : "") +
|
||||||
|
(!userDefinedOperatorResult.message().empty() ? " " + userDefinedOperatorResult.message() : "")
|
||||||
);
|
);
|
||||||
|
|
||||||
if (builtinResult)
|
if (builtinResult)
|
||||||
commonType = builtinResult.get();
|
commonType = builtinResult.get();
|
||||||
else if (userDefinedOperator)
|
else if (userDefinedOperatorResult)
|
||||||
{
|
{
|
||||||
solAssert(
|
solAssert(
|
||||||
userDefinedFunctionType->parameterTypes().size() == 2 &&
|
userDefinedFunctionType->parameterTypes().size() == 2 &&
|
||||||
@ -1845,7 +1846,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
TypeProvider::boolean() :
|
TypeProvider::boolean() :
|
||||||
commonType;
|
commonType;
|
||||||
|
|
||||||
if (userDefinedOperator)
|
if (userDefinedOperatorResult)
|
||||||
solAssert(
|
solAssert(
|
||||||
userDefinedFunctionType->returnParameterTypes().size() == 1 &&
|
userDefinedFunctionType->returnParameterTypes().size() == 1 &&
|
||||||
*userDefinedFunctionType->returnParameterTypes().front() == *_operation.annotation().type
|
*userDefinedFunctionType->returnParameterTypes().front() == *_operation.annotation().type
|
||||||
|
@ -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())
|
if (!typeDefinition())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -409,11 +408,12 @@ FunctionDefinition const* Type::userDefinedOperator(Token _token, ASTNode const&
|
|||||||
seenFunctions.insert(&function);
|
seenFunctions.insert(&function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO proper error handling.
|
|
||||||
if (seenFunctions.size() == 1)
|
if (seenFunctions.size() == 1)
|
||||||
return *seenFunctions.begin();
|
return *seenFunctions.begin();
|
||||||
|
else if (seenFunctions.size() == 0)
|
||||||
|
return FunctionDefinitionResult::err("A user-defined operator not found.");
|
||||||
else
|
else
|
||||||
return nullptr;
|
return FunctionDefinitionResult::err("A user-defined operator not unique.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ using TypePointers = std::vector<Type const*>;
|
|||||||
using rational = boost::rational<bigint>;
|
using rational = boost::rational<bigint>;
|
||||||
using TypeResult = util::Result<Type const*>;
|
using TypeResult = util::Result<Type const*>;
|
||||||
using BoolResult = util::Result<bool>;
|
using BoolResult = util::Result<bool>;
|
||||||
|
using FunctionDefinitionResult = util::Result<FunctionDefinition const*>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,7 +378,7 @@ public:
|
|||||||
/// Clears all internally cached values (if any).
|
/// Clears all internally cached values (if any).
|
||||||
virtual void clearCache() const;
|
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:
|
private:
|
||||||
/// @returns a member list containing all members added to this type by `using for` directives.
|
/// @returns a member list containing all members added to this type by `using for` directives.
|
||||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user