Skip to content

Commit 7f50537

Browse files
authored
Revert "[Constraint application] Stop optimizing casts in the AST."
1 parent 4c2254b commit 7f50537

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

lib/Sema/CSApply.cpp

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,9 +3530,12 @@ namespace {
35303530
// Convert the subexpression.
35313531
Expr *sub = expr->getSubExpr();
35323532

3533-
sub = solution.coerceToType(sub, toType, cs.getConstraintLocator(sub));
3534-
if (!sub)
3533+
solution.setExprTypes(sub);
3534+
3535+
if (TypeChecker::convertToType(sub, toType, cs.DC))
35353536
return nullptr;
3537+
3538+
cs.cacheExprTypes(sub);
35363539

35373540
expr->setSubExpr(sub);
35383541
cs.setType(expr, toType);
@@ -3583,6 +3586,9 @@ namespace {
35833586
return nullptr;
35843587
case CheckedCastKind::Coercion:
35853588
case CheckedCastKind::BridgingCoercion: {
3589+
if (SuppressDiagnostics)
3590+
return nullptr;
3591+
35863592
if (cs.getType(sub)->isEqual(toType)) {
35873593
ctx.Diags.diagnose(expr->getLoc(), diag::forced_downcast_noop, toType)
35883594
.fixItRemove(SourceRange(
@@ -3596,9 +3602,14 @@ namespace {
35963602
"as");
35973603
}
35983604

3599-
expr->setCastKind(castKind);
3600-
cs.setType(expr, toType);
3601-
return expr;
3605+
// Transmute the checked cast into a coercion expression.
3606+
auto *result =
3607+
new (ctx) CoerceExpr(sub, expr->getLoc(), expr->getCastTypeLoc());
3608+
cs.setType(result, toType);
3609+
cs.setType(result->getCastTypeLoc(), toType);
3610+
unsigned disjunctionChoice =
3611+
(castKind == CheckedCastKind::Coercion ? 0 : 1);
3612+
return visitCoerceExpr(result, disjunctionChoice);
36023613
}
36033614

36043615
// Valid casts.
@@ -3651,18 +3662,37 @@ namespace {
36513662
fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,
36523663
expr->getCastTypeLoc().getSourceRange());
36533664
switch (castKind) {
3654-
// Invalid cast.
3665+
/// Invalid cast.
36553666
case CheckedCastKind::Unresolved:
36563667
expr->setCastKind(CheckedCastKind::ValueCast);
36573668
break;
36583669

36593670
case CheckedCastKind::Coercion:
36603671
case CheckedCastKind::BridgingCoercion: {
3672+
if (SuppressDiagnostics)
3673+
return nullptr;
3674+
36613675
ctx.Diags.diagnose(expr->getLoc(), diag::conditional_downcast_coercion,
36623676
cs.getType(sub), toType);
3663-
expr->setCastKind(castKind);
3664-
cs.setType(expr, OptionalType::get(toType));
3665-
return expr;
3677+
3678+
// Transmute the checked cast into a coercion expression.
3679+
auto *coerce =
3680+
new (ctx) CoerceExpr(sub, expr->getLoc(), expr->getCastTypeLoc());
3681+
cs.setType(coerce, toType);
3682+
cs.setType(coerce->getCastTypeLoc(), toType);
3683+
unsigned disjunctionChoice =
3684+
(castKind == CheckedCastKind::Coercion ? 0 : 1);
3685+
Expr *result = visitCoerceExpr(coerce, disjunctionChoice);
3686+
if (!result)
3687+
return nullptr;
3688+
3689+
// Wrap the result in an optional. Mark the optional injection as
3690+
// explicit, because the user did in fact write the '?' as part of
3691+
// 'as?', even though it wasn't necessary.
3692+
result =
3693+
new (ctx) InjectIntoOptionalExpr(result, OptionalType::get(toType));
3694+
result->setImplicit(false);
3695+
return cs.cacheType(result);
36663696
}
36673697

36683698
// Valid casts.

test/stdlib/BridgeIdAsAny.swift.gyb

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,6 @@ testCases = [
199199
]
200200
}%
201201

202-
/// Whether this can be safely casted to NSObject
203-
func isNSObject<T>(_ value: T) -> Bool {
204-
return (value as? NSObject) != nil
205-
}
206-
207202
% for testName, type, valueExpr, testFunc, conformsToError, conformsToHashable in testCases:
208203
BridgeAnything.test("${testName}") {
209204
autoreleasepool {
@@ -215,7 +210,7 @@ BridgeAnything.test("${testName}") {
215210
let xInArray = [x]
216211
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as! [AnyObject])[0])
217212
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as? [AnyObject])![0])
218-
if isNSObject(x) {
213+
if (x as? NSObject) != nil {
219214
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as! [AnyObject])[0])
220215
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as? [AnyObject])![0])
221216
}
@@ -224,7 +219,7 @@ BridgeAnything.test("${testName}") {
224219
let xInDictValue = ["key" : x]
225220
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as! [String: AnyObject])["key"]!)
226221
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as? [String: AnyObject])!["key"]!)
227-
if isNSObject(x) {
222+
if (x as? NSObject) != nil {
228223
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as! [String: NSObject])["key"]!)
229224
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as? [String: NSObject])!["key"]!)
230225
}
@@ -236,7 +231,7 @@ BridgeAnything.test("${testName}") {
236231
// The NSObject version below can't test class LifetimeTracked.
237232
// ${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as! [(AnyObject & Hashable): String]).keys.first!)
238233
// ${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as? [(AnyObject & Hashable): String])!.keys.first!)
239-
if isNSObject(x) {
234+
if (x as? NSObject) != nil {
240235
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as! [NSObject: String]).keys.first!)
241236
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as? [NSObject: String])!.keys.first!)
242237
}

0 commit comments

Comments
 (0)