Skip to content

Commit 12fb0ba

Browse files
committed
[swift-version] Allow swift-version 4 and tests
The recent @escaping on variadic argument closures back-compat fix is the first Swift 3.0 compatibility behavior that we don't want to carry forwards indefinitely into the future. To address this, we version-gate the diagnostic suppression. Makes it an official compatibility check. Creates new test directory for compatibility testing. Allow -swift-version 4 so that we can test it both ways.
1 parent 54f4103 commit 12fb0ba

File tree

7 files changed

+30
-9
lines changed

7 files changed

+30
-9
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,9 @@ class ASTContext {
784784
clang::ObjCInterfaceDecl *classDecl,
785785
bool forInstance);
786786

787+
/// Whether our effective Swift version is in the Swift 3 family
788+
bool isSwiftVersion3() const { return LangOpts.isSwiftVersion3(); }
789+
787790
private:
788791
friend class Decl;
789792
Optional<RawComment> getRawComment(const Decl *D);

include/swift/Basic/LangOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ namespace swift {
227227
return CustomConditionalCompilationFlags;
228228
}
229229

230+
/// Whether our effective Swift version is in the Swift 3 family
231+
bool isSwiftVersion3() const {
232+
return EffectiveLanguageVersion.isVersion3();
233+
}
234+
230235
/// Returns true if the 'os' platform condition argument represents
231236
/// a supported target operating system.
232237
///

include/swift/Basic/Version.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class Version {
9595
/// are attempting to maintain backward-compatibility support for.
9696
bool isValidEffectiveLanguageVersion() const;
9797

98+
/// Whether this version is in the Swift 3 family
99+
bool isVersion3() const { return !empty() && Components[0] == 3; }
100+
98101
/// Parse a version in the form used by the _compiler_version \#if condition.
99102
static Version parseCompilerVersionString(StringRef VersionString,
100103
SourceLoc Loc,

lib/Basic/Version.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,13 @@ Version::isValidEffectiveLanguageVersion() const
291291
// Whitelist of backward-compatibility versions that we permit passing as
292292
// -swift-version <vers>
293293
char const *whitelist[] = {
294+
// Swift 3 family
294295
"3",
295296
"3.0",
297+
298+
// Swift 4 family
299+
"4",
300+
"4.0",
296301
};
297302
for (auto const i : whitelist) {
298303
auto v = parseVersionString(i, SourceLoc(), nullptr);

lib/Sema/TypeCheckType.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,10 +2034,8 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
20342034
if (attrs.has(TAK_escaping)) {
20352035
// For compatibility with 3.0, we don't emit an error if it appears on a
20362036
// 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;
2037+
bool skipDiagnostic =
2038+
isVariadicFunctionParam && Context.isSwiftVersion3();
20412039

20422040
// The attribute is meaningless except on parameter types.
20432041
bool shouldDiagnose = !isFunctionParam && !skipDiagnostic;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-parse-verify-swift
2+
3+
// This is allowed, in order to keep source compat with Swift version 3.0.
4+
func takesVarargsOfFunctionsExplicitEscaping(_ fns: @escaping () -> ()...) {}
5+
6+
func takesVarargsOfFunctions(_ fn: () -> (), _ fns: () -> ()...) {
7+
// expected-note@-1{{parameter 'fn' is implicitly non-escaping}}
8+
takesVarargsOfFunctionsExplicitEscaping(fns[0], fns[1]) // ok
9+
takesVarargsOfFunctionsExplicitEscaping(fn) // expected-error{{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}
10+
}

test/attr/attr_escaping.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-parse-verify-swift
1+
// RUN: %target-parse-verify-swift -swift-version 4
22

33
@escaping var fn : () -> Int = { 4 } // expected-error {{attribute can only be applied to types, not declarations}}
44
func paramDeclEscaping(@escaping fn: (Int) -> Void) {} // expected-error {{attribute can only be applied to types, not declarations}}
@@ -140,10 +140,7 @@ 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 () -> ()...) {}
143+
func takesVarargsOfFunctionsExplicitEscaping(fns: @escaping () -> ()...) {} // expected-error{{@escaping attribute may only be used in function parameter position}}
147144

148145
func takesNoEscapeFunction(fn: () -> ()) { // expected-note {{parameter 'fn' is implicitly non-escaping}}
149146
takesVarargsOfFunctions(fns: fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an @escaping closure}}

0 commit comments

Comments
 (0)