[Pitch] Compile-Time Constant Values

I wonder if we should perhaps be thinking more broadly about this. I think there is a lot to be gained by substituting "compile-time" with "build-time".

SwiftPM recently gained support for plugins. Wouldn't it be better for a type like URL to perform its validation as some kind of linting plugin?

Doing that would avoid the need to define interfaces or worry about future-proofing, and reflect the fact that, as you say, the object itself often can't be created statically.

URL parsing can change, and previously-valid URLs may become invalid. That is obviously done with great care by contributors to the standard - for example, recently, the Google Chrome team discovered that the URL host parser definition had a potentially dangerous interaction when considering whether two URLs were "same site", and this could have serious security and privacy implications. After analysing telemetry data, it was determined that the most reasonable course of action (i.e. with the least breakage) was to declare some URLs invalid if their hostname ends in a number (e.g. http://0.1.2.3.4.5/ is now an invalid URL, interpreted as containing an invalid IPv4 address; previously it was allowed and interpreted as referring to a domain). The data showed that these made up something like 0.0001% of all requests, and most of them failed to resolve to anything anyway.

That's something very specific to URLs, but it is illustrative of the dangers generally when statically initialising objects. What if we had embedded an object for http://0.1.2.3.4.5/ in the binary, and it dynamically links against a new version of the library, which considers that object invalid? What if the new code contained algorithm-level optimisations that assumed such a URL could not exist?

The benefits of a build-time plugin/linting approach are:

a) Easer to implement. No need to touch the compiler. The tools already exist.

b) No interface stability concerns, no viral attributes.

c) Most of the time, showing some kind of warning is about as good as you can do anyway. Static initialisation sounds really cool, but it binds your hands really tightly. Even security-related patches may no longer be possible, and it become almost impossible to reason about which objects may be floating around.

4 Likes

Yeah, that's roughly the solution I use today. It works, but frankly it kinda sucks because of combinatorial explosion.

4 Likes

Yes, that’s one possible implementation, but the concern is that it’s not enough to get what you want and it won’t be necessary anymore once compile-time evaluation capabilities are filled in. It buys you nothing at first, as a library author, to know that your function received a string that the compiler has evaluated to be constant because you can’t do anything with it. Once you start being able to do things with it, you’re able to wrap it in a StaticURL type and the Foundation URL struct can have an initializer that accepts that. This is a better solution than constant arguments because you can forward a StaticURL, whereas you cannot forward a constant argument without it becoming opaque.

So there will be a period during which constant arguments will be the best we have, and then it’ll largely stop being useful. There will be a small handful of places where it’s desirable (like Steve’s case) and those will mostly be in the standard library.