Skip to content

Commit e3773f8

Browse files
committed
Sema: Fix applying solution for OptionalTryExpr
In Swift 5 mode, CSGen generates a conversion constraint from the type of OptionalTryExpr's subexpression, call it T, and Optional<$tv> for a new type variable $tv. When applying the solution, we would coerce the sub-expression to T? if T was not optional, or T otherwise. This was wrong because there's no reason that $tv is actually equal to T. Instead, we must coerce the sub-expression to Optional<$tv>, which is the type of the overall OptionalTryExpr. Fixes <rdar://problem/46742002>.
1 parent df4b9f4 commit e3773f8

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,23 +2824,14 @@ namespace {
28242824
return simplifyExprType(expr);
28252825
}
28262826

2827-
Type subExprType = cs.getType(expr->getSubExpr());
2828-
Type targetType = simplifyType(subExprType);
2829-
2830-
// If the subexpression is not optional, wrap it in
2831-
// an InjectIntoOptionalExpr. Then use the type of the
2832-
// subexpression as the type of the 'try?' expr
2833-
bool subExprIsOptional = (bool) subExprType->getOptionalObjectType();
2834-
2835-
if (!subExprIsOptional) {
2836-
targetType = OptionalType::get(targetType);
2837-
auto subExpr = coerceToType(expr->getSubExpr(), targetType,
2838-
cs.getConstraintLocator(expr));
2839-
if (!subExpr) return nullptr;
2840-
expr->setSubExpr(subExpr);
2841-
}
2842-
2843-
cs.setType(expr, targetType);
2827+
Type exprType = simplifyType(cs.getType(expr));
2828+
2829+
auto subExpr = coerceToType(expr->getSubExpr(), exprType,
2830+
cs.getConstraintLocator(expr));
2831+
if (!subExpr) return nullptr;
2832+
expr->setSubExpr(subExpr);
2833+
2834+
cs.setType(expr, exprType);
28442835
return expr;
28452836
}
28462837

test/Parse/try.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,14 @@ let _: Int? = try? producer.produceDoubleOptionalInt() // expected-error {{value
258258
let _: Int?? = try? producer.produceDoubleOptionalInt() // expected-error {{value of optional type 'Int???' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
259259
let _: Int??? = try? producer.produceDoubleOptionalInt() // good
260260
let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int???' to specified type 'String'}}
261+
262+
// rdar://problem/46742002
263+
protocol Dummy : class {}
264+
265+
class F<T> {
266+
func wait() throws -> T { fatalError() }
267+
}
268+
269+
func bar(_ a: F<Dummy>, _ b: F<Dummy>) {
270+
_ = (try? a.wait()) === (try? b.wait())
271+
}

test/Parse/try_swift5.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,14 @@ let _: Int? = try? producer.produceDoubleOptionalInt() // expected-error {{canno
261261
let _: Int?? = try? producer.produceDoubleOptionalInt() // good
262262
let _: Int??? = try? producer.produceDoubleOptionalInt() // good
263263
let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
264+
265+
// rdar://problem/46742002
266+
protocol Dummy : class {}
267+
268+
class F<T> {
269+
func wait() throws -> T { fatalError() }
270+
}
271+
272+
func bar(_ a: F<Dummy>, _ b: F<Dummy>) {
273+
_ = (try? a.wait()) === (try? b.wait())
274+
}

0 commit comments

Comments
 (0)