Skip to content

Commit 1d88c47

Browse files
[Sema] SR-9851 - Add parens when needed for nil coalescing fixits
https://bugs.swift.org/browse/SR-9851
1 parent 29dd7f8 commit 1d88c47

File tree

3 files changed

+21
-8
lines changed

3 files changed

+21
-8
lines changed

lib/Sema/CSApply.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7626,10 +7626,14 @@ bool swift::exprNeedsParensOutsideFollowingOperator(
76267626
Expr *parent;
76277627
unsigned index;
76287628
std::tie(parent, index) = getPrecedenceParentAndIndex(expr, rootExpr);
7629-
if (!parent || isa<TupleExpr>(parent) || isa<ParenExpr>(parent)) {
7629+
if (!parent || isa<TupleExpr>(parent)) {
76307630
return false;
76317631
}
76327632

7633+
if (auto parenExp = dyn_cast<ParenExpr>(parent))
7634+
if (!parenExp->isImplicit())
7635+
return false;
7636+
76337637
if (parent->isInfixOperator()) {
76347638
auto parentPG = TC.lookupPrecedenceGroupForInfixOperator(DC, parent);
76357639
if (!parentPG) return true;

lib/Sema/CSDiagnostics.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -531,15 +531,15 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
531531
}
532532

533533
// Suggest a default value via ?? <default value>
534-
static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr *expr) {
534+
static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr) {
535535
auto diag =
536536
TC.diagnose(expr->getLoc(), diag::unwrap_with_default_value);
537537

538538
// Figure out what we need to parenthesize.
539539
bool needsParensInside =
540540
exprNeedsParensBeforeAddingNilCoalescing(TC, DC, expr);
541541
bool needsParensOutside =
542-
exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, expr);
542+
exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, rootExpr);
543543

544544
llvm::SmallString<2> insertBefore;
545545
llvm::SmallString<32> insertAfter;
@@ -603,7 +603,7 @@ class VarDeclMultipleReferencesChecker : public ASTWalker {
603603
int referencesCount() { return count; }
604604
};
605605

606-
static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Type baseType,
606+
static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Expr *rootExpr, Type baseType,
607607
Type unwrappedType) {
608608

609609
assert(!baseType->hasTypeVariable() &&
@@ -658,14 +658,14 @@ static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Type baseType,
658658
}
659659
diag.flush();
660660

661-
offerDefaultValueUnwrapFixit(CS.TC, varDecl->getDeclContext(),
662-
initializer);
661+
offerDefaultValueUnwrapFixit(CS.TC, varDecl->getDeclContext(),
662+
initializer, rootExpr);
663663
offerForceUnwrapFixit(CS, initializer);
664664
}
665665
}
666666
}
667667

668-
offerDefaultValueUnwrapFixit(CS.TC, CS.DC, expr);
668+
offerDefaultValueUnwrapFixit(CS.TC, CS.DC, expr, rootExpr);
669669
offerForceUnwrapFixit(CS, expr);
670670
return true;
671671
}
@@ -675,6 +675,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
675675
return false;
676676

677677
auto *anchor = getAnchor();
678+
auto *rootExpr = getParentExpr();
678679

679680
if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
680681
anchor = assignExpr->getSrc();
@@ -684,7 +685,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
684685

685686
auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
686687
if (!tryExpr) {
687-
return diagnoseUnwrap(getConstraintSystem(), unwrapped, getBaseType(),
688+
return diagnoseUnwrap(getConstraintSystem(), unwrapped, rootExpr, getBaseType(),
688689
getUnwrappedType());
689690
}
690691

test/Constraints/fixes.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,11 @@ let _: Int = thing?.e?.a() // expected-error {{value of optional type 'Int?' mus
287287
let _: Int? = thing?.e?.b // expected-error {{value of optional type 'Int??' must be unwrapped to a value of type 'Int?'}}
288288
// expected-note@-1{{coalesce}}
289289
// expected-note@-2{{force-unwrap}}
290+
291+
// SR-9851 - https://bugs.swift.org/browse/SR-9851
292+
func coalesceWithParensRootExprFix() {
293+
let optionalBool: Bool? = false
294+
if !optionalBool { } // expected-error{{value of optional type 'Bool?' must be unwrapped to a value of type 'Bool'}}
295+
// expected-note@-1{{coalesce using '??' to provide a default when the optional value contains 'nil'}}{{7-7=(}}{{19-19= ?? <#default value#>)}}
296+
// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
297+
}

0 commit comments

Comments
 (0)