Skip to content

Commit 968a37d

Browse files
[Diagnostics] Tailored diagnostic message for conditional downcast involving literals that can be statically coerced
1 parent 6c7cdef commit 968a37d

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,11 @@ WARNING(conditional_downcast_coercion,none,
10151015
"conditional cast from %0 to %1 always succeeds",
10161016
(Type, Type))
10171017

1018+
WARNING(literal_conditional_downcast_to_coercion,none,
1019+
"conditional downcast from literal to %0 always fails; "
1020+
"consider using 'as' coercion",
1021+
(Type))
1022+
10181023
WARNING(forced_downcast_noop,none,
10191024
"forced cast of %0 to same type has no effect", (Type))
10201025

lib/Sema/CSApply.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,9 +3648,9 @@ namespace {
36483648
auto sub = cs.coerceToRValue(expr->getSubExpr());
36493649
expr->setSubExpr(sub);
36503650

3651-
3651+
bool isSubExprLiteral = isa<LiteralExpr>(sub);
36523652
auto castContextKind =
3653-
(SuppressDiagnostics || isInsideIsExpr)
3653+
(SuppressDiagnostics || isInsideIsExpr || isSubExprLiteral)
36543654
? CheckedCastContextKind::None
36553655
: CheckedCastContextKind::ConditionalCast;
36563656

@@ -3661,13 +3661,35 @@ namespace {
36613661
switch (castKind) {
36623662
// Invalid cast.
36633663
case CheckedCastKind::Unresolved:
3664+
// FIXME: This literal diagnostics needs to be revisited by a proposal
3665+
// to unify casting semantics for literals.
3666+
// https://bugs.swift.org/browse/SR-12093
3667+
if (isSubExprLiteral) {
3668+
auto protocol = TypeChecker::getLiteralProtocol(ctx, sub);
3669+
// Special handle for literals conditional checked cast when they can
3670+
// be statically coerced to the cast type.
3671+
if (protocol && TypeChecker::conformsToProtocol(
3672+
toType, protocol, cs.DC,
3673+
ConformanceCheckFlags::InExpression)) {
3674+
ctx.Diags
3675+
.diagnose(expr->getLoc(),
3676+
diag::literal_conditional_downcast_to_coercion,
3677+
toType);
3678+
} else {
3679+
ctx.Diags
3680+
.diagnose(expr->getLoc(), diag::downcast_to_unrelated, fromType,
3681+
toType)
3682+
.highlight(sub->getSourceRange())
3683+
.highlight(expr->getCastTypeLoc().getSourceRange());
3684+
}
3685+
}
36643686
expr->setCastKind(CheckedCastKind::ValueCast);
36653687
break;
36663688

36673689
case CheckedCastKind::Coercion:
36683690
case CheckedCastKind::BridgingCoercion: {
36693691
ctx.Diags.diagnose(expr->getLoc(), diag::conditional_downcast_coercion,
3670-
cs.getType(sub), toType);
3692+
fromType, toType);
36713693
expr->setCastKind(castKind);
36723694
cs.setType(expr, OptionalType::get(toType));
36733695
return expr;
@@ -3681,7 +3703,7 @@ namespace {
36813703
expr->setCastKind(castKind);
36823704
break;
36833705
}
3684-
3706+
36853707
return handleOptionalBindingsForCast(expr, simplifyType(cs.getType(expr)),
36863708
OptionalBindingsCastKind::Conditional);
36873709
}

0 commit comments

Comments
 (0)