Skip to content

Commit 54f4103

Browse files
committed
[3.0 compat] Don't diagnose @escaping var-arg closures.
Var-arg closures are already escaping, so we typically want to issue an error if @escaping is specified. To not do sure will confuse and give a false impression on the un-annotated semantics and whether it is needed. But, 3.0 shipped with a bug where we didn't consistently apply the no-escape-by-default rule here, and thus it was semantically meaningful (and needed). In order to preserve source compatibility, albeit at the expense of developers on versions 3.0.1 and later in the Swift 3 family, we suppress the error if we see @escaping. Either way, this is a relatively uncommon usage, so the confusion won't be too wide spread.
1 parent 430a0d8 commit 54f4103

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2032,8 +2032,16 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
20322032
// Handle @escaping
20332033
if (hasFunctionAttr && ty->is<FunctionType>()) {
20342034
if (attrs.has(TAK_escaping)) {
2035+
// For compatibility with 3.0, we don't emit an error if it appears on a
2036+
// variadic argument list.
2037+
//
2038+
// FIXME: Version-gate on Swift language version 3, as we don't want its
2039+
// presence to confuse users.
2040+
bool skipDiagnostic = isVariadicFunctionParam;
2041+
20352042
// The attribute is meaningless except on parameter types.
2036-
if (!isFunctionParam) {
2043+
bool shouldDiagnose = !isFunctionParam && !skipDiagnostic;
2044+
if (shouldDiagnose) {
20372045
auto &SM = TC.Context.SourceMgr;
20382046
auto loc = attrs.getLoc(TAK_escaping);
20392047
auto attrRange = SourceRange(

test/attr/attr_escaping.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ func takesVarargsOfFunctions(fns: () -> ()...) {
140140
}
141141
}
142142

143+
// This is allowed, in order to keep source compat with Swift version 3.0.
144+
//
145+
// FIXME: version-gate on Swift version 3
146+
func takesVarargsOfFunctionsExplicitEscaping(fns: @escaping () -> ()...) {}
147+
143148
func takesNoEscapeFunction(fn: () -> ()) { // expected-note {{parameter 'fn' is implicitly non-escaping}}
144149
takesVarargsOfFunctions(fns: fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
145150
}

0 commit comments

Comments
 (0)