@@ -397,20 +397,23 @@ module Impl {
397397 )
398398 }
399399
400- private newtype TVariableOrAccessCand =
401- TVariableOrAccessCandVariable ( Variable v ) or
402- TVariableOrAccessCandVariableAccessCand ( VariableAccessCand va )
400+ private newtype TDefOrAccessCand =
401+ TDefOrAccessCandNestedFunction ( Function f , BlockExprScope scope ) {
402+ f = scope .getStmtList ( ) .getAStatement ( )
403+ } or
404+ TDefOrAccessCandVariable ( Variable v ) or
405+ TDefOrAccessCandVariableAccessCand ( VariableAccessCand va )
403406
404407 /**
405- * A variable declaration or variable access candidate.
408+ * A nested function declaration, variable declaration, or variable (or function)
409+ * access candidate.
406410 *
407- * In order to determine whether a candidate is an actual variable access,
408- * we rank declarations and candidates by their position in source code .
411+ * In order to determine whether a candidate is an actual variable/function access,
412+ * we rank declarations and candidates by their position in the AST .
409413 *
410- * The ranking must take variable names into account, but also variable scopes;
411- * below a comment `rank(scope, name, i)` means that the declaration/access on
412- * the given line has rank `i` amongst all declarations/accesses inside variable
413- * scope `scope`, for variable name `name`:
414+ * The ranking must take names into account, but also variable scopes; below a comment
415+ * `rank(scope, name, i)` means that the declaration/access on the given line has rank
416+ * `i` amongst all declarations/accesses inside variable scope `scope`, for name `name`:
414417 *
415418 * ```rust
416419 * fn f() { // scope0
@@ -430,8 +433,8 @@ module Impl {
430433 * }
431434 * ```
432435 *
433- * Variable declarations are only ranked in the scope that they bind into, while
434- * accesses candidates propagate outwards through scopes, as they may access
436+ * Function/variable declarations are only ranked in the scope that they bind into,
437+ * while accesses candidates propagate outwards through scopes, as they may access
435438 * declarations from outer scopes.
436439 *
437440 * For an access candidate with ranks `{ rank(scope_i, name, rnk_i) | i in I }` and
@@ -448,41 +451,80 @@ module Impl {
448451 * i.e., its the nearest declaration before the access in the same (or outer) scope
449452 * as the access.
450453 */
451- private class VariableOrAccessCand extends TVariableOrAccessCand {
452- Variable asVariable ( ) { this = TVariableOrAccessCandVariable ( result ) }
454+ abstract private class DefOrAccessCand extends TDefOrAccessCand {
455+ abstract string toString ( ) ;
453456
454- VariableAccessCand asVariableAccessCand ( ) {
455- this = TVariableOrAccessCandVariableAccessCand ( result )
456- }
457+ abstract Location getLocation ( ) ;
457458
458- string toString ( ) {
459- result = this . asVariable ( ) . toString ( ) or result = this . asVariableAccessCand ( ) . toString ( )
460- }
459+ pragma [ nomagic ]
460+ abstract predicate rankBy ( string name , VariableScope scope , int ord , int kind ) ;
461+ }
461462
462- Location getLocation ( ) {
463- result = this .asVariable ( ) .getLocation ( ) or result = this .asVariableAccessCand ( ) .getLocation ( )
464- }
463+ abstract private class NestedFunctionOrVariable extends DefOrAccessCand { }
465464
466- pragma [ nomagic]
467- predicate rankBy ( string name , VariableScope scope , int ord , int kind ) {
468- variableDeclInScope ( this .asVariable ( ) , scope , name , ord ) and
465+ private class DefOrAccessCandNestedFunction extends NestedFunctionOrVariable ,
466+ TDefOrAccessCandNestedFunction
467+ {
468+ private Function f ;
469+ private BlockExprScope scope_ ;
470+
471+ DefOrAccessCandNestedFunction ( ) { this = TDefOrAccessCandNestedFunction ( f , scope_ ) }
472+
473+ override string toString ( ) { result = f .toString ( ) }
474+
475+ override Location getLocation ( ) { result = f .getLocation ( ) }
476+
477+ override predicate rankBy ( string name , VariableScope scope , int ord , int kind ) {
478+ // nested functions behave as if they are defined at the beginning of the scope
479+ name = f .getName ( ) .getText ( ) and
480+ scope = scope_ and
481+ ord = 0 and
469482 kind = 0
470- or
471- variableAccessCandInScope ( this .asVariableAccessCand ( ) , scope , name , _, ord ) and
483+ }
484+ }
485+
486+ private class DefOrAccessCandVariable extends NestedFunctionOrVariable , TDefOrAccessCandVariable {
487+ private Variable v ;
488+
489+ DefOrAccessCandVariable ( ) { this = TDefOrAccessCandVariable ( v ) }
490+
491+ override string toString ( ) { result = v .toString ( ) }
492+
493+ override Location getLocation ( ) { result = v .getLocation ( ) }
494+
495+ override predicate rankBy ( string name , VariableScope scope , int ord , int kind ) {
496+ variableDeclInScope ( v , scope , name , ord ) and
472497 kind = 1
473498 }
474499 }
475500
501+ private class DefOrAccessCandVariableAccessCand extends DefOrAccessCand ,
502+ TDefOrAccessCandVariableAccessCand
503+ {
504+ private VariableAccessCand va ;
505+
506+ DefOrAccessCandVariableAccessCand ( ) { this = TDefOrAccessCandVariableAccessCand ( va ) }
507+
508+ override string toString ( ) { result = va .toString ( ) }
509+
510+ override Location getLocation ( ) { result = va .getLocation ( ) }
511+
512+ override predicate rankBy ( string name , VariableScope scope , int ord , int kind ) {
513+ variableAccessCandInScope ( va , scope , name , _, ord ) and
514+ kind = 2
515+ }
516+ }
517+
476518 private module DenseRankInput implements DenseRankInputSig2 {
477519 class C1 = VariableScope ;
478520
479521 class C2 = string ;
480522
481- class Ranked = VariableOrAccessCand ;
523+ class Ranked = DefOrAccessCand ;
482524
483- int getRank ( VariableScope scope , string name , VariableOrAccessCand v ) {
525+ int getRank ( VariableScope scope , string name , DefOrAccessCand v ) {
484526 v =
485- rank [ result ] ( VariableOrAccessCand v0 , int ord , int kind |
527+ rank [ result ] ( DefOrAccessCand v0 , int ord , int kind |
486528 v0 .rankBy ( name , scope , ord , kind )
487529 |
488530 v0 order by ord , kind
@@ -494,7 +536,7 @@ module Impl {
494536 * Gets the rank of `v` amongst all other declarations or access candidates
495537 * to a variable named `name` in the variable scope `scope`.
496538 */
497- private int rankVariableOrAccess ( VariableScope scope , string name , VariableOrAccessCand v ) {
539+ private int rankVariableOrAccess ( VariableScope scope , string name , DefOrAccessCand v ) {
498540 v = DenseRank2< DenseRankInput > :: denseRank ( scope , name , result + 1 )
499541 }
500542
@@ -512,25 +554,38 @@ module Impl {
512554 * the declaration at rank 0 can only reach the access at rank 1, while the declaration
513555 * at rank 2 can only reach the access at rank 3.
514556 */
515- private predicate variableReachesRank ( VariableScope scope , string name , Variable v , int rnk ) {
516- rnk = rankVariableOrAccess ( scope , name , TVariableOrAccessCandVariable ( v ) )
557+ private predicate variableReachesRank (
558+ VariableScope scope , string name , NestedFunctionOrVariable v , int rnk
559+ ) {
560+ rnk = rankVariableOrAccess ( scope , name , v )
517561 or
518562 variableReachesRank ( scope , name , v , rnk - 1 ) and
519- rnk = rankVariableOrAccess ( scope , name , TVariableOrAccessCandVariableAccessCand ( _) )
563+ rnk = rankVariableOrAccess ( scope , name , TDefOrAccessCandVariableAccessCand ( _) )
520564 }
521565
522566 private predicate variableReachesCand (
523- VariableScope scope , string name , Variable v , VariableAccessCand cand , int nestLevel
567+ VariableScope scope , string name , NestedFunctionOrVariable v , VariableAccessCand cand ,
568+ int nestLevel
524569 ) {
525570 exists ( int rnk |
526571 variableReachesRank ( scope , name , v , rnk ) and
527- rnk = rankVariableOrAccess ( scope , name , TVariableOrAccessCandVariableAccessCand ( cand ) ) and
572+ rnk = rankVariableOrAccess ( scope , name , TDefOrAccessCandVariableAccessCand ( cand ) ) and
528573 variableAccessCandInScope ( cand , scope , name , nestLevel , _)
529574 )
530575 }
531576
577+ pragma [ nomagic]
578+ predicate access ( string name , NestedFunctionOrVariable v , VariableAccessCand cand ) {
579+ v =
580+ min ( NestedFunctionOrVariable v0 , int nestLevel |
581+ variableReachesCand ( _, name , v0 , cand , nestLevel )
582+ |
583+ v0 order by nestLevel
584+ )
585+ }
586+
532587 /** A variable access. */
533- class VariableAccess extends PathExprBaseImpl:: PathExprBase instanceof VariableAccessCand {
588+ class VariableAccess extends PathExprBaseImpl:: PathExprBase {
534589 private string name ;
535590 private Variable v ;
536591
@@ -574,6 +629,16 @@ module Impl {
574629 }
575630 }
576631
632+ /** A nested function access. */
633+ class NestedFunctionAccess extends PathExprBaseImpl:: PathExprBase {
634+ private Function f ;
635+
636+ NestedFunctionAccess ( ) { nestedFunctionAccess ( _, f , this ) }
637+
638+ /** Gets the function being accessed. */
639+ Function getFunction ( ) { result = f }
640+ }
641+
577642 cached
578643 private module Cached {
579644 cached
@@ -582,12 +647,12 @@ module Impl {
582647
583648 cached
584649 predicate variableAccess ( string name , Variable v , VariableAccessCand cand ) {
585- v =
586- min ( Variable v0 , int nestLevel |
587- variableReachesCand ( _ , name , v0 , cand , nestLevel )
588- |
589- v0 order by nestLevel
590- )
650+ access ( name , TDefOrAccessCandVariable ( v ) , cand )
651+ }
652+
653+ cached
654+ predicate nestedFunctionAccess ( string name , Function f , VariableAccessCand cand ) {
655+ access ( name , TDefOrAccessCandNestedFunction ( f , _ ) , cand )
591656 }
592657 }
593658
0 commit comments