Skip to content

Commit a2b3b54

Browse files
committed
[CSGen] Rework constraint generation for nil to avoid failing
1 parent e30bdac commit a2b3b54

File tree

2 files changed

+19
-77
lines changed

2 files changed

+19
-77
lines changed

lib/Sema/CSGen.cpp

Lines changed: 18 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,80 +1015,13 @@ namespace {
10151015
}
10161016

10171017
Type visitNilLiteralExpr(NilLiteralExpr *expr) {
1018-
auto &DE = CS.getASTContext().Diags;
1019-
// If this is a standalone `nil` literal expression e.g.
1020-
// `_ = nil`, let's diagnose it here because solver can't
1021-
// attempt any types for it.
1022-
auto *parentExpr = CS.getParentExpr(expr);
1023-
bool hasContextualType = bool(CS.getContextualType(expr));
1024-
1025-
while (parentExpr) {
1026-
if (!isa<IdentityExpr>(parentExpr))
1027-
break;
1028-
1029-
// If there is a parent, use it, otherwise we need
1030-
// to check whether the last parent node in the chain
1031-
// had a contextual type associated with it because
1032-
// in situations like:
1033-
//
1034-
// \code
1035-
// func foo() -> Int? {
1036-
// return (nil)
1037-
// }
1038-
// \endcode
1039-
//
1040-
// parentheses around `nil` are significant.
1041-
if (auto *nextParent = CS.getParentExpr(parentExpr)) {
1042-
parentExpr = nextParent;
1043-
} else {
1044-
hasContextualType |= bool(CS.getContextualType(parentExpr));
1045-
// Since current expression is an identity expr
1046-
// and there are no more parents, let's pretend
1047-
// that `nil` don't have a parent since parens
1048-
// are not semantically significant for further checks.
1049-
parentExpr = nullptr;
1050-
}
1051-
}
1052-
1053-
// In cases like `_ = nil?` AST would have `nil`
1054-
// wrapped in `BindOptionalExpr`.
1055-
if (parentExpr && isa<BindOptionalExpr>(parentExpr))
1056-
parentExpr = CS.getParentExpr(parentExpr);
1057-
1058-
if (parentExpr) {
1059-
// `_ = nil as? ...`
1060-
if (isa<ConditionalCheckedCastExpr>(parentExpr)) {
1061-
DE.diagnose(expr->getLoc(), diag::conditional_cast_from_nil);
1062-
return Type();
1063-
}
1064-
1065-
// `_ = nil!`
1066-
if (isa<ForceValueExpr>(parentExpr)) {
1067-
DE.diagnose(expr->getLoc(), diag::cannot_force_unwrap_nil_literal);
1068-
return Type();
1069-
}
1070-
1071-
// `_ = nil?`
1072-
if (isa<OptionalEvaluationExpr>(parentExpr)) {
1073-
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
1074-
return Type();
1075-
}
1018+
auto literalTy = visitLiteralExpr(expr);
1019+
// Allow `nil` to be a hole so we can diagnose it via a fix
1020+
// if it turns out that there is no contextual information.
1021+
if (auto *typeVar = literalTy->getAs<TypeVariableType>())
1022+
CS.recordPotentialHole(typeVar);
10761023

1077-
// `_ = nil`
1078-
if (auto *assignment = dyn_cast<AssignExpr>(parentExpr)) {
1079-
if (isa<DiscardAssignmentExpr>(assignment->getDest())) {
1080-
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
1081-
return Type();
1082-
}
1083-
}
1084-
}
1085-
1086-
if (!parentExpr && !hasContextualType) {
1087-
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
1088-
return Type();
1089-
}
1090-
1091-
return visitLiteralExpr(expr);
1024+
return literalTy;
10921025
}
10931026

10941027
Type visitFloatLiteralExpr(FloatLiteralExpr *expr) {
@@ -3024,11 +2957,19 @@ namespace {
30242957
TVO_PrefersSubtypeBinding |
30252958
TVO_CanBindToLValue |
30262959
TVO_CanBindToNoEscape);
3027-
2960+
2961+
auto *valueExpr = expr->getSubExpr();
2962+
// It's invalid to force unwrap `nil` literal e.g. `_ = nil!` or
2963+
// `_ = (try nil)!` and similar constructs.
2964+
if (auto *nilLiteral = dyn_cast<NilLiteralExpr>(
2965+
valueExpr->getSemanticsProvidingExpr())) {
2966+
CS.recordFix(SpecifyContextualTypeForNil::create(
2967+
CS, CS.getConstraintLocator(nilLiteral)));
2968+
}
2969+
30282970
// The result is the object type of the optional subexpression.
3029-
CS.addConstraint(ConstraintKind::OptionalObject,
3030-
CS.getType(expr->getSubExpr()), objectTy,
3031-
locator);
2971+
CS.addConstraint(ConstraintKind::OptionalObject, CS.getType(valueExpr),
2972+
objectTy, locator);
30322973
return objectTy;
30332974
}
30342975

test/Constraints/function_builder_diags.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ struct TestConstraintGenerationErrors {
440440

441441
@TupleBuilder var nilWithoutContext: String {
442442
let a = nil // expected-error {{'nil' requires a contextual type}}
443+
""
443444
}
444445

445446
func buildTupleClosure() {

0 commit comments

Comments
 (0)