@@ -549,16 +549,67 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
549549 resultIsOptional, SourceRange ());
550550}
551551
552- // Suggest a default value via ?? <default value>
553- static void offerDefaultValueUnwrapFixit (TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr) {
554- auto diag =
555- TC.diagnose (expr->getLoc (), diag::unwrap_with_default_value);
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+
590+ void MissingOptionalUnwrapFailure::offerDefaultValueUnwrapFixIt (
591+ 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 ;
556599
600+ if (auto param = getOperatorParameterFor (anchor)) {
601+ if (param->isInOut ())
602+ return ;
603+ }
604+
605+ auto diag = emitDiagnostic (expr->getLoc (), diag::unwrap_with_default_value);
606+
607+ auto &TC = getTypeChecker ();
557608 // Figure out what we need to parenthesize.
558609 bool needsParensInside =
559- exprNeedsParensBeforeAddingNilCoalescing (TC, DC, expr);
610+ exprNeedsParensBeforeAddingNilCoalescing (TC, DC, expr);
560611 bool needsParensOutside =
561- exprNeedsParensAfterAddingNilCoalescing (TC, DC, expr, rootExpr );
612+ exprNeedsParensAfterAddingNilCoalescing (TC, DC, expr, getParentExpr () );
562613
563614 llvm::SmallString<2 > insertBefore;
564615 llvm::SmallString<32 > insertAfter;
@@ -580,8 +631,8 @@ static void offerDefaultValueUnwrapFixit(TypeChecker &TC, DeclContext *DC, Expr
580631}
581632
582633// Suggest a force-unwrap.
583- static void offerForceUnwrapFixit (ConstraintSystem &CS, Expr *expr) {
584- auto diag = CS. TC . diagnose (expr->getLoc (), diag::unwrap_with_force_value);
634+ void MissingOptionalUnwrapFailure::offerForceUnwrapFixIt ( Expr *expr) const {
635+ auto diag = emitDiagnostic (expr->getLoc (), diag::unwrap_with_force_value);
585636
586637 // If expr is optional as the result of an optional chain and this last
587638 // dot isn't a member returning optional, then offer to force the last
@@ -590,7 +641,7 @@ static void offerForceUnwrapFixit(ConstraintSystem &CS, Expr *expr) {
590641 if (auto dotExpr =
591642 dyn_cast<UnresolvedDotExpr>(optionalChain->getSubExpr ())) {
592643 auto bind = dyn_cast<BindOptionalExpr>(dotExpr->getBase ());
593- if (bind && !CS. getType (dotExpr)->getOptionalObjectType ()) {
644+ if (bind && !getType (dotExpr)->getOptionalObjectType ()) {
594645 diag.fixItReplace (SourceRange (bind->getLoc ()), " !" );
595646 return ;
596647 }
@@ -601,7 +652,7 @@ static void offerForceUnwrapFixit(ConstraintSystem &CS, Expr *expr) {
601652 diag.fixItInsertAfter (expr->getEndLoc (), " !" );
602653 } else {
603654 diag.fixItInsert (expr->getStartLoc (), " (" )
604- .fixItInsertAfter (expr->getEndLoc (), " )!" );
655+ .fixItInsertAfter (expr->getEndLoc (), " )!" );
605656 }
606657}
607658
@@ -622,8 +673,38 @@ class VarDeclMultipleReferencesChecker : public ASTWalker {
622673 int referencesCount () { return count; }
623674};
624675
625- static bool diagnoseUnwrap (ConstraintSystem &CS, Expr *expr, Expr *rootExpr, Type baseType,
626- Type unwrappedType) {
676+ bool MissingOptionalUnwrapFailure::diagnoseAsError () {
677+ if (hasComplexLocator ())
678+ return false ;
679+
680+ auto *anchor = getAnchor ();
681+
682+ if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
683+ anchor = assignExpr->getSrc ();
684+
685+ auto *unwrappedExpr = anchor->getValueProvidingExpr ();
686+
687+ if (auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrappedExpr)) {
688+ bool isSwift5OrGreater = getASTContext ().isSwiftVersionAtLeast (5 );
689+ auto subExprType = getType (tryExpr->getSubExpr ());
690+ bool subExpressionIsOptional = (bool )subExprType->getOptionalObjectType ();
691+
692+ if (isSwift5OrGreater && subExpressionIsOptional) {
693+ // Using 'try!' won't change the type for a 'try?' with an optional
694+ // sub-expr under Swift 5+, so just report that a missing unwrap can't be
695+ // handled here.
696+ return false ;
697+ }
698+
699+ emitDiagnostic (tryExpr->getTryLoc (), diag::missing_unwrap_optional_try,
700+ getType (anchor)->getRValueType ())
701+ .fixItReplace ({tryExpr->getTryLoc (), tryExpr->getQuestionLoc ()},
702+ " try!" );
703+ return true ;
704+ }
705+
706+ auto baseType = getBaseType ();
707+ auto unwrappedType = getUnwrappedType ();
627708
628709 assert (!baseType->hasTypeVariable () &&
629710 " Base type must not be a type variable" );
@@ -633,15 +714,14 @@ static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Expr *rootExpr, Typ
633714 if (!baseType->getOptionalObjectType ())
634715 return false ;
635716
636- CS. TC . diagnose (expr ->getLoc (), diag::optional_not_unwrapped, baseType ,
637- unwrappedType);
717+ emitDiagnostic (unwrappedExpr ->getLoc (), diag::optional_not_unwrapped,
718+ baseType, unwrappedType);
638719
639720 // If the expression we're unwrapping is the only reference to a
640721 // local variable whose type isn't explicit in the source, then
641722 // offer unwrapping fixits on the initializer as well.
642- if (auto declRef = dyn_cast<DeclRefExpr>(expr )) {
723+ if (auto declRef = dyn_cast<DeclRefExpr>(unwrappedExpr )) {
643724 if (auto varDecl = dyn_cast<VarDecl>(declRef->getDecl ())) {
644-
645725 bool singleUse = false ;
646726 AbstractFunctionDecl *AFD = nullptr ;
647727 if (auto contextDecl = varDecl->getDeclContext ()->getAsDecl ()) {
@@ -658,69 +738,37 @@ static bool diagnoseUnwrap(ConstraintSystem &CS, Expr *expr, Expr *rootExpr, Typ
658738
659739 Expr *initializer = varDecl->getParentInitializer ();
660740 if (auto declRefExpr = dyn_cast<DeclRefExpr>(initializer)) {
661- if (declRefExpr->getDecl ()->getAttrs ().hasAttribute <ImplicitlyUnwrappedOptionalAttr>()) {
662- CS.TC .diagnose (declRefExpr->getLoc (), diag::unwrap_iuo_initializer,
741+ if (declRefExpr->getDecl ()
742+ ->getAttrs ()
743+ .hasAttribute <ImplicitlyUnwrappedOptionalAttr>()) {
744+ emitDiagnostic (declRefExpr->getLoc (), diag::unwrap_iuo_initializer,
663745 baseType);
664746 }
665747 }
666748
667749 auto fnTy = AFD->getInterfaceType ()->castTo <AnyFunctionType>();
668- bool voidReturn = fnTy->getResult ()->isEqual (TupleType::getEmpty (CS.DC ->getASTContext ()));
750+ bool voidReturn =
751+ fnTy->getResult ()->isEqual (TupleType::getEmpty (getASTContext ()));
669752
670- auto diag = CS. TC . diagnose (varDecl->getLoc (), diag::unwrap_with_guard);
753+ auto diag = emitDiagnostic (varDecl->getLoc (), diag::unwrap_with_guard);
671754 diag.fixItInsert (binding->getStartLoc (), " guard " );
672755 if (voidReturn) {
673756 diag.fixItInsertAfter (binding->getEndLoc (), " else { return }" );
674757 } else {
675758 diag.fixItInsertAfter (binding->getEndLoc (), " else { return <"
676- " #default value#" " > }" );
759+ " #default value#"
760+ " > }" );
677761 }
678762 diag.flush ();
679763
680- offerDefaultValueUnwrapFixit (CS.TC , varDecl->getDeclContext (),
681- initializer, rootExpr);
682- offerForceUnwrapFixit (CS, initializer);
764+ offerDefaultValueUnwrapFixIt (varDecl->getDeclContext (), initializer);
765+ offerForceUnwrapFixIt (initializer);
683766 }
684767 }
685768 }
686769
687- offerDefaultValueUnwrapFixit (CS.TC , CS.DC , expr, rootExpr);
688- offerForceUnwrapFixit (CS, expr);
689- return true ;
690- }
691-
692- bool MissingOptionalUnwrapFailure::diagnoseAsError () {
693- if (hasComplexLocator ())
694- return false ;
695-
696- auto *anchor = getAnchor ();
697- auto *rootExpr = getParentExpr ();
698-
699- if (auto assignExpr = dyn_cast<AssignExpr>(anchor))
700- anchor = assignExpr->getSrc ();
701-
702- auto *unwrapped = anchor->getValueProvidingExpr ();
703- auto type = getType (anchor)->getRValueType ();
704-
705- auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
706- if (!tryExpr) {
707- return diagnoseUnwrap (getConstraintSystem (), unwrapped, rootExpr, getBaseType (),
708- getUnwrappedType ());
709- }
710-
711- bool isSwift5OrGreater = getTypeChecker ().getLangOpts ().isSwiftVersionAtLeast (5 );
712- auto subExprType = getType (tryExpr->getSubExpr ());
713- bool subExpressionIsOptional = (bool )subExprType->getOptionalObjectType ();
714-
715-
716- if (isSwift5OrGreater && subExpressionIsOptional) {
717- // Using 'try!' won't change the type for a 'try?' with an optional sub-expr
718- // under Swift 5+, so just report that a missing unwrap can't be handled here.
719- return false ;
720- }
721-
722- emitDiagnostic (tryExpr->getTryLoc (), diag::missing_unwrap_optional_try, type)
723- .fixItReplace ({tryExpr->getTryLoc (), tryExpr->getQuestionLoc ()}, " try!" );
770+ offerDefaultValueUnwrapFixIt (getDC (), unwrappedExpr);
771+ offerForceUnwrapFixIt (unwrappedExpr);
724772 return true ;
725773}
726774
0 commit comments