@@ -68,36 +68,36 @@ module Impl {
6868 * where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
6969 * pattern.
7070 */
71+ cached
7172 private predicate variableDecl ( AstNode definingNode , Name name , string text ) {
72- (
73- exists ( SelfParam sp |
74- name = sp .getName ( ) and
75- definingNode = name and
76- text = name .getText ( ) and
77- // exclude self parameters from functions without a body as these are
78- // trait method declarations without implementations
79- not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getSelfParam ( ) = sp )
80- )
81- or
82- exists ( IdentPat pat |
83- name = pat .getName ( ) and
84- (
85- definingNode = getOutermostEnclosingOrPat ( pat )
86- or
87- not exists ( getOutermostEnclosingOrPat ( pat ) ) and definingNode = name
88- ) and
89- text = name .getText ( ) and
90- // exclude for now anything starting with an uppercase character, which may be a reference to
91- // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
92- // which we don't appear to recognize yet anyway. This also assumes programmers follow the
93- // naming guidelines, which they generally do, but they're not enforced.
94- not text .charAt ( 0 ) .isUppercase ( ) and
95- // exclude parameters from functions without a body as these are trait method declarations
96- // without implementations
97- not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getAParam ( ) .getPat ( ) = pat ) and
98- // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
99- not exists ( FnPtrTypeRepr fp | fp .getParamList ( ) .getParam ( _) .getPat ( ) = pat )
100- )
73+ Cached:: ref ( ) and
74+ exists ( SelfParam sp |
75+ name = sp .getName ( ) and
76+ definingNode = name and
77+ text = name .getText ( ) and
78+ // exclude self parameters from functions without a body as these are
79+ // trait method declarations without implementations
80+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getSelfParam ( ) = sp )
81+ )
82+ or
83+ exists ( IdentPat pat |
84+ name = pat .getName ( ) and
85+ (
86+ definingNode = getOutermostEnclosingOrPat ( pat )
87+ or
88+ not exists ( getOutermostEnclosingOrPat ( pat ) ) and definingNode = name
89+ ) and
90+ text = name .getText ( ) and
91+ // exclude for now anything starting with an uppercase character, which may be a reference to
92+ // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
93+ // which we don't appear to recognize yet anyway. This also assumes programmers follow the
94+ // naming guidelines, which they generally do, but they're not enforced.
95+ not text .charAt ( 0 ) .isUppercase ( ) and
96+ // exclude parameters from functions without a body as these are trait method declarations
97+ // without implementations
98+ not exists ( Function f | not f .hasBody ( ) and f .getParamList ( ) .getAParam ( ) .getPat ( ) = pat ) and
99+ // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
100+ not exists ( FnPtrTypeRepr fp | fp .getParamList ( ) .getParam ( _) .getPat ( ) = pat )
101101 )
102102 }
103103
@@ -156,8 +156,12 @@ module Impl {
156156 predicate isCaptured ( ) { this .getAnAccess ( ) .isCapture ( ) }
157157
158158 /** Gets the parameter that introduces this variable, if any. */
159+ cached
159160 ParamBase getParameter ( ) {
160- result = this .getSelfParam ( ) or result .( Param ) .getPat ( ) = getAVariablePatAncestor ( this )
161+ Cached:: ref ( ) and
162+ result = this .getSelfParam ( )
163+ or
164+ result .( Param ) .getPat ( ) = getAVariablePatAncestor ( this )
161165 }
162166
163167 /** Hold is this variable is mutable. */
@@ -614,12 +618,18 @@ module Impl {
614618
615619 /** A variable write. */
616620 class VariableWriteAccess extends VariableAccess {
617- VariableWriteAccess ( ) { assignmentExprDescendant ( this ) }
621+ cached
622+ VariableWriteAccess ( ) {
623+ Cached:: ref ( ) and
624+ assignmentExprDescendant ( this )
625+ }
618626 }
619627
620628 /** A variable read. */
621629 class VariableReadAccess extends VariableAccess {
630+ cached
622631 VariableReadAccess ( ) {
632+ Cached:: ref ( ) and
623633 not this instanceof VariableWriteAccess and
624634 not this = any ( RefExpr re ) .getExpr ( ) and
625635 not this = any ( CompoundAssignmentExpr cae ) .getLhs ( )
@@ -638,6 +648,22 @@ module Impl {
638648
639649 cached
640650 private module Cached {
651+ cached
652+ predicate ref ( ) { 1 = 1 }
653+
654+ cached
655+ predicate backref ( ) {
656+ 1 = 1
657+ or
658+ variableDecl ( _, _, _)
659+ or
660+ exists ( VariableReadAccess a )
661+ or
662+ exists ( VariableWriteAccess a )
663+ or
664+ exists ( any ( Variable v ) .getParameter ( ) )
665+ }
666+
641667 cached
642668 newtype TVariable =
643669 MkVariable ( AstNode definingNode , string name ) { variableDecl ( definingNode , _, name ) }
0 commit comments