Skip to content

Commit 3940ceb

Browse files
committed
[Diagnostics] Don't suggest unwrap with default value if type is not materializable
1 parent 39dd630 commit 3940ceb

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,8 +549,59 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
549549
resultIsOptional, SourceRange());
550550
}
551551

552+
Optional<AnyFunctionType::Param>
553+
MissingOptionalUnwrapFailure::getOperatorParameterFor(Expr *expr) const {
554+
auto *parentExpr = findParentExpr(expr);
555+
if (!parentExpr)
556+
return None;
557+
558+
auto getArgIdx = [](TupleExpr *tuple, Expr *argExpr) -> unsigned {
559+
for (unsigned i = 0, n = tuple->getNumElements(); i != n; ++i) {
560+
if (tuple->getElement(i) == argExpr)
561+
return i;
562+
}
563+
llvm_unreachable("argument is not in enclosing tuple?!");
564+
};
565+
566+
auto *tupleExpr = dyn_cast<TupleExpr>(parentExpr);
567+
if (!(tupleExpr && tupleExpr->isImplicit()))
568+
return None;
569+
570+
parentExpr = findParentExpr(tupleExpr);
571+
if (!(parentExpr && isa<ApplyExpr>(parentExpr)))
572+
return None;
573+
574+
auto &cs = getConstraintSystem();
575+
auto *fnExpr = cast<ApplyExpr>(parentExpr)->getFn();
576+
if (auto overload =
577+
getOverloadChoiceIfAvailable(cs.getConstraintLocator(fnExpr))) {
578+
if (auto *decl = overload->choice.getDecl()) {
579+
if (!decl->isOperator())
580+
return None;
581+
582+
auto *fnType = overload->openedType->castTo<FunctionType>();
583+
return fnType->getParams()[getArgIdx(tupleExpr, expr)];
584+
}
585+
}
586+
587+
return None;
588+
}
589+
552590
void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt(
553591
DeclContext *DC, Expr *expr) const {
592+
auto *anchor = getAnchor();
593+
594+
// If anchor is an explicit address-of, or expression which produces
595+
// an l-value (e.g. first argument of `+=` operator), let's not
596+
// suggest default value here because that would produce r-value type.
597+
if (isa<InOutExpr>(anchor))
598+
return;
599+
600+
if (auto param = getOperatorParameterFor(anchor)) {
601+
if (param->isInOut())
602+
return;
603+
}
604+
554605
auto diag = emitDiagnostic(expr->getLoc(), diag::unwrap_with_default_value);
555606

556607
auto &TC = getTypeChecker();

lib/Sema/CSDiagnostics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,10 @@ class MissingOptionalUnwrapFailure final : public FailureDiagnostic {
570570
void offerDefaultValueUnwrapFixIt(DeclContext *DC, Expr *expr) const;
571571
/// Suggest a force optional unwrap via `!`
572572
void offerForceUnwrapFixIt(Expr *expr) const;
573+
574+
/// Determine whether given expression is an argument used in the
575+
/// operator invocation, and if so return corresponding parameter.
576+
Optional<AnyFunctionType::Param> getOperatorParameterFor(Expr *expr) const;
573577
};
574578

575579
/// Diagnose errors associated with rvalues in positions

0 commit comments

Comments
 (0)