mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Type::sameTypeOrPointerTo()
This commit is contained in:
parent
acf943005a
commit
5657515f45
@ -282,6 +282,30 @@ string Type::identifier() const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Type::sameTypeOrPointerTo(Type const& _targetType, bool _excludeLocation) const
|
||||||
|
{
|
||||||
|
auto const* thisAsReference = dynamic_cast<ReferenceType const*>(this);
|
||||||
|
auto const* targetAsReference = dynamic_cast<ReferenceType const*>(&_targetType);
|
||||||
|
|
||||||
|
auto thisLocation = DataLocation::Storage;
|
||||||
|
auto targetLocation = DataLocation::Storage;
|
||||||
|
if (thisAsReference && !_excludeLocation)
|
||||||
|
thisLocation = thisAsReference->location();
|
||||||
|
if (targetAsReference && !_excludeLocation)
|
||||||
|
targetLocation = targetAsReference->location();
|
||||||
|
|
||||||
|
if (
|
||||||
|
(!targetAsReference || !targetAsReference->isPointer()) &&
|
||||||
|
(thisAsReference && thisAsReference->isPointer())
|
||||||
|
)
|
||||||
|
return false; // The target is a pointer to our type. We only accept the reverse.
|
||||||
|
|
||||||
|
return
|
||||||
|
// Compare as if both were pointers.
|
||||||
|
*TypeProvider::withLocationIfReference(thisLocation, this, true /* _isPointer */) ==
|
||||||
|
*TypeProvider::withLocationIfReference(targetLocation, &_targetType, true /* _isPointer */);
|
||||||
|
}
|
||||||
|
|
||||||
Type const* Type::commonType(Type const* _a, Type const* _b)
|
Type const* Type::commonType(Type const* _a, Type const* _b)
|
||||||
{
|
{
|
||||||
if (!_a || !_b)
|
if (!_a || !_b)
|
||||||
@ -361,23 +385,19 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
|
|||||||
if (usingFor->global() && usingFor->typeName())
|
if (usingFor->global() && usingFor->typeName())
|
||||||
usingForDirectives.emplace_back(usingFor);
|
usingForDirectives.emplace_back(usingFor);
|
||||||
|
|
||||||
// Normalise data location of type.
|
|
||||||
DataLocation typeLocation = DataLocation::Storage;
|
|
||||||
if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
|
|
||||||
typeLocation = refType->location();
|
|
||||||
|
|
||||||
return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool {
|
return usingForDirectives | ranges::views::filter([&](UsingForDirective const* _directive) -> bool {
|
||||||
// Convert both types to pointers for comparison to see if the `using for` directive applies.
|
if (!_directive->typeName())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Type const& usingForType = *_directive->typeName()->annotation().type;
|
||||||
|
if (auto const* referenceType = dynamic_cast<ReferenceType const*>(&usingForType))
|
||||||
|
// NOTE: We want the type in 'using for' to represent both pointers and values.
|
||||||
|
// sameTypeOrPointerTo() gives us that behavior as long as usingForType.isPointer() is true.
|
||||||
|
solAssert(referenceType->isPointer());
|
||||||
|
|
||||||
// Note that at this point we don't yet know if the functions are actually usable with the type.
|
// Note that at this point we don't yet know if the functions are actually usable with the type.
|
||||||
// `_type` may not be convertible to the function parameter type.
|
// `_type` may not be convertible to the function parameter type.
|
||||||
return
|
return _type.sameTypeOrPointerTo(usingForType, true /* _excludeLocation */);
|
||||||
!_directive->typeName() ||
|
|
||||||
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) ==
|
|
||||||
*TypeProvider::withLocationIfReference(
|
|
||||||
typeLocation,
|
|
||||||
_directive->typeName()->annotation().type,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}) | ranges::to<vector<UsingForDirective const*>>;
|
}) | ranges::to<vector<UsingForDirective const*>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1636,7 +1656,7 @@ BoolResult ArrayType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Conversion to storage pointer or to memory, we de not copy element-for-element here, so
|
// Conversion to storage pointer or to memory, we do not copy element-for-element here, so
|
||||||
// require that the base type is the same, not only convertible.
|
// require that the base type is the same, not only convertible.
|
||||||
// This disallows assignment of nested dynamic arrays from storage to memory for now.
|
// This disallows assignment of nested dynamic arrays from storage to memory for now.
|
||||||
if (
|
if (
|
||||||
|
@ -221,6 +221,15 @@ public:
|
|||||||
virtual bool operator==(Type const& _other) const { return category() == _other.category(); }
|
virtual bool operator==(Type const& _other) const { return category() == _other.category(); }
|
||||||
virtual bool operator!=(Type const& _other) const { return !this->operator ==(_other); }
|
virtual bool operator!=(Type const& _other) const { return !this->operator ==(_other); }
|
||||||
|
|
||||||
|
/// Compares types, accepting both exact matches and pointers. The comparison is not
|
||||||
|
/// symmetric, i.e.. the type may be a pointer to the target type but not the other way around.
|
||||||
|
/// You can think of the target as the left-hand side of an assignment - you can assign a value
|
||||||
|
/// to a pointer (without making a copy) but not a pointer to a value.
|
||||||
|
/// @param _excludeLocation Compare reference types as if both had identical locations.
|
||||||
|
/// @returns true if both types are equal or the object is a reference type that can point at
|
||||||
|
/// values of @a _targetType.
|
||||||
|
bool sameTypeOrPointerTo(Type const& _targetType, bool _excludeLocation = false) const;
|
||||||
|
|
||||||
/// @returns number of bytes used by this type when encoded for CALL. Cannot be used for
|
/// @returns number of bytes used by this type when encoded for CALL. Cannot be used for
|
||||||
/// dynamically encoded types.
|
/// dynamically encoded types.
|
||||||
/// Always returns a value greater than zero and throws if the type cannot be encoded in calldata
|
/// Always returns a value greater than zero and throws if the type cannot be encoded in calldata
|
||||||
|
Loading…
Reference in New Issue
Block a user