Is -Xfrontend forbidding enough?

There are a handful of things in the Swift ecosystem that we say are "not for general use, and we reserve the right to break you if you use them". Most of these start with underscores (or for initializers or subscripts, have an argument label that starts with an underscore). However, there's a place we don't follow that convention: the compiler driver itself.

Because swiftc is used in build systems (and swift in #! lines), it's important that we don't break people's command lines—a very similar problem to source compatibility. But in order to do that in good faith, we need to clearly delineate which options are okay to rely on and which aren't. Options.td in the Swift repo sort of does this by marking some options HelpHidden, but that's not really a very strong check. Let's see what kind of options are there:

  • Some options with an -enable-experimental- prefix, like -enable-experimental-dependencies. That's pretty clear.

  • Some options with a -no- prefix, where "no" is the default.

  • -incremental. Okay, this one just has a comment "Unhide this once it doesn't depend on an output file map". Anyone want to pick up SR-6079?

  • -enable-batch-mode and -disable-batch-mode. These should probably not be hidden any longer!

  • -enable-testing. This probably ought to be public.

  • -repl, -lldb-repl. Explicit ways to say things you can get without typing anything special. (Kind of surprised -deprecated-integrated-repl is not hidden, given that we keep making it less and less functional.)

  • -autolink-force-load. There's no real reason not to make this public, but there's also not much demand: it's only useful for people building libraries whose clients are going to be linked with swiftc or Apple's ld64. Most Apple people build frameworks, which get autolinking for free, and on Linux SwiftPM handles linking.

  • -typo-correction-limit. Mostly for testing, but setting it to 0 can work around compiler bugs sometimes, so "hidden but without a forbidding name" might be the right balance.

  • -Oplayground. Ooh, a secret optimization mode! Actually just hidden so that no one tries to use it for anything but playgrounds…but we probably can't take it out.

  • -update-code. Part but not all of the Xcode migrator implementation. I know we've posted publicly about it before, so it's also probably here to stay.

  • -warn-swift3-objc-inference. Mostly for dealing with migration from Swift-3-era code…but there's nothing that forces you off of this mode.

  • -enable-parseable-module-interface and -enable-private-imports. This one's hidden because it's under development. They should probably have -experimental- in the name.

  • -import-cf-types and -disable-swift-bridge-attr are both feature flags for things that used to be under development; I think they can be removed now.

  • -assume-single-threaded is a feature flag for something no one is actually working on

  • -solver-memory-threshold, -solver-shrink-unsolved-threshold, and -value-recursion-threshold are options for testing the type checker. I don't know if they're supposed to be in the driver at all. @rudkx, @xedin?

  • -stats-output-dir, -trace-stats-events, -profile-stats-events, -profile-stats-entities. These are hidden from -help because the stats format is unstable, but they're not meant to be secret or anything. They're just not so useful to a normal developer.

  • -Xfrontend, which prompted this post. Every frontend argument is considered unstable. All of them. Even the ones that are the same as driver options. I'd really like to rename this but I don't know what to rename it too. (And to make matters worse, Xcode currently uses it for something. You don't want to know.)

  • -Xclang-linker. Hidden because it only works on some platforms, but it's also not intended to be a secret long-term. Part of this involves whether we'll change swiftc to use clang to link even on Apple platforms.

  • -Xllvm. Hidden because it's not a normal feature, but I also don't think anything passed here counts as "supported". Maybe it's more like -Xfrontend than -Xcc.

  • -resource-dir. Supported but not actually that useful for anything, since the stdlib in the resource directory you pass still has to be compatible with the compiler.

  • A bunch of items with a -driver- prefix, like -driver-print-bindings or -driver-show-incremental. These are all intended for testing the driver, but some of them are also useful for general verbose output, if not necessarily so well designed (or integrated; -driver-show-incremental breaks Xcode's output parsing because it's not compatible with -parseable-output). There's also -### in this set, which is basically public (it's even mentioned in docs/Driver.md).

  • -parse-stdlib. Not something normal people should be using, and definitely not supported, but…not secret either. I don't have a good name to use for this.

  • -import-objc-header, -pch-output-dir, -enable-bridging-pch, -disable-bridging-pch. These are "hidden" because they aren't really supported in command-line builds (and we don't want them to get used on Linux), but Xcode knows how to use them, so we can't change them around. Should we have a name for this kind of option?

Can we do anything to make it clearer which of these are "unstable" or "off-limits"?

P.S. I realize by making a list of "interesting options" that more people are going to try them out, so keep in mind that I made a list of options that might break in the future.

4 Likes

-solver-memory-threshold, -solver-shrink-unsolved-threshold I think we wanted to give developers an ability to set these as a last resort, because it affects the performance of the type-checker. I'm not sure about the last one though, it might be obsolete, what do you think @rudkx?

1 Like
  • -unstable
  • -unsupported
  • -internal
  • -format-partition

These optimize for the scare factor and drop the "frontend" terminology, which I think is fine since very few people need to know what the driver vs. frontend is anyway.

"internal" isn't bad, but it's also important for compiler devs that it's a separate set of options entirely. Maybe "-Xinternal" would be clear enough, since it's like the other -X options.

I don't actually have anything to add to your real question here, but here are a few random comments:

Speaking of which, do we plan on getting rid of this mode at some point? It's technically part of "Swift 3 compatibility". CC @Douglas_Gregor @tkremenek

Are you going to remove these (or file a bug to remove them)?

Should we remove it? Does it even work anymore? You have to build your own runtime and stdlib for it too, IIRC.

What's the problem with -import-objc-header on Linux? Perhaps it should be renamed, but it's a quick and dirty way to test C interoperability.

Swift does not have source compatibility requirements in the same way that, say, JavaScript has source compatibility requirements. Shipping a new compiler does not affect any code in production; there is always a cycle where programmers have an opportunity to react. In that light, the purpose of creating a private namespace like -Xfrontend and documenting it as unstable and undependable is not to affirmatively prevent people from using it, it's to make it clear that we aren't generally going to worry about people who use it. Such people have made a legitimate engineering decision: they wanted to get some benefit from it more than they wanted to avoid the risk of getting their build broken at the next compiler release.

All of this is to say that I don't think it's worthwhile to spend a bunch of time renaming the option to make it scarier.

Xcode using -Xfrontend options is unfortunate only because it potentially limits the documented ability of users to use new toolchains from swift.org.

2 Likes

Very deep meta-question: Is the command line interface of the compiler part of "source compatibility"?

4 Likes

I would say so: source compatibility in my opinion is a broad statement that existing projects will continue to build (and run with generally equivalent semantics) if they obey certain reasonable constraints. A programmer having to update their build scripts to replace -o with -output is just as much a compatibility break as a programmer having to update their source code to replace String with Text.

6 Likes