@@ -397,20 +397,23 @@ module Impl {
397
397
)
398
398
}
399
399
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 )
403
406
404
407
/**
405
- * A variable declaration or variable access candidate.
408
+ * A nested function declaration, variable declaration, or variable (or function)
409
+ * access candidate.
406
410
*
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 .
409
413
*
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`:
414
417
*
415
418
* ```rust
416
419
* fn f() { // scope0
@@ -430,8 +433,8 @@ module Impl {
430
433
* }
431
434
* ```
432
435
*
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
435
438
* declarations from outer scopes.
436
439
*
437
440
* For an access candidate with ranks `{ rank(scope_i, name, rnk_i) | i in I }` and
@@ -448,41 +451,80 @@ module Impl {
448
451
* i.e., its the nearest declaration before the access in the same (or outer) scope
449
452
* as the access.
450
453
*/
451
- private class VariableOrAccessCand extends TVariableOrAccessCand {
452
- Variable asVariable ( ) { this = TVariableOrAccessCandVariable ( result ) }
454
+ abstract private class DefOrAccessCand extends TDefOrAccessCand {
455
+ abstract string toString ( ) ;
453
456
454
- VariableAccessCand asVariableAccessCand ( ) {
455
- this = TVariableOrAccessCandVariableAccessCand ( result )
456
- }
457
+ abstract Location getLocation ( ) ;
457
458
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
+ }
461
462
462
- Location getLocation ( ) {
463
- result = this .asVariable ( ) .getLocation ( ) or result = this .asVariableAccessCand ( ) .getLocation ( )
464
- }
463
+ abstract private class NestedFunctionOrVariable extends DefOrAccessCand { }
465
464
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
469
482
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
472
497
kind = 1
473
498
}
474
499
}
475
500
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
+
476
518
private module DenseRankInput implements DenseRankInputSig2 {
477
519
class C1 = VariableScope ;
478
520
479
521
class C2 = string ;
480
522
481
- class Ranked = VariableOrAccessCand ;
523
+ class Ranked = DefOrAccessCand ;
482
524
483
- int getRank ( VariableScope scope , string name , VariableOrAccessCand v ) {
525
+ int getRank ( VariableScope scope , string name , DefOrAccessCand v ) {
484
526
v =
485
- rank [ result ] ( VariableOrAccessCand v0 , int ord , int kind |
527
+ rank [ result ] ( DefOrAccessCand v0 , int ord , int kind |
486
528
v0 .rankBy ( name , scope , ord , kind )
487
529
|
488
530
v0 order by ord , kind
@@ -494,7 +536,7 @@ module Impl {
494
536
* Gets the rank of `v` amongst all other declarations or access candidates
495
537
* to a variable named `name` in the variable scope `scope`.
496
538
*/
497
- private int rankVariableOrAccess ( VariableScope scope , string name , VariableOrAccessCand v ) {
539
+ private int rankVariableOrAccess ( VariableScope scope , string name , DefOrAccessCand v ) {
498
540
v = DenseRank2< DenseRankInput > :: denseRank ( scope , name , result + 1 )
499
541
}
500
542
@@ -512,25 +554,38 @@ module Impl {
512
554
* the declaration at rank 0 can only reach the access at rank 1, while the declaration
513
555
* at rank 2 can only reach the access at rank 3.
514
556
*/
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 )
517
561
or
518
562
variableReachesRank ( scope , name , v , rnk - 1 ) and
519
- rnk = rankVariableOrAccess ( scope , name , TVariableOrAccessCandVariableAccessCand ( _) )
563
+ rnk = rankVariableOrAccess ( scope , name , TDefOrAccessCandVariableAccessCand ( _) )
520
564
}
521
565
522
566
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
524
569
) {
525
570
exists ( int rnk |
526
571
variableReachesRank ( scope , name , v , rnk ) and
527
- rnk = rankVariableOrAccess ( scope , name , TVariableOrAccessCandVariableAccessCand ( cand ) ) and
572
+ rnk = rankVariableOrAccess ( scope , name , TDefOrAccessCandVariableAccessCand ( cand ) ) and
528
573
variableAccessCandInScope ( cand , scope , name , nestLevel , _)
529
574
)
530
575
}
531
576
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
+
532
587
/** A variable access. */
533
- class VariableAccess extends PathExprBaseImpl:: PathExprBase instanceof VariableAccessCand {
588
+ class VariableAccess extends PathExprBaseImpl:: PathExprBase {
534
589
private string name ;
535
590
private Variable v ;
536
591
@@ -574,6 +629,16 @@ module Impl {
574
629
}
575
630
}
576
631
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
+
577
642
cached
578
643
private module Cached {
579
644
cached
@@ -582,12 +647,12 @@ module Impl {
582
647
583
648
cached
584
649
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 )
591
656
}
592
657
}
593
658
0 commit comments