mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CS] Don't consider implicit TupleExprs in exprNeedsParensOutsideFollowingOperator
Such implicit tuples may be used to represent argument lists for e.g binary expressions, and as such shouldn't be considered as parent exprs that satisfy the role of parentheses. Also fix the callers to use the raw anchor as the root expression they pass to provide an accurate parent map. This requires sinking the UnresolvedMemberChainResultExpr handling logic into `getPrecedenceParentAndIndex`. rdar://81109287
This commit is contained in:
@@ -7891,6 +7891,15 @@ static std::pair<Expr *, unsigned> getPrecedenceParentAndIndex(Expr *expr,
|
||||
}
|
||||
Expr *parent = it->second;
|
||||
|
||||
// Look through an unresolved chain wrapper expr, as it has no effect on
|
||||
// precedence.
|
||||
if (isa<UnresolvedMemberChainResultExpr>(parent)) {
|
||||
it = parentMap.find(parent);
|
||||
if (it == parentMap.end())
|
||||
return {nullptr, 0};
|
||||
parent = it->second;
|
||||
}
|
||||
|
||||
// Handle all cases where the answer isn't just going to be { parent, 0 }.
|
||||
if (auto tuple = dyn_cast<TupleExpr>(parent)) {
|
||||
// Get index of expression in tuple.
|
||||
@@ -7970,13 +7979,13 @@ bool swift::exprNeedsParensOutsideFollowingOperator(
|
||||
Expr *parent;
|
||||
unsigned index;
|
||||
std::tie(parent, index) = getPrecedenceParentAndIndex(expr, rootExpr);
|
||||
if (!parent || isa<TupleExpr>(parent)) {
|
||||
if (!parent)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto parenExp = dyn_cast<ParenExpr>(parent))
|
||||
if (!parenExp->isImplicit())
|
||||
if (isa<ParenExpr>(parent) || isa<TupleExpr>(parent)) {
|
||||
if (!parent->isImplicit())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent->isInfixOperator()) {
|
||||
auto parentPG = TypeChecker::lookupPrecedenceGroupForInfixOperator(DC,
|
||||
|
||||
@@ -1146,6 +1146,7 @@ ASTNode MissingExplicitConversionFailure::getAnchor() const {
|
||||
bool MissingExplicitConversionFailure::diagnoseAsError() {
|
||||
auto *DC = getDC();
|
||||
auto *anchor = castToExpr(getAnchor());
|
||||
auto *rawAnchor = castToExpr(getRawAnchor());
|
||||
|
||||
auto fromType = getFromType();
|
||||
auto toType = getToType();
|
||||
@@ -1171,7 +1172,7 @@ bool MissingExplicitConversionFailure::diagnoseAsError() {
|
||||
}
|
||||
|
||||
bool needsParensInside = exprNeedsParensBeforeAddingAs(anchor);
|
||||
bool needsParensOutside = exprNeedsParensAfterAddingAs(anchor, expr);
|
||||
bool needsParensOutside = exprNeedsParensAfterAddingAs(anchor, rawAnchor);
|
||||
|
||||
llvm::SmallString<2> insertBefore;
|
||||
llvm::SmallString<32> insertAfter;
|
||||
@@ -1310,11 +1311,8 @@ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt(
|
||||
// Figure out what we need to parenthesize.
|
||||
bool needsParensInside =
|
||||
exprNeedsParensBeforeAddingNilCoalescing(DC, const_cast<Expr *>(expr));
|
||||
auto parentExpr = findParentExpr(anchor);
|
||||
if (parentExpr && isa<UnresolvedMemberChainResultExpr>(parentExpr))
|
||||
parentExpr = findParentExpr(parentExpr);
|
||||
bool needsParensOutside = exprNeedsParensAfterAddingNilCoalescing(
|
||||
DC, const_cast<Expr *>(expr), parentExpr);
|
||||
DC, const_cast<Expr *>(expr), castToExpr(getRawAnchor()));
|
||||
|
||||
llvm::SmallString<2> insertBefore;
|
||||
llvm::SmallString<32> insertAfter;
|
||||
|
||||
@@ -258,9 +258,9 @@ func rdar19770981(_ s: String, ns: NSString) {
|
||||
_ = ns as String > s
|
||||
|
||||
// 'as' has lower precedence than '+' so add parens with the fixit:
|
||||
s + ns // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}}{{9-9= as String}}
|
||||
s + ns // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{7-7=(}} {{9-9= as String)}}
|
||||
_ = s + (ns as String)
|
||||
ns + s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}}{{5-5= as String}}
|
||||
ns + s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{3-3=(}} {{5-5= as String)}}
|
||||
_ = (ns as String) + s
|
||||
}
|
||||
|
||||
|
||||
@@ -1415,3 +1415,31 @@ func rdar74696023() {
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
|
||||
}
|
||||
}
|
||||
|
||||
func testUnwrapFixIts(x: Int?) {
|
||||
let _ = x + 2 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{11-11=(}} {{12-12= ?? <#default value#>)}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{12-12=!}}
|
||||
let _ = (x ?? 0) + 2
|
||||
|
||||
let _ = 2 + x // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{15-15=(}} {{16-16= ?? <#default value#>)}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{16-16=!}}
|
||||
let _ = 2 + (x ?? 0)
|
||||
|
||||
func foo(y: Int) {}
|
||||
foo(y: x) // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{11-11= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{11-11=!}}
|
||||
foo(y: x ?? 0)
|
||||
|
||||
let _ = x < 2 // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{12-12= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{12-12=!}}
|
||||
let _ = x ?? 0 < 2
|
||||
|
||||
let _ = 2 < x // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
|
||||
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} {{16-16= ?? <#default value#>}}
|
||||
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{16-16=!}}
|
||||
let _ = 2 < x ?? 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user