diff --git a/Changelog.md b/Changelog.md index a344d516d..55238ed12 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,7 @@ Bugfixes: * SMTChecker: Fix internal error when encoding tuples of tuples. * SMTChecker: Fix aliasing soundness after pushing to an array pointer. * Type system: Fix internal compiler error on calling externally a function that returns variables with calldata location. + * Type system: Fix bug where a bound function was not found if ``using for`` is applied to explicit reference types. ### 0.6.9 (2020-06-04) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 160ab0b0c..bb202e875 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -356,10 +356,18 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition for (ContractDefinition const* contract: _scope.annotation().linearizedBaseContracts) for (UsingForDirective const* ufd: contract->usingForDirectives()) { - if (ufd->typeName() && _type != *TypeProvider::withLocationIfReference( - typeLocation, - ufd->typeName()->annotation().type - )) + // Convert both types to pointers for comparison to see if the `using for` + // directive applies. + // Further down, we check more detailed for each function if `_type` is + // convertible to the function parameter type. + if (ufd->typeName() && + *TypeProvider::withLocationIfReference(typeLocation, &_type, true) != + *TypeProvider::withLocationIfReference( + typeLocation, + ufd->typeName()->annotation().type, + true + ) + ) continue; auto const& library = dynamic_cast( *ufd->libraryName().annotation().referencedDeclaration diff --git a/test/libsolidity/semanticTests/libraries/using_for_storage_structs.sol b/test/libsolidity/semanticTests/libraries/using_for_storage_structs.sol new file mode 100644 index 000000000..cd45726b6 --- /dev/null +++ b/test/libsolidity/semanticTests/libraries/using_for_storage_structs.sol @@ -0,0 +1,25 @@ +struct Struct { uint x; } + +library L { + function f(Struct storage _x) internal view returns (uint256) { + return _x.x; + } +} + +contract C { + using L for Struct; + + Struct s; + + function h(Struct storage _s) internal view returns (uint) { + // _s is pointer + return _s.f(); + } + function g() public returns (uint, uint) { + s.x = 7; + // s is reference + return (s.f(), h(s)); + } +} +// ---- +// g() -> 7, 7