@@ -905,6 +905,94 @@ bool AttributedFuncToTypeConversionFailure::diagnoseAsError() {
905905 return true ;
906906}
907907
908+ static VarDecl *getDestinationVarDecl (AssignExpr *AE,
909+ const Solution &solution) {
910+ ConstraintLocator *locator = nullptr ;
911+ if (auto *URDE = dyn_cast<UnresolvedDotExpr>(AE->getDest ())) {
912+ locator = solution.getConstraintLocator (URDE, {ConstraintLocator::Member});
913+ } else if (auto *declRef = dyn_cast<DeclRefExpr>(AE->getDest ())) {
914+ locator = solution.getConstraintLocator (declRef);
915+ }
916+ if (!locator)
917+ return nullptr ;
918+
919+ auto overload = solution.getOverloadChoiceIfAvailable (locator);
920+ if (!overload)
921+ return nullptr ;
922+
923+ return dyn_cast_or_null<VarDecl>(overload->choice .getDecl ());
924+ }
925+
926+ bool AttributedFuncToTypeConversionFailure::
927+ diagnoseFunctionParameterEscapenessMismatch (AssignExpr *AE) const {
928+ auto loc = getLocator ();
929+ if (attributeKind != Escaping)
930+ return false ;
931+
932+ if (!loc->findLast <LocatorPathElt::FunctionArgument>())
933+ return false ;
934+
935+ auto destType = getType (AE->getDest ())->lookThroughAllOptionalTypes ();
936+ auto destFnType = destType->castTo <FunctionType>();
937+ auto sourceType = getType (AE->getSrc ())->lookThroughAllOptionalTypes ();
938+
939+ // The tuple locator element will give us the exact parameter mismatch
940+ // position.
941+ auto tupleElt = loc->getLastElementAs <LocatorPathElt::TupleElement>();
942+ auto mismatchPosition = tupleElt ? tupleElt->getIndex () : 0 ;
943+ auto param = destFnType->getParams ()[mismatchPosition];
944+
945+ emitDiagnostic (diag::cannot_convert_assign, sourceType, destType);
946+ emitDiagnosticAt (AE->getDest ()->getLoc (),
947+ diag::escape_expected_at_parameter_position,
948+ mismatchPosition, param.getParameterType ());
949+
950+ auto &solution = getSolution ();
951+ auto decl = getDestinationVarDecl (AE, solution);
952+ // We couldn't find a declaration to add an extra note with a fix-it but
953+ // the main diagnostic was already covered.
954+ if (!decl)
955+ return true ;
956+
957+ auto declRepr = decl->getTypeReprOrParentPatternTypeRepr ();
958+ class TopLevelFuncReprFinder : public ASTWalker {
959+ bool walkToTypeReprPre (TypeRepr *TR) override {
960+ FnRepr = dyn_cast<FunctionTypeRepr>(TR);
961+ return FnRepr == nullptr ;
962+ }
963+
964+ public:
965+ FunctionTypeRepr *FnRepr;
966+ TopLevelFuncReprFinder () : FnRepr(nullptr ) {}
967+ };
968+
969+ // Look to find top-level function repr that maybe inside optional
970+ // representations.
971+ TopLevelFuncReprFinder fnFinder;
972+ declRepr->walk (fnFinder);
973+
974+ auto declFnRepr = fnFinder.FnRepr ;
975+ if (!declFnRepr)
976+ return true ;
977+
978+ auto note = emitDiagnosticAt (decl->getLoc (), diag::add_explicit_escaping,
979+ mismatchPosition);
980+ auto argsRepr = declFnRepr->getArgsTypeRepr ();
981+ auto argRepr = argsRepr->getElement (mismatchPosition).Type ;
982+ if (!param.isAutoClosure ()) {
983+ note.fixItInsert (argRepr->getStartLoc (), " @escaping " );
984+ } else {
985+ auto attrRepr = dyn_cast<AttributedTypeRepr>(argRepr);
986+ if (attrRepr) {
987+ auto autoclosureEndLoc = Lexer::getLocForEndOfToken (
988+ getASTContext ().SourceMgr ,
989+ attrRepr->getAttrs ().getLoc (TAK_autoclosure));
990+ note.fixItInsertAfter (autoclosureEndLoc, " @escaping" );
991+ }
992+ }
993+ return true ;
994+ }
995+
908996bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse () const {
909997 auto convertTo = getToType ();
910998 // If the other side is not a function, we have common case diagnostics
@@ -961,6 +1049,11 @@ bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse() const {
9611049 diagnostic = diag::passing_noattrfunc_to_attrfunc;
9621050 }
9631051 } else if (auto *AE = getAsExpr<AssignExpr>(getRawAnchor ())) {
1052+ // Attempt to diagnose escape/non-escape mismatch in function
1053+ // parameter position.
1054+ if (diagnoseFunctionParameterEscapenessMismatch (AE))
1055+ return true ;
1056+
9641057 if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getSrc ())) {
9651058 PD = dyn_cast<ParamDecl>(DRE->getDecl ());
9661059 diagnostic = diag::assigning_noattrfunc_to_attrfunc;
0 commit comments