Skip to content

Commit 4907a98

Browse files
authored
Merge pull request swiftlang#28355 from DougGregor/no-opt-ast-casts
[Constraint application] Stop optimizing casts in the AST.
2 parents 22f6a52 + f95f8e9 commit 4907a98

File tree

2 files changed

+17
-42
lines changed

2 files changed

+17
-42
lines changed

lib/Sema/CSApply.cpp

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

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

35403537
expr->setSubExpr(sub);
35413538
cs.setType(expr, toType);
@@ -3586,9 +3583,6 @@ namespace {
35863583
return nullptr;
35873584
case CheckedCastKind::Coercion:
35883585
case CheckedCastKind::BridgingCoercion: {
3589-
if (SuppressDiagnostics)
3590-
return nullptr;
3591-
35923586
if (cs.getType(sub)->isEqual(toType)) {
35933587
ctx.Diags.diagnose(expr->getLoc(), diag::forced_downcast_noop, toType)
35943588
.fixItRemove(SourceRange(
@@ -3602,14 +3596,9 @@ namespace {
36023596
"as");
36033597
}
36043598

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);
3599+
expr->setCastKind(castKind);
3600+
cs.setType(expr, toType);
3601+
return expr;
36133602
}
36143603

36153604
// Valid casts.
@@ -3662,37 +3651,18 @@ namespace {
36623651
fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,
36633652
expr->getCastTypeLoc().getSourceRange());
36643653
switch (castKind) {
3665-
/// Invalid cast.
3654+
// Invalid cast.
36663655
case CheckedCastKind::Unresolved:
36673656
expr->setCastKind(CheckedCastKind::ValueCast);
36683657
break;
36693658

36703659
case CheckedCastKind::Coercion:
36713660
case CheckedCastKind::BridgingCoercion: {
3672-
if (SuppressDiagnostics)
3673-
return nullptr;
3674-
36753661
ctx.Diags.diagnose(expr->getLoc(), diag::conditional_downcast_coercion,
36763662
cs.getType(sub), toType);
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);
3663+
expr->setCastKind(castKind);
3664+
cs.setType(expr, OptionalType::get(toType));
3665+
return expr;
36963666
}
36973667

36983668
// Valid casts.

test/stdlib/BridgeIdAsAny.swift.gyb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ testCases = [
196196
]
197197
}%
198198

199+
/// Whether this can be safely casted to NSObject
200+
func isNSObject<T>(_ value: T) -> Bool {
201+
return (value as? NSObject) != nil
202+
}
203+
199204
% for testName, type, valueExpr, testFunc, conformsToError, conformsToHashable in testCases:
200205
BridgeAnything.test("${testName}") {
201206
autoreleasepool {
@@ -207,7 +212,7 @@ BridgeAnything.test("${testName}") {
207212
let xInArray = [x]
208213
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as! [AnyObject])[0])
209214
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as? [AnyObject])![0])
210-
if (x as? NSObject) != nil {
215+
if isNSObject(x) {
211216
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as! [AnyObject])[0])
212217
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInArray) as? [AnyObject])![0])
213218
}
@@ -216,7 +221,7 @@ BridgeAnything.test("${testName}") {
216221
let xInDictValue = ["key" : x]
217222
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as! [String: AnyObject])["key"]!)
218223
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as? [String: AnyObject])!["key"]!)
219-
if (x as? NSObject) != nil {
224+
if isNSObject(x) {
220225
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as! [String: NSObject])["key"]!)
221226
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictValue) as? [String: NSObject])!["key"]!)
222227
}
@@ -228,7 +233,7 @@ BridgeAnything.test("${testName}") {
228233
// The NSObject version below can't test class LifetimeTracked.
229234
// ${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as! [(AnyObject & Hashable): String]).keys.first!)
230235
// ${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as? [(AnyObject & Hashable): String])!.keys.first!)
231-
if (x as? NSObject) != nil {
236+
if isNSObject(x) {
232237
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as! [NSObject: String]).keys.first!)
233238
${testFunc}(original: x, bridged: (_bridgeAnythingToObjectiveC(xInDictKey) as? [NSObject: String])!.keys.first!)
234239
}

0 commit comments

Comments
 (0)