diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1486e63f7f839..3f432cfa3f9c7 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2544,7 +2544,17 @@ namespace { ConstraintKind::CheckedCast, subPatternType, castType, locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); - return setType(subPatternType); + // Allow `is` pattern to infer type from context which is then going + // to be propaged down to its sub-pattern via conversion. This enables + // correct handling of patterns like `_ as Foo` where `_` would + // get a type of `Foo` but `is` pattern enclosing it could still be + // inferred from enclosing context. + auto isType = CS.createTypeVariable(CS.getConstraintLocator(pattern), + TVO_CanBindToNoEscape); + CS.addConstraint( + ConstraintKind::Conversion, subPatternType, isType, + locator.withPathElement(LocatorPathElt::PatternMatch(pattern))); + return setType(isType); } case PatternKind::Bool: diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift index f184629fa37f4..a3a2de3f5ee24 100644 --- a/test/Constraints/patterns.swift +++ b/test/Constraints/patterns.swift @@ -478,3 +478,20 @@ func rdar_60048356() { } } } + +// rdar://problem/63510989 - valid pattern doesn't type-check +func rdar63510989() { + enum Value : P { + func p() {} + } + + enum E { + case foo(P?) + } + + func test(e: E) { + if case .foo(_ as Value) = e {} // Ok + if case .foo(let v as Value) = e {} // Ok + // expected-warning@-1 {{immutable value 'v' was never used; consider replacing with '_' or removing it}} + } +}