Update code to review comments

This commit is contained in:
wechman 2022-07-27 10:42:58 +02:00
parent c1dc8df9c9
commit 3be5114fb0
10 changed files with 50 additions and 27 deletions

View File

@ -1790,7 +1790,7 @@ 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.
FunctionDefinitionResult userDefinedOperatorResult = leftType->userDefinedOperator( Result<FunctionDefinition const*> userDefinedOperatorResult = leftType->userDefinedOperator(
_operation.getOperator(), _operation.getOperator(),
*currentDefinitionScope(), *currentDefinitionScope(),
false // _unaryOperation false // _unaryOperation

View File

@ -59,6 +59,8 @@ using namespace solidity;
using namespace solidity::langutil; using namespace solidity::langutil;
using namespace solidity::frontend; using namespace solidity::frontend;
using util::Result;
namespace namespace
{ {
@ -384,7 +386,7 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
} }
FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const
{ {
if (!typeDefinition()) if (!typeDefinition())
return nullptr; return nullptr;
@ -412,12 +414,10 @@ FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const&
if (seenFunctions.size() == 1) if (seenFunctions.size() == 1)
return *seenFunctions.begin(); return *seenFunctions.begin();
else if (!!typeDefinition() && seenFunctions.size() == 0) else if (seenFunctions.size() == 0)
return FunctionDefinitionResult::err("Operator has not been user-defined."); return Result<FunctionDefinition const*>::err("No matching user-defined operator found.");
else if (!!typeDefinition())
return FunctionDefinitionResult::err("Multiple user-defined functions provided for this operator.");
else else
return nullptr; return Result<FunctionDefinition const*>::err("Multiple user-defined functions provided for this operator.");
} }
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope) MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)

View File

@ -54,7 +54,6 @@ 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*>;
} }
@ -378,7 +377,7 @@ public:
/// Clears all internally cached values (if any). /// Clears all internally cached values (if any).
virtual void clearCache() const; virtual void clearCache() const;
FunctionDefinitionResult userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const; util::Result<FunctionDefinition const*> 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.

View File

@ -416,7 +416,8 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
solAssert(function->isFree(), "Only free functions can be bound to a user type operator."); solAssert(function->isFree(), "Only free functions can be bound to a user type operator.");
FunctionType const* functionType = dynamic_cast<FunctionType const*>( FunctionType const* functionType = dynamic_cast<FunctionType const*>(
function->libraryFunction() ? function->typeViaContractName() : function->type()); function->libraryFunction() ? function->typeViaContractName() : function->type()
);
solAssert(functionType); solAssert(functionType);
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction(); functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();

View File

@ -694,21 +694,22 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation)
"Functions with parameters other than self parameter cannot be bound to a user type unary operator." "Functions with parameters other than self parameter cannot be bound to a user type unary operator."
); );
string parameter = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType()); string argument = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType());
solAssert(!parameter.empty()); solAssert(!argument.empty());
solAssert(function->isImplemented(), ""); solAssert(function->isImplemented(), "");
solAssert( solAssert(
function->returnParameters().size() == 1, function->returnParameters().size() == 1,
"A function bound to the user type operator is supposed to return exactly one value." "A function bound to the user type operator is supposed to return exactly one value."
); );
solAssert(*_unaryOperation.annotation().type == *function->returnParameters().at(0)->type(), solAssert(
*_unaryOperation.annotation().type == *function->returnParameters().at(0)->type(),
"A return type of the bound function is supposed to be same as a operator type." "A return type of the bound function is supposed to be same as a operator type."
); );
define(_unaryOperation) << define(_unaryOperation) <<
m_context.enqueueFunctionForCodeGeneration(*function) << m_context.enqueueFunctionForCodeGeneration(*function) <<
("(" + parameter + ")\n"); ("(" + argument + ")\n");
return false; return false;
} }

View File

@ -1,11 +1,22 @@
struct S { bool f; } struct S {
uint v;
}
using {bitand as &} for S;
function bitand(S storage, S storage) returns (S storage) {
S storage rTmp;
return rTmp;
}
contract C { contract C {
function f() public view { S s;
S storage s; function f() public {
s.f && true; S storage sTmp;
sTmp & s;
} }
} }
// ---- // ----
// TypeError 3464: (95-96): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. // TypeError 3464: (145-149): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError 3464: (234-238): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.

View File

@ -1,11 +1,22 @@
struct S { bool f; } struct S {
uint v;
}
using {bitor as |} for S;
function bitor(S storage, S storage) returns (S storage) {
S storage rTmp;
return rTmp;
}
contract C { contract C {
function f() public view { S s;
S storage s; function f() public {
s.f || true; S storage sTmp;
sTmp | s;
} }
} }
// ---- // ----
// TypeError 3464: (95-96): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. // TypeError 3464: (143-147): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.
// TypeError 3464: (232-236): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.

View File

@ -7,4 +7,4 @@ contract test {
} }
} }
// ---- // ----
// TypeError 2271: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref. Operator has not been user-defined. // TypeError 2271: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref. No matching user-defined operator found.

View File

@ -2,7 +2,7 @@ type Int is int128;
using { using {
add as +, sub as -, add as +, sub as -,
mul as *, div as / mul as *, div as /
} for Int; } for Int;
function add(Int, Int) pure returns (Int) { function add(Int, Int) pure returns (Int) {
return Int.wrap(1); return Int.wrap(1);

View File

@ -4,7 +4,7 @@ using {
add as +, sub as -, add as +, sub as -,
mul as *, div as /, mul as *, div as /,
gt as >, lt as < gt as >, lt as <
} for Int; } for Int;
function add(Int) pure returns (Int) { function add(Int) pure returns (Int) {
return Int.wrap(0); return Int.wrap(0);