Simplify Type::userDefinedOperator function

This commit is contained in:
wechman 2022-08-03 12:02:24 +02:00
parent e3f5c4c1b5
commit b860561814
3 changed files with 66 additions and 26 deletions

View File

@ -1750,13 +1750,37 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
solAssert(!builtinResult || !userDefinedOperatorResult);
if (userDefinedOperatorResult)
{
solAssert(userDefinedFunctionType->parameterTypes().size() == 1);
solAssert(userDefinedFunctionType->returnParameterTypes().size() == 1);
solAssert(
*userDefinedFunctionType->parameterTypes().at(0) ==
*userDefinedFunctionType->returnParameterTypes().at(0)
);
_operation.annotation().type = userDefinedFunctionType->returnParameterTypes().at(0);
if (userDefinedFunctionType->returnParameterTypes().size() != 1)
{
m_errorReporter.typeError(
3138_error,
_operation.location(),
"User defined operator " + string(TokenTraits::toString(_operation.getOperator())) +
" needs to return exactly one value."
);
_operation.annotation().type = subExprType;
}
else if (*userDefinedFunctionType->returnParameterTypes().front() != *userDefinedFunctionType->parameterTypes().front())
{
m_errorReporter.typeError(
7983_error,
_operation.location(),
"User defined operator " + string(TokenTraits::toString(_operation.getOperator())) +
" needs to return value of type " +
userDefinedFunctionType->parameterTypes().front()->humanReadableName() + "."
);
_operation.annotation().type = subExprType;
}
else
{
solAssert(userDefinedFunctionType->parameterTypes().size() == 1);
solAssert(
*userDefinedFunctionType->parameterTypes().at(0) ==
*userDefinedFunctionType->returnParameterTypes().at(0)
);
_operation.annotation().type = userDefinedFunctionType->returnParameterTypes().at(0);
}
}
else if (builtinResult)
_operation.annotation().type = builtinResult;
@ -1840,7 +1864,8 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
*userDefinedFunctionType->parameterTypes().at(0) ==
*userDefinedFunctionType->parameterTypes().at(1)
);
commonType = userDefinedFunctionType->returnParameterTypes().at(0);
if (userDefinedFunctionType->returnParameterTypes().size() == 1)
commonType = userDefinedFunctionType->parameterTypes().at(0);
}
_operation.annotation().commonType = commonType;
@ -1850,11 +1875,24 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
commonType;
if (userDefinedOperatorResult)
solAssert(
userDefinedFunctionType->returnParameterTypes().size() == 1 &&
*userDefinedFunctionType->returnParameterTypes().front() == *_operation.annotation().type,
"User defined operator has an invalid return parameter."
);
{
if (userDefinedFunctionType->returnParameterTypes().size() != 1)
m_errorReporter.typeError(
1208_error,
_operation.location(),
"User defined operator " + string(TokenTraits::toString(_operation.getOperator())) +
" needs to return exactly one value."
);
else if (*userDefinedFunctionType->returnParameterTypes().front() != *_operation.annotation().type)
m_errorReporter.typeError(
3841_error,
_operation.location(),
"User defined operator " + string(TokenTraits::toString(_operation.getOperator())) +
" needs to return value of type " +
_operation.annotation().type->humanReadableName() + "."
);
}
else if (_operation.getOperator() == Token::Exp || _operation.getOperator() == Token::SHL)
{
string operation = _operation.getOperator() == Token::Exp ? "exponentiation" : "shift";

View File

@ -404,14 +404,8 @@ Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNod
);
solAssert(functionType && !functionType->parameterTypes().empty());
Type const* expectedReturnType =
TokenTraits::isCompareOp(_token) ?
TypeProvider::boolean() : functionType->parameterTypes().front();
if (
isImplicitlyConvertibleTo(*functionType->parameterTypes().front()) &&
function.returnParameterList()->parameters().size() == 1 &&
function.returnParameterList()->parameters().front()->type()->isImplicitlyConvertibleTo(*expectedReturnType) &&
(
(_unaryOperation && function.parameterList().parameters().size() == 1) ||
(!_unaryOperation && function.parameterList().parameters().size() == 2)

View File

@ -4,6 +4,7 @@ using {
add as +,
div as /,
unsub as -,
bitnot as ~,
gt as >,
lt as <
} for Int;
@ -20,6 +21,10 @@ function unsub(Int) pure returns (Int, Int) {
return (Int.wrap(0), Int.wrap(1));
}
function bitnot(Int) pure returns (int256) {
return 0;
}
function gt(Int, Int) pure returns (Int) {
return Int.wrap(0);
}
@ -32,6 +37,7 @@ function f() pure {
Int.wrap(0) + Int.wrap(1);
Int.wrap(0) / Int.wrap(0);
-Int.wrap(0);
~Int.wrap(0);
Int.wrap(0) < Int.wrap(0);
Int.wrap(0) > Int.wrap(0);
}
@ -40,10 +46,12 @@ function f() pure {
// TypeError 7743: (33-36): The function "add" needs to return exactly one value of type Int to be used for the operator +.
// TypeError 7743: (47-50): The function "div" needs to return exactly one value of type Int to be used for the operator /.
// TypeError 7743: (61-66): The function "unsub" needs to return exactly one value of type Int to be used for the operator -.
// TypeError 7995: (77-79): The function "gt" needs to return exactly one value of type bool to be used for the operator >.
// TypeError 7995: (90-92): The function "lt" needs to return exactly one value of type bool to be used for the operator <.
// TypeError 2271: (492-517): Operator + not compatible with types Int and Int. No matching user-defined operator found.
// TypeError 2271: (523-548): Operator / not compatible with types Int and Int. No matching user-defined operator found.
// TypeError 4907: (554-566): Unary operator - cannot be applied to type Int. No matching user-defined operator found.
// TypeError 2271: (572-597): Operator < not compatible with types Int and Int. No matching user-defined operator found.
// TypeError 2271: (603-628): Operator > not compatible with types Int and Int. No matching user-defined operator found.
// TypeError 7743: (77-83): The function "bitnot" needs to return exactly one value of type Int to be used for the operator ~.
// TypeError 7995: (94-96): The function "gt" needs to return exactly one value of type bool to be used for the operator >.
// TypeError 7995: (107-109): The function "lt" needs to return exactly one value of type bool to be used for the operator <.
// TypeError 3841: (571-596): User defined operator + needs to return value of type Int.
// TypeError 1208: (602-627): User defined operator / needs to return exactly one value.
// TypeError 3138: (633-645): User defined operator - needs to return exactly one value.
// TypeError 7983: (651-663): User defined operator ~ needs to return value of type Int.
// TypeError 1208: (669-694): User defined operator < needs to return exactly one value.
// TypeError 3841: (700-725): User defined operator > needs to return value of type bool.