@@ -905,6 +905,81 @@ bool AttributedFuncToTypeConversionFailure::diagnoseAsError() {
905
905
return true ;
906
906
}
907
907
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
+
908
983
bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse () const {
909
984
auto convertTo = getToType ();
910
985
// If the other side is not a function, we have common case diagnostics
@@ -961,6 +1036,11 @@ bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse() const {
961
1036
diagnostic = diag::passing_noattrfunc_to_attrfunc;
962
1037
}
963
1038
} 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
+
964
1044
if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getSrc ())) {
965
1045
PD = dyn_cast<ParamDecl>(DRE->getDecl ());
966
1046
diagnostic = diag::assigning_noattrfunc_to_attrfunc;
0 commit comments