Skip to content

Commit e6010be

Browse files
committed
Add support for -disable-upcoming-feature and -disable-experimental-feature.
Synchronize Options.swift with swiftlang/swift#77662 and update the driver to pass all feature related flags down to the frontend together, preserving the order the flags were specified.
1 parent a5f4c3a commit e6010be

File tree

4 files changed

+63
-8
lines changed

4 files changed

+63
-8
lines changed

Sources/SwiftDriver/Jobs/FrontendJobHelpers.swift

+16-8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ extension Driver {
5252
case computed
5353
}
5454

55+
/// If the given option is specified but the frontend doesn't support it, throw an error.
56+
func verifyFrontendSupportsOptionIfNecessary(_ option: Option) throws {
57+
if parsedOptions.hasArgument(option) && !isFrontendArgSupported(option) {
58+
diagnosticEngine.emit(.error_unsupported_opt_for_frontend(option: option))
59+
throw ErrorDiagnostics.emitted
60+
}
61+
}
62+
5563
/// Add frontend options that are common to different frontend invocations.
5664
mutating func addCommonFrontendOptions(
5765
commandLine: inout [Job.ArgTemplate],
@@ -154,6 +162,9 @@ extension Driver {
154162
throw ErrorDiagnostics.emitted
155163
}
156164

165+
try verifyFrontendSupportsOptionIfNecessary(.disableUpcomingFeature)
166+
try verifyFrontendSupportsOptionIfNecessary(.disableExperimentalFeature)
167+
157168
// Handle the CPU and its preferences.
158169
try commandLine.appendLast(.targetCpu, from: &parsedOptions)
159170

@@ -275,14 +286,11 @@ extension Driver {
275286
if isFrontendArgSupported(.compilerAssertions) {
276287
try commandLine.appendLast(.compilerAssertions, from: &parsedOptions)
277288
}
278-
if isFrontendArgSupported(.enableExperimentalFeature) {
279-
try commandLine.appendAll(
280-
.enableExperimentalFeature, from: &parsedOptions)
281-
}
282-
if isFrontendArgSupported(.enableUpcomingFeature) {
283-
try commandLine.appendAll(
284-
.enableUpcomingFeature, from: &parsedOptions)
285-
}
289+
try commandLine.appendAll(.enableExperimentalFeature,
290+
.disableExperimentalFeature,
291+
.enableUpcomingFeature,
292+
.disableUpcomingFeature,
293+
from: &parsedOptions)
286294
try commandLine.appendAll(.moduleAlias, from: &parsedOptions)
287295
if isFrontendArgSupported(.enableBareSlashRegex) {
288296
try commandLine.appendLast(.enableBareSlashRegex, from: &parsedOptions)

Sources/SwiftDriver/Utilities/Diagnostics.swift

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ extension Diagnostic.Message {
3535
.error("unsupported argument '\(argument)' to option '\(option.spelling)'")
3636
}
3737

38+
static func error_unsupported_opt_for_frontend(option: Option) -> Diagnostic.Message {
39+
.error("frontend does not support option '\(option.spelling)'")
40+
}
41+
3842
static func error_option_requires_sanitizer(option: Option) -> Diagnostic.Message {
3943
.error("option '\(option.spelling)' requires a sanitizer to be enabled. Use -sanitize= to enable a sanitizer")
4044
}

Sources/SwiftOptions/Options.swift

+4
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ extension Option {
184184
public static let disableDynamicActorIsolation: Option = Option("-disable-dynamic-actor-isolation", .flag, attributes: [.frontend, .doesNotAffectIncrementalBuild], helpText: "Disable dynamic actor isolation checks")
185185
public static let disableEmitGenericClassRoTList: Option = Option("-disable-emit-generic-class-ro_t-list", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable emission of a section with references to class_ro_t of generic class patterns")
186186
public static let disableExperimentalClangImporterDiagnostics: Option = Option("-disable-experimental-clang-importer-diagnostics", .flag, attributes: [.helpHidden, .frontend, .noDriver, .moduleInterface], helpText: "Disable experimental diagnostics when importing C, C++, and Objective-C libraries")
187+
public static let disableExperimentalFeature: Option = Option("-disable-experimental-feature", .separate, attributes: [.frontend, .moduleInterface], helpText: "Disable an experimental feature")
187188
public static let disableExperimentalLifetimeDependenceInference: Option = Option("-disable-experimental-lifetime-dependence-inference", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable experimental lifetime dependence inference")
188189
public static let disableExperimentalOpenedExistentialTypes: Option = Option("-disable-experimental-opened-existential-types", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable experimental support for implicitly opened existentials")
189190
public static let disableExperimentalParserRoundTrip: Option = Option("-disable-experimental-parser-round-trip", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable round trip through the new swift parser")
@@ -263,6 +264,7 @@ extension Option {
263264
public static let disableThrowsPrediction: Option = Option("-disable-throws-prediction", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disables optimization assumption that functions rarely throw errors.")
264265
public static let disableTypeLayouts: Option = Option("-disable-type-layout", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable type layout based lowering")
265266
public static let disableTypoCorrection: Option = Option("-disable-typo-correction", .flag, attributes: [.frontend, .noDriver], helpText: "Disable typo correction")
267+
public static let disableUpcomingFeature: Option = Option("-disable-upcoming-feature", .separate, attributes: [.frontend, .moduleInterface], helpText: "Disable a feature that will be introduced in an upcoming language version")
266268
public static let disableVerifyExclusivity: Option = Option("-disable-verify-exclusivity", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Disable verification of access markers used to enforce exclusivity.")
267269
public static let disallowForwardingDriver: Option = Option("-disallow-use-new-driver", .flag, helpText: "Disable using new swift-driver")
268270
public static let downgradeTypecheckInterfaceError: Option = Option("-downgrade-typecheck-interface-error", .flag, attributes: [.helpHidden, .frontend, .noDriver], helpText: "Downgrade error to warning when typechecking emitted module interfaces")
@@ -1087,6 +1089,7 @@ extension Option {
10871089
Option.disableDynamicActorIsolation,
10881090
Option.disableEmitGenericClassRoTList,
10891091
Option.disableExperimentalClangImporterDiagnostics,
1092+
Option.disableExperimentalFeature,
10901093
Option.disableExperimentalLifetimeDependenceInference,
10911094
Option.disableExperimentalOpenedExistentialTypes,
10921095
Option.disableExperimentalParserRoundTrip,
@@ -1166,6 +1169,7 @@ extension Option {
11661169
Option.disableThrowsPrediction,
11671170
Option.disableTypeLayouts,
11681171
Option.disableTypoCorrection,
1172+
Option.disableUpcomingFeature,
11691173
Option.disableVerifyExclusivity,
11701174
Option.disallowForwardingDriver,
11711175
Option.downgradeTypecheckInterfaceError,

Tests/SwiftDriverTests/SwiftDriverTests.swift

+39
Original file line numberDiff line numberDiff line change
@@ -8295,6 +8295,45 @@ final class SwiftDriverTests: XCTestCase {
82958295
XCTAssertTrue(!jobs[0].commandLine.contains("-emit-irgen"))
82968296
}
82978297
}
8298+
8299+
func testEnableFeatures() throws {
8300+
do {
8301+
let featureArgs = [
8302+
"-enable-upcoming-feature", "MemberImportVisibility",
8303+
"-enable-experimental-feature", "ParserValidation",
8304+
"-enable-upcoming-feature", "ConcisePoundFile",
8305+
]
8306+
var driver = try Driver(args: ["swiftc", "file.swift"] + featureArgs)
8307+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
8308+
XCTAssertEqual(jobs.count, 2)
8309+
8310+
// Verify that the order of both upcoming and experimental features is preserved.
8311+
XCTAssertTrue(jobs[0].commandLine.contains(subsequence: featureArgs.map { Job.ArgTemplate.flag($0) }))
8312+
}
8313+
}
8314+
8315+
func testDisableFeatures() throws {
8316+
let driver = try Driver(args: ["swiftc", "foo.swift"])
8317+
guard driver.isFrontendArgSupported(.disableUpcomingFeature) else {
8318+
throw XCTSkip("Skipping: compiler does not support '-disable-upcoming-feature'")
8319+
}
8320+
8321+
do {
8322+
let featureArgs = [
8323+
"-enable-upcoming-feature", "MemberImportVisibility",
8324+
"-disable-upcoming-feature", "MemberImportVisibility",
8325+
"-disable-experimental-feature", "ParserValidation",
8326+
"-enable-experimental-feature", "ParserValidation",
8327+
]
8328+
8329+
var driver = try Driver(args: ["swiftc", "file.swift"] + featureArgs)
8330+
let jobs = try driver.planBuild().removingAutolinkExtractJobs()
8331+
XCTAssertEqual(jobs.count, 2)
8332+
8333+
// Verify that the order of both upcoming and experimental features is preserved.
8334+
XCTAssertTrue(jobs[0].commandLine.contains(subsequence: featureArgs.map { Job.ArgTemplate.flag($0) }))
8335+
}
8336+
}
82988337
}
82998338

83008339
func assertString(

0 commit comments

Comments
 (0)