Skip to content

Commit 60a9f47

Browse files
committed
Improved Cast Diagnostics when Literals are involved
Fixes Issue #53822
1 parent 8ac71b1 commit 60a9f47

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,9 +1184,9 @@ WARNING(conditional_downcast_coercion,none,
11841184
(Type, Type))
11851185

11861186
WARNING(literal_conditional_downcast_to_coercion,none,
1187-
"conditional downcast from literal to %0 always fails; "
1187+
"cast from literal of inferred type %0 to unrelated type %1 always fails; "
11881188
"consider using 'as' coercion",
1189-
(Type))
1189+
(Type, Type))
11901190

11911191
WARNING(forced_downcast_noop,none,
11921192
"forced cast of %0 to same type has no effect", (Type))

lib/Sema/CSDiagnostics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8621,6 +8621,7 @@ bool UnsupportedRuntimeCheckedCastFailure::diagnoseAsError() {
86218621
}
86228622

86238623
bool CheckedCastToUnrelatedFailure::diagnoseAsError() {
8624+
const auto fromType = getFromType();
86248625
const auto toType = getToType();
86258626
auto *sub = CastExpr->getSubExpr()->getSemanticsProvidingExpr();
86268627
// FIXME(https://github.com/apple/swift/issues/54529): This literal diagnostics needs to be revisited by a proposal to unify casting semantics for literals.
@@ -8632,7 +8633,8 @@ bool CheckedCastToUnrelatedFailure::diagnoseAsError() {
86328633
// be statically coerced to the cast type.
86338634
if (protocol && TypeChecker::conformsToProtocol(toType, protocol,
86348635
dc->getParentModule())) {
8635-
emitDiagnostic(diag::literal_conditional_downcast_to_coercion, toType);
8636+
emitDiagnostic(diag::literal_conditional_downcast_to_coercion, fromType,
8637+
toType);
86368638
return true;
86378639
}
86388640
}

test/expr/cast/literals_downcast.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,32 @@
22

33
let ok = "A" as Character // OK
44
let succeed = "A" as? String // expected-warning {{always succeeds}}
5-
let bad = "A" as? Character // expected-warning {{conditional downcast from literal to 'Character' always fails; consider using 'as' coercion}} {{none}}
5+
let force = "A" as! String // expected-warning {{forced cast of 'String' to same type has no effect}}
6+
let bad = "A" as? Character // expected-warning {{cast from literal of inferred type 'String' to unrelated type 'Character' always fails; consider using 'as' coercion}} {{none}}
67
let bad2 = "Aa" as? Character // expected-warning {{cast from 'String' to unrelated type 'Character' always fails}}
8+
let badForce = "Aa" as! Character // expected-warning {{cast from 'String' to unrelated type 'Character' always fails}}
79
let bad1 = 1 as? Character // expected-warning {{cast from 'Int' to unrelated type 'Character' always fails}}
10+
let bad1Force = 1 as! Character // expected-warning {{cast from 'Int' to unrelated type 'Character' always fails}}
811

912
let okInt = 1 as Int // OK
13+
let IntForce = 1 as! Int // expected-warning {{forced cast of 'Int' to same type has no effect}}
1014
let badInt = 1 as? Int // expected-warning {{always succeeds}}
1115
let badInt1 = 1.0 as? Int // expected-warning {{cast from 'Double' to unrelated type 'Int' always fails}}
12-
let badInt2 = 1 as? Double // expected-warning {{conditional downcast from literal to 'Double' always fails; consider using 'as' coercion}} {{none}}
16+
let badInt2 = 1 as? Double // expected-warning {{cast from literal of inferred type 'Int' to unrelated type 'Double' always fails; consider using 'as' coercion}} {{none}}
17+
let badInt3 = 1 as! Double // expected-warning {{cast from literal of inferred type 'Int' to unrelated type 'Double' always fails; consider using 'as' coercion}}
18+
let badInt4 = 1.0 as! Int // expected-warning {{cast from 'Double' to unrelated type 'Int' always fails}}
1319

1420
let okUInt = 1 as UInt // OK
15-
let badUInt = 1 as? UInt // expected-warning {{conditional downcast from literal to 'UInt' always fails; consider using 'as' coercion}} {{none}}
21+
let badUInt = 1 as? UInt // expected-warning {{cast from literal of inferred type 'Int' to unrelated type 'UInt' always fails; consider using 'as' coercion}} {{none}}
1622
let badUInt1 = 1.0 as? UInt // expected-warning {{cast from 'Double' to unrelated type 'UInt' always fails}}
23+
let badUInt2 = 1.0 as! UInt // expected-warning {{cast from 'Double' to unrelated type 'UInt' always fails}}
24+
let badUInt3 = 1 as! UInt // expected-warning {{cast from literal of inferred type 'Int' to unrelated type 'UInt' always fails; consider using 'as' coercion}}
1725

1826
// Custom protocol adoption
1927
struct S: ExpressibleByStringLiteral {
2028
typealias StringLiteralType = String
2129
init(stringLiteral value: Self.StringLiteralType) {}
2230
}
2331

24-
let a = "A" as? S // expected-warning {{conditional downcast from literal to 'S' always fails; consider using 'as' coercion}} {{none}}
32+
let a = "A" as? S // expected-warning {{cast from literal of inferred type 'String' to unrelated type 'S' always fails; consider using 'as' coercion}} {{none}}
33+
let a1 = "A" as! S // expected-warning {{cast from literal of inferred type 'String' to unrelated type 'S' always fails; consider using 'as' coercion}}

0 commit comments

Comments
 (0)