Skip to content

Commit d2d830f

Browse files
authored
[test] Warning about Swift features that do not exist (#77542)
Sometimes features are removed from `Features.def`, but they are not removed from the test files. The compiler ignores every feature that does not exist. This leads to removed features still being tested, and with the introduction of #76740, `REQUIRED:`. Modify the code that generates the active feature set for testing to also generate the set of existing features, and pass this list of existing features to the verifier script. If a feature is trying to be activated and does not exist, the verifier will warn the user. - `SwiftParser` feature was renamed `ParserASTGen`, but some tests were using both spellings. Remove the mentions of `SwiftParser` in the tests. - `ImportObjcForwardDeclarations` was spelled with upper case `C` in a couple of tests. Fix it so the matching is easier. - `TransferringArgsAndResults` was an experimental feature that was removed. - Ignore the usage of inexisting feature in `swift-export-as.swift` because it seems to be what the test is actually testing. - Ignore the test `availability_define.swift` because it tests the pseudo-feature `AvailabilityMacro=` which is not part of `Features.def`.
1 parent e2f6133 commit d2d830f

File tree

6 files changed

+118
-88
lines changed

6 files changed

+118
-88
lines changed

test/ClangImporter/incomplete_objc_types_full_availability.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
// RUN: %target-clang %S/Inputs/custom-modules/IncompleteTypes/incomplete-type-library-1.m -c -o %t/incomplete-type-library-1.o
33
// RUN: %target-clang %S/Inputs/custom-modules/IncompleteTypes/complete-types.m -c -o %t/complete-types.o
44

5-
// RUN: %target-build-swift -Xfrontend -enable-upcoming-feature -Xfrontend ImportObjCForwardDeclarations -Xfrontend -enable-objc-interop -I %S/Inputs/custom-modules/IncompleteTypes %s %t/incomplete-type-library-1.o %t/complete-types.o -Xlinker -framework -Xlinker Foundation -o %t/a.out
5+
// RUN: %target-build-swift -Xfrontend -enable-upcoming-feature -Xfrontend ImportObjcForwardDeclarations -Xfrontend -enable-objc-interop -I %S/Inputs/custom-modules/IncompleteTypes %s %t/incomplete-type-library-1.o %t/complete-types.o -Xlinker -framework -Xlinker Foundation -o %t/a.out
66
// RUN: %target-run %t/a.out
77

88
// REQUIRES: objc_interop
99
// REQUIRES: executable_test
10-
// REQUIRES: swift_feature_ImportObjCForwardDeclarations
10+
// REQUIRES: swift_feature_ImportObjcForwardDeclarations
1111

1212
import IncompleteTypeLibrary1
1313
import CompleteTypes

test/Concurrency/sending_continuation.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
// RUN: %target-swift-frontend -emit-sil -swift-version 6 -target %target-swift-5.1-abi-triple -enable-experimental-feature TransferringArgsAndResults -verify %s -o /dev/null -parse-as-library
1+
// RUN: %target-swift-frontend -emit-sil -swift-version 6 -target %target-swift-5.1-abi-triple -verify %s -o /dev/null -parse-as-library
22

33
// REQUIRES: concurrency
4-
// REQUIRES: swift_feature_TransferringArgsAndResults
54

65
////////////////////////
76
// MARK: Declarations //
Lines changed: 104 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#! /usr/bin/env python3
22
# -*- python -*-
3-
# RUN: %{python} %s '%swift_src_root'
3+
# RUN: %{python} %s '%swift_src_root' %existing-swift-features
44

5+
import json
56
import pathlib
67
import re
78
import subprocess
@@ -11,8 +12,14 @@ import sys
1112
# Tests that check for the behaviour of experimental/upcoming features, so
1213
# they cannot automatically be checked.
1314
EXCEPTIONAL_FILES = [
15+
# Tests for ParserValidation not being defined in no-asserts compilers
1416
pathlib.Path("test/Frontend/experimental-features-no-asserts.swift"),
17+
# Tests for UnknownFeature not existing
1518
pathlib.Path("test/Frontend/upcoming_feature.swift"),
19+
# Tests for ModuleInterfaceExportAs being ignored
20+
pathlib.Path("test/ModuleInterface/swift-export-as.swift"),
21+
# Uses the pseudo-feature AvailabilityMacro=
22+
pathlib.Path("test/Sema/availability_define.swift"),
1623
]
1724

1825
FEATURE_USAGE_RE = re.compile(
@@ -28,16 +35,19 @@ def find_test_files_with_features_usage(swift_src_root):
2835
# mention `-enable-experimental-feature` or `-enable-upcoming-feature`.
2936
# Be careful of not using REQUIRES or RUN with a colon after them or Lit will
3037
# pick them up.
31-
output = subprocess.check_output([
32-
"grep",
33-
"--extended-regexp",
34-
"--recursive",
35-
"-e",
36-
"RUN[:].*-enable-(experimental|upcoming)-feature",
37-
"--files-with-matches",
38-
str(swift_src_root / "test"),
39-
str(swift_src_root / "validation-test"),
40-
], text=True)
38+
output = subprocess.check_output(
39+
[
40+
"grep",
41+
"--extended-regexp",
42+
"--recursive",
43+
"-e",
44+
"RUN[:].*-enable-(experimental|upcoming)-feature",
45+
"--files-with-matches",
46+
str(swift_src_root / "test"),
47+
str(swift_src_root / "validation-test"),
48+
],
49+
text=True,
50+
)
4151
return output.splitlines()
4252

4353

@@ -46,91 +56,110 @@ def find_test_files_with_marker_usage(swift_src_root):
4656
# that mention `swift_feature_`.
4757
# Be careful of not using REQUIRES with a colon after them or Lit will
4858
# pick them up.
49-
output = subprocess.check_output([
50-
"grep",
51-
"--extended-regexp",
52-
"--recursive",
53-
"-e",
54-
"REQUIRES[:].*swift_feature_",
55-
"--files-with-matches",
56-
str(swift_src_root / "test"),
57-
str(swift_src_root / "validation-test"),
58-
], text=True)
59+
output = subprocess.check_output(
60+
[
61+
"grep",
62+
"--extended-regexp",
63+
"--recursive",
64+
"-e",
65+
"REQUIRES[:].*swift_feature_",
66+
"--files-with-matches",
67+
str(swift_src_root / "test"),
68+
str(swift_src_root / "validation-test"),
69+
],
70+
text=True,
71+
)
5972
return output.splitlines()
6073

6174

6275
def find_run_lines(test_file):
63-
output = subprocess.check_output([
64-
"grep",
65-
"--extended-regexp",
66-
"--no-filename",
67-
"-e",
68-
"RUN[:]",
69-
str(test_file),
70-
], text=True)
76+
output = subprocess.check_output(
77+
[
78+
"grep",
79+
"--extended-regexp",
80+
"--no-filename",
81+
"-e",
82+
"RUN[:]",
83+
str(test_file),
84+
],
85+
text=True,
86+
)
7187
return output.splitlines()
7288

7389

7490
def find_requires_lines(test_file):
75-
output = subprocess.check_output([
76-
"grep",
77-
"--extended-regexp",
78-
"--no-filename",
79-
"-e",
80-
"REQUIRES[:]",
81-
str(test_file),
82-
], text=True)
91+
output = subprocess.check_output(
92+
[
93+
"grep",
94+
"--extended-regexp",
95+
"--no-filename",
96+
"-e",
97+
"REQUIRES[:]",
98+
str(test_file),
99+
],
100+
text=True,
101+
)
83102
return output.splitlines()
84103

85104

86105
def check_existing_requires(test_file, feature):
87-
returncode = subprocess.call([
88-
"grep",
89-
"--extended-regexp",
90-
"--quiet",
91-
"-e",
92-
"REQUIRES[:].*swift_feature_" + feature,
93-
str(test_file),
94-
])
106+
returncode = subprocess.call(
107+
[
108+
"grep",
109+
"--extended-regexp",
110+
"--quiet",
111+
"-e",
112+
"REQUIRES[:].*swift_feature_" + feature,
113+
str(test_file),
114+
]
115+
)
95116
return returncode != 0
96117

97118

98119
def check_existing_feature_usage(test_file, feature):
99-
returncode = subprocess.call([
100-
"grep",
101-
"--extended-regexp",
102-
"--quiet",
103-
"-e",
104-
(
105-
"RUN[:].*-enable-(experimental|upcoming)-feature (-Xfrontend )?"
106-
+ re.escape(feature)
107-
),
108-
str(test_file),
109-
])
120+
returncode = subprocess.call(
121+
[
122+
"grep",
123+
"--extended-regexp",
124+
"--quiet",
125+
"-e",
126+
(
127+
"RUN[:].*-enable-(experimental|upcoming)-feature (-Xfrontend )?"
128+
+ re.escape(feature)
129+
),
130+
str(test_file),
131+
]
132+
)
110133
return returncode != 0
111134

112135

113136
def check_existing_error_message_checks(test_file, feature):
114-
returncode = subprocess.call([
115-
"grep",
116-
"--extended-regexp",
117-
"--quiet",
118-
"-e",
119-
"requires '-enable-(experimental|upcoming)-feature " + feature + "'",
120-
str(test_file),
121-
])
137+
returncode = subprocess.call(
138+
[
139+
"grep",
140+
"--extended-regexp",
141+
"--quiet",
142+
"-e",
143+
"requires '-enable-(experimental|upcoming)-feature " + feature + "'",
144+
str(test_file),
145+
]
146+
)
122147
return returncode != 0
123148

124149

125-
def check_test_file_feature_usage(test_file):
150+
def check_test_file_feature_usage(test_file, existing_swift_features):
126151
run_lines = find_run_lines(test_file)
127152
features = set(
128-
feature
129-
for line in run_lines
130-
for feature in FEATURE_USAGE_RE.findall(line)
153+
feature for line in run_lines for feature in FEATURE_USAGE_RE.findall(line)
131154
)
132155
num_failures = 0
133156
for feature in features:
157+
# First, check this is a valid feature
158+
if feature not in existing_swift_features:
159+
print("error: {}: Unknown feature: {}".format(str(test_file), feature))
160+
num_failures += 1
161+
continue
162+
134163
# No warning if the necessary `REQUIRES` is already there
135164
if not check_existing_requires(test_file, feature):
136165
continue
@@ -142,9 +171,7 @@ def check_test_file_feature_usage(test_file):
142171
# For everything else, print a warning and add to the invalid exit code
143172
print(
144173
"error: {}: Missing '{}: swift_feature_{}'".format(
145-
str(test_file),
146-
"REQUIRES",
147-
feature
174+
str(test_file), "REQUIRES", feature
148175
)
149176
)
150177
num_failures += 1
@@ -167,20 +194,20 @@ def check_test_file_marker_usage(test_file):
167194
# For everything else, print a warning and add to the invalid exit code
168195
print(
169196
"error: {}: Missing '-enable-experimental/upcoming-feature: {}'".format(
170-
str(test_file),
171-
feature
197+
str(test_file), feature
172198
)
173199
)
174200
num_failures += 1
175201
return num_failures == 0
176202

177203

178204
def main():
179-
if len(sys.argv) < 2:
180-
print('Invalid number of arguments.')
205+
if len(sys.argv) < 3:
206+
print("Invalid number of arguments.")
181207
sys.exit(1)
182208

183209
swift_src_root = pathlib.Path(sys.argv[1])
210+
existing_swift_features = set(json.loads(sys.argv[2]))
184211

185212
num_failures = 0
186213
test_files_with_features_usage = find_test_files_with_features_usage(swift_src_root)
@@ -190,7 +217,7 @@ def main():
190217
if test_file.relative_to(swift_src_root) in EXCEPTIONAL_FILES:
191218
continue
192219

193-
if not check_test_file_feature_usage(test_file):
220+
if not check_test_file_feature_usage(test_file, existing_swift_features):
194221
num_failures += 1
195222

196223
test_files_with_marker_usage = find_test_files_with_marker_usage(swift_src_root)
@@ -208,5 +235,5 @@ def main():
208235
sys.exit(1)
209236

210237

211-
if __name__ == '__main__':
238+
if __name__ == "__main__":
212239
main()

test/Sema/availability_define.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
// RUN: -enable-experimental-feature AvailabilityMacro="_myProject 2.5:macOS 52.5"
1616

1717
// REQUIRES: OS=macosx
18-
// REQUIRES: swift_feature_AvailabilityMacro
1918

2019
@available(_iOS53Aligned, *)
2120
public func onMacOS50() {}

test/lit.cfg

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@
1818
#
1919
# -----------------------------------------------------------------------------
2020

21+
import glob
22+
import json
2123
import os
2224
import platform
2325
import re
2426
import shlex
2527
import shutil
28+
import socket
2629
import subprocess
2730
import sys
28-
import socket
29-
import glob
3031

3132
import lit
3233
import lit.formats
@@ -790,6 +791,8 @@ config.substitutions.append( ('%clang',
790791
"%r %s" %
791792
(config.clang, clang_mcp_opt)) )
792793

794+
config.substitutions.append(('%existing-swift-features', shlex.quote(json.dumps(list(config.existing_swift_features)))))
795+
793796
###
794797

795798
def disallow(execName):

test/lit.swift-features.cfg.inc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
* statements).
2323
*/
2424

25+
config.existing_swift_features = set()
2526
def language_feature(feature_name, enabled):
27+
config.existing_swift_features.add(feature_name)
2628
if enabled or "asserts" in config.available_features:
27-
config.available_features.add(feature_name)
29+
config.available_features.add("swift_feature_" + feature_name)
2830

29-
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) language_feature("swift_feature_" # FeatureName, True)
30-
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) language_feature("swift_feature_" # FeatureName, #AvailableInProd == "true")
31-
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) language_feature("swift_feature_" # FeatureName, True)
31+
#define UPCOMING_FEATURE(FeatureName, SENumber, Version) language_feature(#FeatureName, True)
32+
#define EXPERIMENTAL_FEATURE(FeatureName, AvailableInProd) language_feature(#FeatureName, #AvailableInProd == "true")
33+
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) language_feature(#FeatureName, True)
3234

3335
#include <swift/Basic/Features.def>

0 commit comments

Comments
 (0)