@@ -905,6 +905,81 @@ bool AttributedFuncToTypeConversionFailure::diagnoseAsError() {
905905 return true ;
906906}
907907
908+ bool AttributedFuncToTypeConversionFailure::
909+ diagnoseFunctionParameterEscapenessMismatch (AssignExpr *AE) const {
910+ auto loc = getLocator ();
911+ if (attributeKind != Escaping)
912+ return false ;
913+
914+ if (!loc->findLast <LocatorPathElt::FunctionArgument>())
915+ return false ;
916+
917+ auto *URDE = dyn_cast<UnresolvedDotExpr>(AE->getDest ());
918+ if (!URDE)
919+ return false ;
920+
921+ auto &solution = getSolution ();
922+ auto memberLoc = getConstraintLocator (URDE, ConstraintLocator::Member);
923+ auto overload = solution.getOverloadChoiceIfAvailable (memberLoc);
924+ if (!overload)
925+ return false ;
926+
927+ auto decl = dyn_cast_or_null<VarDecl>(overload->choice .getDecl ());
928+ if (!decl)
929+ return false ;
930+
931+ // The tuple locator element will give us the exact parameter mismatch
932+ // position.
933+ auto tupleElt = loc->getLastElementAs <LocatorPathElt::TupleElement>();
934+ auto mismatchPosition = tupleElt ? tupleElt->getIndex () : 0 ;
935+
936+ auto destInterfaceType =
937+ decl->getInterfaceType ()->lookThroughAllOptionalTypes ();
938+ auto destInterfaceFnType = destInterfaceType->castTo <FunctionType>();
939+ auto param = destInterfaceFnType->getParams ()[mismatchPosition];
940+ emitDiagnostic (diag::converting_noattrfunc_contravariant_parameter_position,
941+ mismatchPosition, decl->getName (), param.getParameterType ());
942+
943+ auto note = emitDiagnosticAt (decl->getLoc (), diag::add_explicit_escaping,
944+ mismatchPosition);
945+
946+ auto declRepr = decl->getTypeReprOrParentPatternTypeRepr ();
947+ class TopLevelFuncReprFinder : public ASTWalker {
948+ bool walkToTypeReprPre (TypeRepr *TR) override {
949+ FnRepr = dyn_cast<FunctionTypeRepr>(TR);
950+ return FnRepr == nullptr ;
951+ }
952+
953+ public:
954+ FunctionTypeRepr *FnRepr;
955+ TopLevelFuncReprFinder () : FnRepr(nullptr ) {}
956+ };
957+
958+ // Look to find top-level function repr that maybe inside optional
959+ // representations.
960+ TopLevelFuncReprFinder fnFinder;
961+ declRepr->walk (fnFinder);
962+
963+ auto declFnRepr = fnFinder.FnRepr ;
964+ if (!declFnRepr)
965+ return false ;
966+
967+ auto argsRepr = declFnRepr->getArgsTypeRepr ();
968+ auto argRepr = argsRepr->getElement (mismatchPosition).Type ;
969+ if (!param.isAutoClosure ()) {
970+ note.fixItInsert (argRepr->getStartLoc (), " @escaping " );
971+ } else {
972+ auto attrRepr = dyn_cast<AttributedTypeRepr>(argRepr);
973+ if (attrRepr) {
974+ auto autoclosureEndLoc = Lexer::getLocForEndOfToken (
975+ getASTContext ().SourceMgr ,
976+ attrRepr->getAttrs ().getLoc (TAK_autoclosure));
977+ note.fixItInsertAfter (autoclosureEndLoc, " @escaping" );
978+ }
979+ }
980+ return true ;
981+ }
982+
908983bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse () const {
909984 auto convertTo = getToType ();
910985 // If the other side is not a function, we have common case diagnostics
@@ -961,6 +1036,11 @@ bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse() const {
9611036 diagnostic = diag::passing_noattrfunc_to_attrfunc;
9621037 }
9631038 } else if (auto *AE = getAsExpr<AssignExpr>(getRawAnchor ())) {
1039+ // Attempt to diagnose escape/non-escape mismatch in function
1040+ // parameter position.
1041+ if (diagnoseFunctionParameterEscapenessMismatch (AE))
1042+ return true ;
1043+
9641044 if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getSrc ())) {
9651045 PD = dyn_cast<ParamDecl>(DRE->getDecl ());
9661046 diagnostic = diag::assigning_noattrfunc_to_attrfunc;
0 commit comments