Skip to content

Commit f14e9a8

Browse files
authored
Merge pull request #30621 from xedin/extend-nil-diags
[ConstraintSystem] Diagnose more cases of invalid `nil` use during co…
2 parents 1beb37e + 465b0e1 commit f14e9a8

File tree

3 files changed

+22
-30
lines changed

3 files changed

+22
-30
lines changed

lib/Sema/CSGen.cpp

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,18 @@ namespace {
11551155
while (parentExpr && isa<ParenExpr>(parentExpr))
11561156
parentExpr = CS.getParentExpr(parentExpr);
11571157

1158+
// In cases like `_ = nil?` AST would have `nil`
1159+
// wrapped in `BindOptionalExpr`.
1160+
if (parentExpr && isa<BindOptionalExpr>(parentExpr))
1161+
parentExpr = CS.getParentExpr(parentExpr);
1162+
11581163
if (parentExpr) {
1164+
// `_ = nil as? ...`
1165+
if (isa<ConditionalCheckedCastExpr>(parentExpr)) {
1166+
DE.diagnose(expr->getLoc(), diag::conditional_cast_from_nil);
1167+
return Type();
1168+
}
1169+
11591170
// `_ = nil!`
11601171
if (isa<ForceValueExpr>(parentExpr)) {
11611172
DE.diagnose(expr->getLoc(), diag::cannot_force_unwrap_nil_literal);
@@ -1167,13 +1178,13 @@ namespace {
11671178
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
11681179
return Type();
11691180
}
1170-
}
11711181

1172-
// `_ = nil`
1173-
if (auto *assignment = dyn_cast_or_null<AssignExpr>(parentExpr)) {
1174-
if (isa<DiscardAssignmentExpr>(assignment->getDest())) {
1175-
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
1176-
return Type();
1182+
// `_ = nil`
1183+
if (auto *assignment = dyn_cast<AssignExpr>(parentExpr)) {
1184+
if (isa<DiscardAssignmentExpr>(assignment->getDest())) {
1185+
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
1186+
return Type();
1187+
}
11771188
}
11781189
}
11791190

@@ -2982,26 +2993,6 @@ namespace {
29822993
if (!fromExpr) // Either wasn't constructed correctly or wasn't folded.
29832994
return nullptr;
29842995

2985-
std::function<Expr *(Expr *)> nilLiteralExpr = [&](Expr *expr) -> Expr * {
2986-
expr = expr->getSemanticsProvidingExpr();
2987-
if (expr->getKind() == ExprKind::NilLiteral)
2988-
return expr;
2989-
2990-
if (auto *optionalEvalExpr = dyn_cast<OptionalEvaluationExpr>(expr))
2991-
return nilLiteralExpr(optionalEvalExpr->getSubExpr());
2992-
2993-
if (auto *bindOptionalExpr = dyn_cast<BindOptionalExpr>(expr))
2994-
return nilLiteralExpr(bindOptionalExpr->getSubExpr());
2995-
2996-
return nullptr;
2997-
};
2998-
2999-
if (auto nilLiteral = nilLiteralExpr(fromExpr)) {
3000-
ctx.Diags.diagnose(nilLiteral->getLoc(),
3001-
diag::conditional_cast_from_nil);
3002-
return nullptr;
3003-
}
3004-
30052996
// Validate the resulting type.
30062997
TypeResolutionOptions options(TypeResolverContext::ExplicitCastExpr);
30072998
options |= TypeResolutionFlags::AllowUnboundGenerics;

test/Constraints/casts.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func process(p: Any?) {
221221
func compare<T>(_: T, _: T) {} // expected-note {{'compare' declared here}}
222222
func compare<T>(_: T?, _: T?) {}
223223

224-
_ = nil? as? Int?? // expected-error {{nil literal cannot be the source of a conditional cast}}
224+
_ = nil? as? Int?? // expected-error {{'nil' requires a contextual type}}
225225

226226
func test_tuple_casts_no_warn() {
227227
struct Foo {}

test/Constraints/optional.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,10 @@ func sr_12309() {
439439
_ = (nil!) // expected-error {{'nil' literal cannot be force unwrapped}}
440440
_ = (nil)! // expected-error {{'nil' literal cannot be force unwrapped}}
441441
_ = ((nil))! // expected-error {{'nil' literal cannot be force unwrapped}}
442-
_ = nil? // expected-error {{value of optional type 'Optional<_>' must be unwrapped to a value of type '_'}}
443-
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
444-
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
442+
_ = nil? // expected-error {{'nil' requires a contextual type}}
443+
_ = ((nil?)) // expected-error {{'nil' requires a contextual type}}
444+
_ = ((nil))? // expected-error {{'nil' requires a contextual type}}
445+
_ = ((nil)?) // expected-error {{'nil' requires a contextual type}}
445446
_ = nil // expected-error {{'nil' requires a contextual type}}
446447
_ = (nil) // expected-error {{'nil' requires a contextual type}}
447448
_ = ((nil)) // expected-error {{'nil' requires a contextual type}}

0 commit comments

Comments
 (0)