@@ -62,7 +62,7 @@ abstract class ConditionalCompletion extends NormalCompletion {
6262 abstract ConditionalCompletion getDual ( ) ;
6363}
6464
65- /** Holds if node `le` has the Boolean constant value `value`. */
65+ /** Holds if node `le` has the constant Boolean value `value`. */
6666private predicate isBooleanConstant ( LiteralExpr le , Boolean value ) {
6767 le .getTextValue ( ) = value .toString ( )
6868}
@@ -117,13 +117,61 @@ class BooleanCompletion extends ConditionalCompletion, TBooleanCompletion {
117117 override string toString ( ) { result = "boolean(" + value + ")" }
118118}
119119
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+
120161/**
121162 * A completion that represents the result of a pattern match.
122163 */
123164class MatchCompletion extends TMatchCompletion , ConditionalCompletion {
124165 MatchCompletion ( ) { this = TMatchCompletion ( value ) }
125166
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+ }
127175
128176 override MatchSuccessor getAMatchingSuccessorType ( ) { result .getValue ( ) = value }
129177
0 commit comments