@@ -213,12 +213,39 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
213213 )
214214 }
215215
216- predicate declInScope ( AstNode definingNode , string name , AstNode scope ) {
217- bindingContext ( definingNode , scope ) and
218- (
219- definingNode .( NamePattern ) .getIdentifier ( ) .getValue ( ) = name
216+ /**
217+ * Gets the nearest enclosing `OrPattern` to which variable bindings in `p` should be lifted.
218+ *
219+ * To ensure that `case .foo(let x), .bar(let x)` result in a single definition for
220+ * the variable `x`, the `OrPattern` becomes the `definingNode` for `x`.
221+ *
222+ * At the moment no further checks are needed since the Swift compiler enforces that
223+ * variable names bound in any branch are bound in all branches.
224+ */
225+ private OrPattern getEnclosingOrPattern ( Pattern p ) {
226+ p = result .getPattern ( _)
227+ or
228+ exists ( Pattern parent | result = getEnclosingOrPattern ( parent ) |
229+ p = parent .( ConstructorPattern ) .getElement ( _) .getPattern ( )
220230 or
221- definingNode .( Identifier ) .getValue ( ) = name
231+ p = parent .( TuplePattern ) .getElement ( _) .getPattern ( )
232+ )
233+ }
234+
235+ predicate declInScope ( AstNode definingNode , string name , AstNode scope ) {
236+ exists ( AstNode pattern |
237+ bindingContext ( pattern , scope ) and
238+ (
239+ pattern .( NamePattern ) .getIdentifier ( ) .getValue ( ) = name
240+ or
241+ pattern .( Identifier ) .getValue ( ) = name
242+ ) and
243+ (
244+ definingNode = getEnclosingOrPattern ( pattern )
245+ or
246+ not exists ( getEnclosingOrPattern ( pattern ) ) and
247+ definingNode = pattern
248+ )
222249 )
223250 }
224251
0 commit comments