Skip to content

Commit 51ee1de

Browse files
[Sema] Adjust escapeness function parameter diagnostic to use decl description
1 parent e58dfa9 commit 51ee1de

File tree

4 files changed

+36
-20
lines changed

4 files changed

+36
-20
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3892,8 +3892,8 @@ ERROR(converting_noattrfunc_to_type,none,
38923892
(unsigned, Type))
38933893
ERROR(converting_noattrfunc_contravariant_parameter_position,none,
38943894
"converting escaping to non-escaping functions of type %2 in parameter position "
3895-
"#%0 of function type member %1 is not allowed",
3896-
(unsigned, Identifier, Type))
3895+
"#%0 of function type %3 %1 is not allowed",
3896+
(unsigned, Identifier, Type, DescriptiveDeclKind))
38973897
NOTE(add_explicit_escaping,none,
38983898
"add explicit @escaping to function parameter #%0",
38993899
(unsigned))

lib/Sema/CSDiagnostics.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,24 @@ 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+
908926
bool AttributedFuncToTypeConversionFailure::
909927
diagnoseFunctionParameterEscapenessMismatch(AssignExpr *AE) const {
910928
auto loc = getLocator();
@@ -914,17 +932,8 @@ bool AttributedFuncToTypeConversionFailure::
914932
if (!loc->findLast<LocatorPathElt::FunctionArgument>())
915933
return false;
916934

917-
auto *URDE = dyn_cast<UnresolvedDotExpr>(AE->getDest());
918-
if (!URDE)
919-
return false;
920-
921935
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());
936+
auto decl = getDestinationVarDecl(AE, solution);
928937
if (!decl)
929938
return false;
930939

@@ -938,7 +947,8 @@ bool AttributedFuncToTypeConversionFailure::
938947
auto destInterfaceFnType = destInterfaceType->castTo<FunctionType>();
939948
auto param = destInterfaceFnType->getParams()[mismatchPosition];
940949
emitDiagnostic(diag::converting_noattrfunc_contravariant_parameter_position,
941-
mismatchPosition, decl->getName(), param.getParameterType());
950+
mismatchPosition, decl->getName(), param.getParameterType(),
951+
decl->getDescriptiveKind());
942952

943953
auto note = emitDiagnosticAt(decl->getLoc(), diag::add_explicit_escaping,
944954
mismatchPosition);

test/Constraints/function_conversion.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ func twoFns(_ f: (Int) -> Int, _ g: @escaping (Int) -> Int) {
5757
takesAny(consumeNoEscape)
5858
takesAny(consumeEscaping)
5959

60-
var noEscapeParam: ((Int) -> Int) -> () = consumeNoEscape
60+
var noEscapeParam: ((Int) -> Int) -> () = consumeNoEscape // expected-note {{add explicit @escaping to function parameter}}{{21-21=@escaping }}
6161
var escapingParam: (@escaping (Int) -> Int) -> () = consumeEscaping
62-
noEscapeParam = escapingParam // expected-error {{converting non-escaping value to '(Int) -> Int' may allow it to escape}}
62+
noEscapeParam = escapingParam // expected-error {{converting escaping to non-escaping functions of type '(Int) -> Int' in parameter position #0 of function type var 'noEscapeParam' is not allowed}}
6363

6464
escapingParam = takesAny
6565
noEscapeParam = takesAny // expected-error {{converting non-escaping value to 'Any' may allow it to escape}}

test/attr/attr_escaping.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class FooClass {
153153
}
154154
var computedEscaping : (@escaping ()->Int)->Void {
155155
get { return stored! }
156-
set(newValue) { stored = newValue } // expected-error{{converting escaping to non-escaping functions of type '() -> Int' in parameter position #0 of function type member 'stored' is not allowed}}
156+
set(newValue) { stored = newValue } // expected-error{{converting escaping to non-escaping functions of type '() -> Int' in parameter position #0 of function type property 'stored' is not allowed}}
157157
}
158158
}
159159

@@ -231,6 +231,8 @@ extension SR_9760 {
231231
func foo<T>(_ x: @escaping T) {} // expected-error 1{{@escaping attribute only applies to function types}}
232232

233233
// SR-14720
234+
var global: ((() -> Void) -> Void)? = nil // expected-note {{add explicit @escaping to function parameter #0}} {{15-15=@escaping }}
235+
234236
class SR14720 {
235237
let ok: (@escaping () -> Void) -> Void // OK
236238
let callback: (() -> Void) -> Void // expected-note {{add explicit @escaping to function parameter #0}} {{18-18=@escaping }}
@@ -239,19 +241,23 @@ class SR14720 {
239241
let callbackOpt: ((() -> Void) -> Void)? // expected-note{{add explicit @escaping to function parameter #0}} {{22-22=@escaping }}
240242

241243
init(f: @escaping (@escaping() -> Void) -> Void) {
242-
self.callback = f // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type member 'callback' is not allowed}}
244+
self.callback = f // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type property 'callback' is not allowed}}
243245
self.ok = f // Ok
244246
}
245247

246248
init(af: @escaping (@escaping() -> Void) -> Void) {
247-
self.callbackOpt = af // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type member 'callbackOpt' is not allowed}}
249+
self.callbackOpt = af // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type property 'callbackOpt' is not allowed}}
250+
}
251+
252+
init(ag: @escaping (@escaping() -> Void) -> Void) {
253+
global = ag // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type var 'global' is not allowed}}
248254
}
249255

250256
init(a: @escaping (@escaping () -> Void) -> Void) {
251-
self.callbackAuto = a // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type member 'callbackAuto' is not allowed}}
257+
self.callbackAuto = a // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #0 of function type property 'callbackAuto' is not allowed}}
252258
}
253259

254260
init(f: @escaping (() -> Void, @escaping() -> Void) -> Void) {
255-
self.callback1 = f // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #1 of function type member 'callback1' is not allowed}}
261+
self.callback1 = f // expected-error{{converting escaping to non-escaping functions of type '() -> Void' in parameter position #1 of function type property 'callback1' is not allowed}}
256262
}
257263
}

0 commit comments

Comments
 (0)