@@ -905,6 +905,94 @@ bool AttributedFuncToTypeConversionFailure::diagnoseAsError() {
905
905
return true ;
906
906
}
907
907
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
+
908
996
bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse () const {
909
997
auto convertTo = getToType ();
910
998
// If the other side is not a function, we have common case diagnostics
@@ -961,6 +1049,11 @@ bool AttributedFuncToTypeConversionFailure::diagnoseParameterUse() const {
961
1049
diagnostic = diag::passing_noattrfunc_to_attrfunc;
962
1050
}
963
1051
} 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
+
964
1057
if (auto *DRE = dyn_cast<DeclRefExpr>(AE->getSrc ())) {
965
1058
PD = dyn_cast<ParamDecl>(DRE->getDecl ());
966
1059
diagnostic = diag::assigning_noattrfunc_to_attrfunc;
0 commit comments