mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add InlineArrayType to support literals conversion to statically and dynamically allocated arrays.
This commit is contained in:
@@ -67,6 +67,13 @@ bool TypeChecker::typeSupportedByOldABIEncoder(Type const& _type, bool _isLibrar
|
||||
if (!typeSupportedByOldABIEncoder(*base, _isLibraryCall) || (base->category() == Type::Category::Array && base->isDynamicallySized()))
|
||||
return false;
|
||||
}
|
||||
if (_type.category() == Type::Category::InlineArray)
|
||||
{
|
||||
auto const& mobileType = dynamic_cast<InlineArrayType const&>(_type).mobileType();
|
||||
if (!mobileType)
|
||||
return false;
|
||||
return typeSupportedByOldABIEncoder(*mobileType, _isLibraryCall);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1647,7 +1654,6 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
else
|
||||
{
|
||||
bool isPure = true;
|
||||
Type const* inlineArrayType = nullptr;
|
||||
|
||||
for (size_t i = 0; i < components.size(); ++i)
|
||||
{
|
||||
@@ -1662,7 +1668,8 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
{
|
||||
if (_tuple.isInlineArray())
|
||||
m_errorReporter.fatalTypeError(5604_error, components[i]->location(), "Array component cannot be empty.");
|
||||
m_errorReporter.typeError(6473_error, components[i]->location(), "Tuple component cannot be empty.");
|
||||
else
|
||||
m_errorReporter.typeError(6473_error, components[i]->location(), "Tuple component cannot be empty.");
|
||||
}
|
||||
|
||||
// Note: code generation will visit each of the expression even if they are not assigned from.
|
||||
@@ -1670,48 +1677,37 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
|
||||
if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType())
|
||||
m_errorReporter.fatalTypeError(3390_error, components[i]->location(), "Invalid rational number.");
|
||||
|
||||
if (_tuple.isInlineArray())
|
||||
if (_tuple.isInlineArray() &&
|
||||
types[i]->category() != Type::Category::InlineArray)
|
||||
{
|
||||
solAssert(!!types[i], "Inline array cannot have empty components");
|
||||
|
||||
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
|
||||
Type const* mobileType = types[i]->mobileType();
|
||||
if (!mobileType)
|
||||
m_errorReporter.fatalTypeError(9563_error, components[i]->location(), "Invalid mobile type.");
|
||||
|
||||
if (i == 0)
|
||||
inlineArrayType = types[i]->mobileType();
|
||||
else if (inlineArrayType)
|
||||
inlineArrayType = Type::commonType(inlineArrayType, types[i]);
|
||||
else if (!mobileType->nameable())
|
||||
m_errorReporter.fatalTypeError(
|
||||
9656_error,
|
||||
_tuple.location(),
|
||||
"Unable to deduce nameable type for array elements. Try adding explicit type conversion for the first element."
|
||||
);
|
||||
else if (mobileType->containsNestedMapping())
|
||||
m_errorReporter.fatalTypeError(
|
||||
1545_error,
|
||||
_tuple.location(),
|
||||
"Type " + types[i]->humanReadableName() + " is only valid in storage."
|
||||
);
|
||||
}
|
||||
|
||||
if (!*components[i]->annotation().isPure)
|
||||
isPure = false;
|
||||
}
|
||||
_tuple.annotation().isPure = isPure;
|
||||
if (_tuple.isInlineArray())
|
||||
{
|
||||
if (!inlineArrayType)
|
||||
m_errorReporter.fatalTypeError(6378_error, _tuple.location(), "Unable to deduce common type for array elements.");
|
||||
else if (!inlineArrayType->nameable())
|
||||
m_errorReporter.fatalTypeError(
|
||||
9656_error,
|
||||
_tuple.location(),
|
||||
"Unable to deduce nameable type for array elements. Try adding explicit type conversion for the first element."
|
||||
);
|
||||
else if (inlineArrayType->containsNestedMapping())
|
||||
m_errorReporter.fatalTypeError(
|
||||
1545_error,
|
||||
_tuple.location(),
|
||||
"Type " + inlineArrayType->humanReadableName() + " is only valid in storage."
|
||||
);
|
||||
|
||||
_tuple.annotation().type = TypeProvider::array(DataLocation::Memory, inlineArrayType, types.size());
|
||||
}
|
||||
if (_tuple.isInlineArray())
|
||||
_tuple.annotation().type = TypeProvider::inlineArray(move(types));
|
||||
else if (components.size() == 1)
|
||||
_tuple.annotation().type = type(*components[0]);
|
||||
else
|
||||
{
|
||||
if (components.size() == 1)
|
||||
_tuple.annotation().type = type(*components[0]);
|
||||
else
|
||||
_tuple.annotation().type = TypeProvider::tuple(move(types));
|
||||
}
|
||||
_tuple.annotation().type = TypeProvider::tuple(move(types));
|
||||
|
||||
_tuple.annotation().isLValue = false;
|
||||
}
|
||||
@@ -2105,10 +2101,9 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
}
|
||||
|
||||
// Check additional arguments for variadic functions
|
||||
vector<ASTPointer<Expression const>> const& arguments = _functionCall.arguments();
|
||||
for (size_t i = 0; i < arguments.size(); ++i)
|
||||
for (auto const& argument: _functionCall.arguments())
|
||||
{
|
||||
auto const& argType = type(*arguments[i]);
|
||||
Type const* argType = type(*argument);
|
||||
|
||||
if (argType->category() == Type::Category::RationalNumber)
|
||||
{
|
||||
@@ -2117,7 +2112,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
6090_error,
|
||||
arguments[i]->location(),
|
||||
argument->location(),
|
||||
"Fractional numbers cannot yet be encoded."
|
||||
);
|
||||
continue;
|
||||
@@ -2126,7 +2121,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
8009_error,
|
||||
arguments[i]->location(),
|
||||
argument->location(),
|
||||
"Invalid rational number (too large or division by zero)."
|
||||
);
|
||||
continue;
|
||||
@@ -2135,7 +2130,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
7279_error,
|
||||
arguments[i]->location(),
|
||||
argument->location(),
|
||||
"Cannot perform packed encoding for a literal."
|
||||
" Please convert it to an explicit type first."
|
||||
);
|
||||
@@ -2147,7 +2142,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
{
|
||||
m_errorReporter.typeError(
|
||||
9578_error,
|
||||
arguments[i]->location(),
|
||||
argument->location(),
|
||||
"Type not supported in packed mode."
|
||||
);
|
||||
continue;
|
||||
@@ -2156,7 +2151,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
if (!argType->fullEncodingType(false, abiEncoderV2, !_functionType->padArguments()))
|
||||
m_errorReporter.typeError(
|
||||
2056_error,
|
||||
arguments[i]->location(),
|
||||
argument->location(),
|
||||
"This type cannot be encoded."
|
||||
);
|
||||
}
|
||||
@@ -3361,6 +3356,16 @@ bool TypeChecker::visit(IndexAccess const& _access)
|
||||
isLValue = actualType.location() != DataLocation::CallData;
|
||||
break;
|
||||
}
|
||||
case Type::Category::InlineArray:
|
||||
{
|
||||
if (!index)
|
||||
m_errorReporter.typeError(5093_error, _access.location(), "Index expression cannot be omitted.");
|
||||
else
|
||||
expectType(*index, *TypeProvider::uint256());
|
||||
|
||||
resultType = dynamic_cast<InlineArrayType const&>(*baseType).componentsCommonMobileType();
|
||||
break;
|
||||
}
|
||||
case Type::Category::Mapping:
|
||||
{
|
||||
MappingType const& actualType = dynamic_cast<MappingType const&>(*baseType);
|
||||
@@ -3469,6 +3474,8 @@ bool TypeChecker::visit(IndexRangeAccess const& _access)
|
||||
ArrayType const* arrayType = nullptr;
|
||||
if (auto const* arraySlice = dynamic_cast<ArraySliceType const*>(exprType))
|
||||
arrayType = &arraySlice->arrayType();
|
||||
else if (auto const* inlineArray = dynamic_cast<InlineArrayType const*>(exprType))
|
||||
arrayType = TypeProvider::array(DataLocation::Memory, inlineArray->componentsCommonMobileType(), inlineArray->components().size());
|
||||
else if (!(arrayType = dynamic_cast<ArrayType const*>(exprType)))
|
||||
m_errorReporter.fatalTypeError(4781_error, _access.location(), "Index range access is only possible for arrays and array slices.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user