@@ -62,7 +62,7 @@ abstract class ConditionalCompletion extends NormalCompletion {
62
62
abstract ConditionalCompletion getDual ( ) ;
63
63
}
64
64
65
- /** Holds if node `le` has the Boolean constant value `value`. */
65
+ /** Holds if node `le` has the constant Boolean value `value`. */
66
66
private predicate isBooleanConstant ( LiteralExpr le , Boolean value ) {
67
67
le .getTextValue ( ) = value .toString ( )
68
68
}
@@ -117,13 +117,61 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
117
117
override string toString ( ) { result = "boolean(" + value + ")" }
118
118
}
119
119
120
+ /** Holds if node `pat` has the constant match value `value`. */
121
+ pragma [ nomagic]
122
+ private predicate isMatchConstant ( Pat pat , boolean value ) {
123
+ value = true and
124
+ (
125
+ pat instanceof WildcardPat
126
+ or
127
+ pat = any ( IdentPat ip | not ip .hasPat ( ) and ip = any ( Variable v ) .getPat ( ) )
128
+ or
129
+ pat instanceof RestPat
130
+ or
131
+ // `let` statements without an `else` branch must be exhaustive
132
+ pat = any ( LetStmt let | not let .hasLetElse ( ) ) .getPat ( )
133
+ or
134
+ // `match` expressions must be exhaustive, so last arm cannot fail
135
+ pat = any ( MatchExpr me ) .getLastArm ( ) .getPat ( )
136
+ or
137
+ // parameter patterns must be exhaustive
138
+ pat = any ( Param p ) .getPat ( )
139
+ ) and
140
+ not pat = any ( ForExpr for ) .getPat ( ) // workaround until `for` loops are desugared
141
+ or
142
+ exists ( Pat parent | isMatchConstant ( parent , value ) |
143
+ pat = parent .( BoxPat ) .getPat ( )
144
+ or
145
+ pat = parent .( IdentPat ) .getPat ( )
146
+ or
147
+ pat = parent .( ParenPat ) .getPat ( )
148
+ or
149
+ pat = parent .( RecordPat ) .getRecordPatFieldList ( ) .getField ( _) .getPat ( )
150
+ or
151
+ pat = parent .( RefPat ) .getPat ( )
152
+ or
153
+ pat = parent .( TuplePat ) .getAField ( )
154
+ or
155
+ pat = parent .( TupleStructPat ) .getAField ( )
156
+ or
157
+ pat = parent .( OrPat ) .getLastPat ( )
158
+ )
159
+ }
160
+
120
161
/**
121
162
* A completion that represents the result of a pattern match.
122
163
*/
123
164
class MatchCompletion extends TMatchCompletion , ConditionalCompletion {
124
165
MatchCompletion ( ) { this = TMatchCompletion ( value ) }
125
166
126
- override predicate isValidForSpecific ( AstNode e ) { e instanceof Pat }
167
+ override predicate isValidForSpecific ( AstNode e ) {
168
+ e instanceof Pat and
169
+ (
170
+ isMatchConstant ( e , value )
171
+ or
172
+ not isMatchConstant ( e , _)
173
+ )
174
+ }
127
175
128
176
override MatchSuccessor getAMatchingSuccessorType ( ) { result .getValue ( ) = value }
129
177
0 commit comments