Merge pull request #22572 from dcci/rdar47982630-50
[5.0][DebuggerSupport] Unbreak closures in the expression parser.
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index 3535a99..aa16188 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -350,6 +350,14 @@
"not a representative");
assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type");
+ // Determines whether this type variable represents an object
+ // of the optional type extracted by force unwrap.
+ bool isOptionalObject = false;
+ if (auto *locator = typeVar->getImpl().getLocator()) {
+ auto *anchor = locator->getAnchor();
+ isOptionalObject = anchor && isa<ForceValueExpr>(anchor);
+ }
+
// Gather the constraints associated with this type variable.
llvm::SetVector<Constraint *> constraints;
getConstraintGraph().gatherConstraints(
@@ -401,6 +409,18 @@
if (exactTypes.insert(type->getCanonicalType()).second) {
result.addPotentialBinding(*binding);
+ // Result of force unwrap is always connected to its base
+ // optional type via `OptionalObject` constraint which
+ // preserves l-valueness, so in case where object type got
+ // inferred before optional type (because it got the
+ // type from context e.g. parameter type of a function call),
+ // we need to test type with and without l-value after
+ // delaying bindings for as long as possible.
+ if (isOptionalObject && !type->is<LValueType>()) {
+ result.FullyBound = true;
+ result.PotentiallyIncomplete = true;
+ }
+
if (auto *locator = typeVar->getImpl().getLocator()) {
auto path = locator->getPath();
auto voidType = getASTContext().TheEmptyTupleType;
diff --git a/test/Constraints/optional.swift b/test/Constraints/optional.swift
index b255778..0d2f919 100644
--- a/test/Constraints/optional.swift
+++ b/test/Constraints/optional.swift
@@ -302,3 +302,34 @@
_ = [i!] // expected-error {{cannot force unwrap value of non-optional type 'Int'}} {{9-10=}}
_ = S<Int>([i!]) // expected-error {{cannot force unwrap value of non-optional type 'Int'}} {{16-17=}}
}
+
+// rdar://problem/47967277 - cannot assign through '!': '$0' is immutable
+func sr_9893_1() {
+ func foo<T : Equatable>(_: @autoclosure () throws -> T,
+ _: @autoclosure () throws -> T) {}
+
+ class A {
+ var bar: String?
+ }
+
+ let r1 = A()
+ let r2 = A()
+
+ let arr1: [A] = []
+ foo(Set(arr1.map { $0.bar! }), Set([r1, r2].map { $0.bar! })) // Ok
+}
+
+func sr_9893_2(cString: UnsafePointer<CChar>) {
+ struct S {
+ var a: Int32 = 0
+ var b = ContiguousArray<CChar>(repeating: 0, count: 10)
+ }
+
+ var s = S()
+
+ withUnsafeMutablePointer(to: &s.a) { ptrA in
+ s.b.withUnsafeMutableBufferPointer { bufferB in
+ withVaList([ptrA, bufferB.baseAddress!]) { ptr in } // Ok
+ }
+ }
+}