Skip to content

Commit

Permalink
Merge pull request #34060 from xedin/rdar-69454410-5.3
Browse files Browse the repository at this point in the history
[5.3][CSGen] Check whether parent has a contextual type before diagnosing `nil` use
  • Loading branch information
xedin committed Sep 25, 2020
2 parents 1b2565a + 1421959 commit 9348907
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
33 changes: 30 additions & 3 deletions lib/Sema/CSGen.cpp
Expand Up @@ -1207,8 +1207,35 @@ namespace {
// `_ = nil`, let's diagnose it here because solver can't
// attempt any types for it.
auto *parentExpr = CS.getParentExpr(expr);
while (parentExpr && isa<ParenExpr>(parentExpr))
parentExpr = CS.getParentExpr(parentExpr);
bool hasContextualType = bool(CS.getContextualType(expr));

while (parentExpr) {
if (!isa<IdentityExpr>(parentExpr))
break;

// If there is a parent, use it, otherwise we need
// to check whether the last parent node in the chain
// had a contextual type associated with it because
// in situations like:
//
// \code
// func foo() -> Int? {
// return (nil)
// }
// \endcode
//
// parentheses around `nil` are significant.
if (auto *nextParent = CS.getParentExpr(parentExpr)) {
parentExpr = nextParent;
} else {
hasContextualType |= bool(CS.getContextualType(parentExpr));
// Since current expression is an identity expr
// and there are no more parents, let's pretend
// that `nil` don't have a parent since parens
// are not semantically significant for further checks.
parentExpr = nullptr;
}
}

// In cases like `_ = nil?` AST would have `nil`
// wrapped in `BindOptionalExpr`.
Expand Down Expand Up @@ -1243,7 +1270,7 @@ namespace {
}
}

if (!parentExpr && !CS.getContextualType(expr)) {
if (!parentExpr && !hasContextualType) {
DE.diagnose(expr->getLoc(), diag::unresolved_nil_literal);
return Type();
}
Expand Down
8 changes: 8 additions & 0 deletions test/Constraints/optional.swift
Expand Up @@ -449,4 +449,12 @@ func sr_12309() {
_ = (((nil))) // expected-error {{'nil' requires a contextual type}}
_ = ((((((nil)))))) // expected-error {{'nil' requires a contextual type}}
_ = (((((((((nil))))))))) // expected-error {{'nil' requires a contextual type}}

func test_with_contextual_type_one() -> Int? {
return (nil) // Ok
}

func test_with_contextual_type_many() -> Int? {
return (((nil))) // Ok
}
}

0 comments on commit 9348907

Please sign in to comment.