diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index adcd2e542..8cc1f2589 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -537,7 +537,19 @@ TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const { - return _convertTo.getCategory() == getCategory(); + if (_convertTo.getCategory() != getCategory()) + return false; + auto& convertTo = dynamic_cast(_convertTo); + // let us not allow assignment to memory arrays for now + if (convertTo.getLocation() != Location::Storage) + return false; + if (convertTo.isByteArray() != isByteArray()) + return false; + if (!getBaseType()->isImplicitlyConvertibleTo(*convertTo.getBaseType())) + return false; + if (convertTo.isDynamicallySized()) + return true; + return !isDynamicallySized() && convertTo.getLength() >= getLength(); } TypePointer ArrayType::unaryOperatorResult(Token::Value _operator) const @@ -552,7 +564,10 @@ bool ArrayType::operator==(Type const& _other) const if (_other.getCategory() != getCategory()) return false; ArrayType const& other = dynamic_cast(_other); - return other.m_location == m_location; + if (other.m_location != m_location || other.isByteArray() != isByteArray() || + other.isDynamicallySized() != isDynamicallySized()) + return false; + return isDynamicallySized() || getLength() == other.getLength(); } u256 ArrayType::getStorageSize() const diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 4809aac1e..ff9fa1655 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -1185,6 +1185,61 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); } +BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) +{ + char const* text = R"( + contract c { + bytes a; + uint[] b; + function f() { b = a; } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) +{ + char const* text = R"( + contract c { + uint32[] a; + uint8[] b; + function f() { b = a; } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + +BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) +{ + char const* text = R"( + contract c { + uint32[] a; + uint8[] b; + function f() { a = b; } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic) +{ + char const* text = R"( + contract c { + uint32[] a; + uint8[80] b; + function f() { a = b; } + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + +BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) +{ + char const* text = R"( + contract c { + uint[] a; + uint[80] b; + function f() { b = a; } + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() }