Move dynamic type removal out of the type system.

This commit is contained in:
chriseth 2018-02-21 00:40:38 +01:00 committed by Alex Beregszaszi
parent 32c94f5059
commit cc2f71e4ac
4 changed files with 37 additions and 18 deletions

View File

@ -1551,16 +1551,22 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
_functionCall.expression().annotation().isPure && _functionCall.expression().annotation().isPure &&
functionType->isPure(); functionType->isPure();
bool allowDynamicTypes = false; // @TODO
if (!functionType) if (!functionType)
{ {
m_errorReporter.typeError(_functionCall.location(), "Type is not callable"); m_errorReporter.typeError(_functionCall.location(), "Type is not callable");
_functionCall.annotation().type = make_shared<TupleType>(); _functionCall.annotation().type = make_shared<TupleType>();
return false; return false;
} }
else if (functionType->returnParameterTypes().size() == 1)
_functionCall.annotation().type = functionType->returnParameterTypes().front(); auto returnTypes =
allowDynamicTypes ?
functionType->returnParameterTypes() :
functionType->returnParameterTypesWithoutDynamicTypes();
if (returnTypes.size() == 1)
_functionCall.annotation().type = returnTypes.front();
else else
_functionCall.annotation().type = make_shared<TupleType>(functionType->returnParameterTypes()); _functionCall.annotation().type = make_shared<TupleType>(returnTypes);
if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression())) if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{ {

View File

@ -2311,6 +2311,18 @@ vector<string> FunctionType::parameterNames() const
return vector<string>(m_parameterNames.cbegin() + 1, m_parameterNames.cend()); return vector<string>(m_parameterNames.cbegin() + 1, m_parameterNames.cend());
} }
TypePointers FunctionType::returnParameterTypesWithoutDynamicTypes() const
{
TypePointers returnParameterTypes = m_returnParameterTypes;
if (m_kind == Kind::External || m_kind == Kind::CallCode || m_kind == Kind::DelegateCall)
for (auto& param: returnParameterTypes)
if (param->isDynamicallySized() && !param->dataStoredIn(DataLocation::Storage))
param = make_shared<InaccessibleDynamicType>();
return returnParameterTypes;
}
TypePointers FunctionType::parameterTypes() const TypePointers FunctionType::parameterTypes() const
{ {
if (!bound()) if (!bound())
@ -2772,18 +2784,9 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound)
kind = Kind::DelegateCall; kind = Kind::DelegateCall;
} }
TypePointers returnParameterTypes = m_returnParameterTypes;
if (kind != Kind::Internal)
{
// Alter dynamic types to be non-accessible.
for (auto& param: returnParameterTypes)
if (param->isDynamicallySized())
param = make_shared<InaccessibleDynamicType>();
}
return make_shared<FunctionType>( return make_shared<FunctionType>(
parameterTypes, parameterTypes,
returnParameterTypes, m_returnParameterTypes,
m_parameterNames, m_parameterNames,
m_returnParameterNames, m_returnParameterNames,
kind, kind,

View File

@ -973,6 +973,9 @@ public:
TypePointers parameterTypes() const; TypePointers parameterTypes() const;
std::vector<std::string> parameterNames() const; std::vector<std::string> parameterNames() const;
TypePointers const& returnParameterTypes() const { return m_returnParameterTypes; } TypePointers const& returnParameterTypes() const { return m_returnParameterTypes; }
/// @returns the list of return parameter types. All dynamically-sized types (this excludes
/// storage pointers) are replaced by InaccessibleDynamicType instances.
TypePointers returnParameterTypesWithoutDynamicTypes() const;
std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; } std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; }
/// @returns the "self" parameter type for a bound function /// @returns the "self" parameter type for a bound function
TypePointer const& selfType() const; TypePointer const& selfType() const;

View File

@ -139,8 +139,8 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
utils().popStackSlots(paramTypes.size() - 1); utils().popStackSlots(paramTypes.size() - 1);
} }
unsigned retSizeOnStack = 0; unsigned retSizeOnStack = 0;
solAssert(accessorType.returnParameterTypes().size() >= 1, ""); auto returnTypes = accessorType.returnParameterTypes();
auto const& returnTypes = accessorType.returnParameterTypes(); solAssert(returnTypes.size() >= 1, "");
if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get())) if (StructType const* structType = dynamic_cast<StructType const*>(returnType.get()))
{ {
// remove offset // remove offset
@ -1618,15 +1618,22 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context.experimentalFeatureActive(ExperimentalFeature::V050) && m_context.experimentalFeatureActive(ExperimentalFeature::V050) &&
m_context.evmVersion().hasStaticCall(); m_context.evmVersion().hasStaticCall();
bool allowDynamicTypes = false; // @TODO
unsigned retSize = 0; unsigned retSize = 0;
TypePointers returnTypes;
if (returnSuccessCondition) if (returnSuccessCondition)
retSize = 0; // return value actually is success condition retSize = 0; // return value actually is success condition
else if (allowDynamicTypes)
returnTypes = _functionType.returnParameterTypes();
else else
for (auto const& retType: _functionType.returnParameterTypes()) {
returnTypes = _functionType.returnParameterTypesWithoutDynamicTypes();
for (auto const& retType: returnTypes)
{ {
solAssert(!retType->isDynamicallySized(), "Unable to return dynamic type from external call."); solAssert(!retType->isDynamicallySized(), "Unable to return dynamic type from external call.");
retSize += retType->calldataEncodedSize(); retSize += retType->calldataEncodedSize();
} }
}
// Evaluate arguments. // Evaluate arguments.
TypePointers argumentTypes; TypePointers argumentTypes;
@ -1824,11 +1831,11 @@ void ExpressionCompiler::appendExternalFunctionCall(
utils().fetchFreeMemoryPointer(); utils().fetchFreeMemoryPointer();
m_context << Instruction::SUB << Instruction::MLOAD; m_context << Instruction::SUB << Instruction::MLOAD;
} }
else if (!_functionType.returnParameterTypes().empty()) else if (!returnTypes.empty())
{ {
utils().fetchFreeMemoryPointer(); utils().fetchFreeMemoryPointer();
bool memoryNeeded = false; bool memoryNeeded = false;
for (auto const& retType: _functionType.returnParameterTypes()) for (auto const& retType: returnTypes)
{ {
utils().loadFromMemoryDynamic(*retType, false, true, true); utils().loadFromMemoryDynamic(*retType, false, true, true);
if (dynamic_cast<ReferenceType const*>(retType.get())) if (dynamic_cast<ReferenceType const*>(retType.get()))