Skip to content

Commit d91e474

Browse files
authored
Merge pull request swiftlang#28073 from hborla/nil-conditional-cast
[CSGen] Add a tailored diagnostic for conditional casting from a nil literal.
2 parents 513467f + b1638ce commit d91e474

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ ERROR(cannot_subscript_ambiguous_base,none,
243243

244244
ERROR(cannot_subscript_nil_literal,none,
245245
"cannot subscript a nil literal value", ())
246+
ERROR(conditional_cast_from_nil,none,
247+
"nil literal cannot be the source of a conditional cast", ())
246248

247249
ERROR(cannot_pass_rvalue_inout_subelement,none,
248250
"cannot pass immutable value as inout argument: %0",

lib/Sema/CSGen.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,25 @@ namespace {
26742674
if (!fromExpr) // Either wasn't constructed correctly or wasn't folded.
26752675
return nullptr;
26762676

2677+
std::function<Expr *(Expr *)> nilLiteralExpr = [&](Expr *expr) -> Expr * {
2678+
expr = expr->getSemanticsProvidingExpr();
2679+
if (expr->getKind() == ExprKind::NilLiteral)
2680+
return expr;
2681+
2682+
if (auto *optionalEvalExpr = dyn_cast<OptionalEvaluationExpr>(expr))
2683+
return nilLiteralExpr(optionalEvalExpr->getSubExpr());
2684+
2685+
if (auto *bindOptionalExpr = dyn_cast<BindOptionalExpr>(expr))
2686+
return nilLiteralExpr(bindOptionalExpr->getSubExpr());
2687+
2688+
return nullptr;
2689+
};
2690+
2691+
if (auto nilLiteral = nilLiteralExpr(fromExpr)) {
2692+
tc.diagnose(nilLiteral->getLoc(), diag::conditional_cast_from_nil);
2693+
return nullptr;
2694+
}
2695+
26772696
// Validate the resulting type.
26782697
TypeResolutionOptions options(TypeResolverContext::ExplicitCastExpr);
26792698
options |= TypeResolutionFlags::AllowUnboundGenerics;

test/Constraints/casts.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,5 @@ func process(p: Any?) {
220220

221221
func compare<T>(_: T, _: T) {} // expected-note {{'compare' declared here}}
222222
func compare<T>(_: T?, _: T?) {}
223+
224+
_ = nil? as? Int?? // expected-error {{nil literal cannot be the source of a conditional cast}}

0 commit comments

Comments
 (0)