48
48
#include < range/v3/view/reverse.hpp>
49
49
#include < range/v3/view/tail.hpp>
50
50
#include < range/v3/view/transform.hpp>
51
+ #include < range/v3/view/filter.hpp>
51
52
52
53
#include < limits>
53
54
#include < unordered_set>
@@ -337,7 +338,10 @@ Type const* Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
337
338
return encodingType;
338
339
}
339
340
340
- MemberList::MemberMap Type::boundFunctions (Type const & _type, ASTNode const & _scope)
341
+ namespace
342
+ {
343
+
344
+ vector<UsingForDirective const *> usingForDirectivesForType (Type const & _type, ASTNode const & _scope)
341
345
{
342
346
vector<UsingForDirective const *> usingForDirectives;
343
347
SourceUnit const * sourceUnit = dynamic_cast <SourceUnit const *>(&_scope);
@@ -362,6 +366,25 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
362
366
if (auto refType = dynamic_cast <ReferenceType const *>(&_type))
363
367
typeLocation = refType->location ();
364
368
369
+ return usingForDirectives | ranges::views::filter ([&](UsingForDirective const * _directive) -> bool {
370
+ // Convert both types to pointers for comparison to see if the `using for` directive applies.
371
+ // Note that at this point we don't yet know if the functions are actually usable with the type.
372
+ // `_type` may not be convertible to the function parameter type.
373
+ return
374
+ !_directive->typeName () ||
375
+ *TypeProvider::withLocationIfReference (typeLocation, &_type, true ) ==
376
+ *TypeProvider::withLocationIfReference (
377
+ typeLocation,
378
+ _directive->typeName ()->annotation ().type ,
379
+ true
380
+ );
381
+ }) | ranges::to<vector<UsingForDirective const *>>;
382
+ }
383
+
384
+ }
385
+
386
+ MemberList::MemberMap Type::boundFunctions (Type const & _type, ASTNode const & _scope)
387
+ {
365
388
MemberList::MemberMap members;
366
389
367
390
set<pair<string, Declaration const *>> seenFunctions;
@@ -381,27 +404,11 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
381
404
members.emplace_back (&_function, asBoundFunction, *_name);
382
405
};
383
406
384
- for (UsingForDirective const * ufd: usingForDirectives)
385
- {
386
- // Convert both types to pointers for comparison to see if the `using for`
387
- // directive applies.
388
- // Further down, we check more detailed for each function if `_type` is
389
- // convertible to the function parameter type.
390
- if (
391
- ufd->typeName () &&
392
- *TypeProvider::withLocationIfReference (typeLocation, &_type, true ) !=
393
- *TypeProvider::withLocationIfReference (
394
- typeLocation,
395
- ufd->typeName ()->annotation ().type ,
396
- true
397
- )
398
- )
399
- continue ;
400
-
401
- for (auto const & pathPointer: ufd->functionsOrLibrary ())
407
+ for (UsingForDirective const * ufd: usingForDirectivesForType (_type, _scope))
408
+ for (auto const & identifierPath: ufd->functionsOrLibrary ())
402
409
{
403
- solAssert (pathPointer );
404
- Declaration const * declaration = pathPointer ->annotation ().referencedDeclaration ;
410
+ solAssert (identifierPath );
411
+ Declaration const * declaration = identifierPath ->annotation ().referencedDeclaration ;
405
412
solAssert (declaration);
406
413
407
414
if (ContractDefinition const * library = dynamic_cast <ContractDefinition const *>(declaration))
@@ -417,10 +424,9 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _sc
417
424
else
418
425
addFunction (
419
426
dynamic_cast <FunctionDefinition const &>(*declaration),
420
- pathPointer ->path ().back ()
427
+ identifierPath ->path ().back ()
421
428
);
422
429
}
423
- }
424
430
425
431
return members;
426
432
}
0 commit comments