Skip to content

Commit 0c78826

Browse files
authored
Merge pull request #21503 from xedin/rdar-46544601-5.0
[5.0][CSDiag] Always attempt to erase open existentials after re-typecheck
2 parents 2e6ed71 + 73a9c01 commit 0c78826

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,7 +1877,7 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
18771877
(isa<OverloadedDeclRefExpr>(subExpr->getValueProvidingExpr()))) {
18781878
return subExpr;
18791879
}
1880-
1880+
18811881
// Save any existing type data of the subexpr tree, and reset it to null in
18821882
// prep for re-type-checking the tree. If things fail, we can revert the
18831883
// types back to their original state.
@@ -1921,9 +1921,12 @@ Expr *FailureDiagnosis::typeCheckChildIndependently(
19211921
// holding on to an expression containing open existential types but
19221922
// no OpenExistentialExpr, which breaks invariants enforced by the
19231923
// ASTChecker.
1924-
if (isa<OpenExistentialExpr>(subExpr))
1925-
eraseOpenedExistentials(CS, subExpr);
1926-
1924+
// Another reason why we need to do this is because diagnostics might pick
1925+
// constraint anchor for re-typechecking which would only have opaque value
1926+
// expression and not enclosing open existential, which is going to trip up
1927+
// sanitizer.
1928+
eraseOpenedExistentials(CS, subExpr);
1929+
19271930
// If recursive type checking failed, then an error was emitted. Return
19281931
// null to indicate this to the caller.
19291932
if (!resultTy)

test/Constraints/rdar46544601.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct D {}
4+
5+
class Future<T> {
6+
func then<U>(_ fn: @escaping (T) -> Future<U>) -> Future<U> { fatalError() }
7+
func thenThrowing<U>(_ fn: @escaping (T) throws -> U) -> Future<U> { fatalError() }
8+
func whenFailure(_ fn: @escaping (Error) -> Void) {}
9+
10+
func and<U>(result: U) -> Future<(T,U)> { fatalError() }
11+
}
12+
13+
protocol P {
14+
func foo(arr: [D], data: ArraySlice<UInt8>) -> Future<D>
15+
// expected-note@-1 {{found this candidate}}
16+
func bar(root: D, from: P) -> Future<D>
17+
}
18+
19+
extension P {
20+
func foo(arr: [D] = [], data: [UInt8]) -> Future<D> { fatalError() }
21+
// expected-note@-1 {{found this candidate}}
22+
}
23+
24+
func crash(_ p: P, payload: [UInt8]) throws {
25+
p.foo(data: payload).then { _ in
26+
return Future<(D, [D])>()
27+
}.then { (id, arr) in
28+
p.foo(arr: arr, data: []).and(result: (id, arr))
29+
// expected-error@-1 {{mbiguous reference to member 'foo(arr:data:)'}}
30+
}.then { args0 in
31+
let (parentID, args1) = args0
32+
p.bar(root: parentID, from: p).and(args1)
33+
}.whenFailure { _ in }
34+
}

0 commit comments

Comments
 (0)