diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d9a4bc7d2..5378f15fb 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -139,14 +139,21 @@ TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall c toString(arguments.size()) + " were provided." ); - if (arguments.size() >= 1 && !type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType::bytesMemory())) - m_errorReporter.typeError( - arguments.front()->location(), - "Invalid type for argument in function call. " - "Invalid implicit conversion from " + - type(*arguments.front())->toString() + - " to bytes memory requested." - ); + + if (arguments.size() >= 1) + { + BoolResult result = type(*arguments.front())->isImplicitlyConvertibleTo(ArrayType::bytesMemory()); + + if (!result) + m_errorReporter.typeErrorConcatenateDescriptions( + arguments.front()->location(), + "Invalid type for argument in function call. " + "Invalid implicit conversion from " + + type(*arguments.front())->toString() + + " to bytes memory requested.", + result.message() + ); + } if (arguments.size() < 2) return {}; @@ -262,16 +269,20 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance) ); } for (size_t i = 0; i < std::min(arguments->size(), parameterTypes.size()); ++i) - if (!type(*(*arguments)[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) - m_errorReporter.typeError( + { + BoolResult result = type(*(*arguments)[i])->isImplicitlyConvertibleTo(*parameterTypes[i]); + if (!result) + m_errorReporter.typeErrorConcatenateDescriptions( (*arguments)[i]->location(), "Invalid type for argument in constructor call. " "Invalid implicit conversion from " + type(*(*arguments)[i])->toString() + " to " + parameterTypes[i]->toString() + - " requested." + " requested.", + result.message() ); + } } } @@ -566,16 +577,20 @@ void TypeChecker::visitManually( return; } for (size_t i = 0; i < arguments.size(); ++i) - if (!type(*arguments[i])->isImplicitlyConvertibleTo(*type(*(*parameters)[i]))) - m_errorReporter.typeError( + { + BoolResult result = type(*arguments[i])->isImplicitlyConvertibleTo(*type(*(*parameters)[i])); + if (!result) + m_errorReporter.typeErrorConcatenateDescriptions( arguments[i]->location(), "Invalid type for argument in modifier invocation. " "Invalid implicit conversion from " + type(*arguments[i])->toString() + " to " + type(*(*parameters)[i])->toString() + - " requested." + " requested.", + result.message() ); + } } bool TypeChecker::visit(EventDefinition const& _eventDef) @@ -767,29 +782,34 @@ void TypeChecker::endVisit(Return const& _return) { if (tupleType->components().size() != params->parameters().size()) m_errorReporter.typeError(_return.location(), "Different number of arguments in return statement than in returns declaration."); - else if (!tupleType->isImplicitlyConvertibleTo(TupleType(returnTypes))) - m_errorReporter.typeError( - _return.expression()->location(), - "Return argument type " + - type(*_return.expression())->toString() + - " is not implicitly convertible to expected type " + - TupleType(returnTypes).toString(false) + - "." - ); + else + { + BoolResult result = tupleType->isImplicitlyConvertibleTo(TupleType(returnTypes)); + if (!result) + m_errorReporter.typeErrorConcatenateDescriptions( + _return.expression()->location(), + "Return argument type " + + type(*_return.expression())->toString() + + " is not implicitly convertible to expected type " + + TupleType(returnTypes).toString(false) + ".", + result.message() + ); + } } else if (params->parameters().size() != 1) m_errorReporter.typeError(_return.location(), "Different number of arguments in return statement than in returns declaration."); else { TypePointer const& expected = type(*params->parameters().front()); - if (!type(*_return.expression())->isImplicitlyConvertibleTo(*expected)) - m_errorReporter.typeError( + BoolResult result = type(*_return.expression())->isImplicitlyConvertibleTo(*expected); + if (!result) + m_errorReporter.typeErrorConcatenateDescriptions( _return.expression()->location(), "Return argument type " + type(*_return.expression())->toString() + " is not implicitly convertible to expected type (type of first return variable) " + - expected->toString() + - "." + expected->toString() + ".", + result.message() ); } } @@ -981,7 +1001,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) else { var.accept(*this); - if (!valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type)) + BoolResult result = valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type); + if (!result) { auto errorMsg = "Type " + valueComponentType->toString() + @@ -1008,7 +1029,11 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) ); } else - m_errorReporter.typeError(_statement.location(), errorMsg + "."); + m_errorReporter.typeErrorConcatenateDescriptions( + _statement.location(), + errorMsg + ".", + result.message() + ); } } }