Skip to content

Commit 8e5d5ed

Browse files
authored
Merge pull request #22802 from xcadaverx/xcadaverx/SR-9851_Incorrect_fix_it_logical_not_optional_bool
[Sema] SR-9851 - Add parens when needed for nil coalescing fixits
2 parents d9f21b7 + 1d88c47 commit 8e5d5ed

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
@@ -546,15 +546,15 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
546546
}
547547

548548
// Suggest a default value via ?? <default value>
549-
static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr *expr) {
549+
static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr) {
550550
auto diag =
551551
TC.diagnose(expr->getLoc(), diag::unwrap_with_default_value);
552552

553553
// Figure out what we need to parenthesize.
554554
bool needsParensInside =
555555
exprNeedsParensBeforeAddingNilCoalescing(TC, DC, expr);
556556
bool needsParensOutside =
557-
exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, expr);
557+
exprNeedsParensAfterAddingNilCoalescing(TC, DC, expr, rootExpr);
558558

559559
llvm::SmallString<2> insertBefore;
560560
llvm::SmallString<32> insertAfter;
@@ -618,7 +618,7 @@ class VarDeclMultipleReferencesChecker : public ASTWalker {
618618
int referencesCount() { return count; }
619619
};
620620

621-
static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Type baseType,
621+
static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Expr *rootExpr, Type baseType,
622622
Type unwrappedType) {
623623

624624
assert(!baseType->hasTypeVariable() &&
@@ -673,14 +673,14 @@ static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Type baseType,
673673
}
674674
diag.flush();
675675

676-
offerDefaultValueUnwrapFixit(CS.TC, varDecl->getDeclContext(),
677-
initializer);
676+
offerDefaultValueUnwrapFixit(CS.TC, varDecl->getDeclContext(),
677+
initializer, rootExpr);
678678
offerForceUnwrapFixit(CS, initializer);
679679
}
680680
}
681681
}
682682

683-
offerDefaultValueUnwrapFixit(CS.TC, CS.DC, expr);
683+
offerDefaultValueUnwrapFixit(CS.TC, CS.DC, expr, rootExpr);
684684
offerForceUnwrapFixit(CS, expr);
685685
return true;
686686
}
@@ -690,6 +690,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
690690
return false;
691691

692692
auto *anchor = getAnchor();
693+
auto *rootExpr = getParentExpr();
693694

694695
if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
695696
anchor = assignExpr->getSrc();
@@ -699,7 +700,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
699700

700701
auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
701702
if (!tryExpr) {
702-
return diagnoseUnwrap(getConstraintSystem(), unwrapped, getBaseType(),
703+
return diagnoseUnwrap(getConstraintSystem(), unwrapped, rootExpr, getBaseType(),
703704
getUnwrappedType());
704705
}
705706

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)