Unknown attributes should be a warning (not an error)

There are some private attributes like @inline(__always), @_specialize, @_exported etc, that are considered unstable (i. e. they may go away any time), but nonetheless are quite important in some use cases (like the CryptoSwift library, which, according to its maintainer, is really slow without all those private attributes).

At the same time, it is unclear whether those attributes will ever make it through Swift Evolution, as their use cases are too narrow to be worth a proposal. Also, there's this "I want to write cool things in Swift right now, not wait 5 years until a language feature is maybe de-underscored" factor.

Those library authors that make use of those attributes are unintentionally putting their users in danger: any time their app may stop compiling after upgrading to a new Xcode version just because some dependency used those underscored attributes, and some of them went away in that new Xcode version.

Can the core team consider making unknown attributes a warning rather than an error? In this case, if, say, @inline(__always) is removed, the libraries that make use of it won't break. In other words, can we adopt the same behavior as C++11 attributes?

on the other hand if someone writes @_dontFormatMyHardDrive and then it gets removed from the language, I would like for it to be a build error, instead of the app running and my hard drive being formatted

Your example is super artificial. I can't think of any existing built-in underscore attribute such that its removal changes the semantic meaning of a program. Will it break compilation? Yes, maybe (e. g. @_exported). But not semantics. If adding or removing it changed semantics, it would be a keyword.

(We're not looking at property wrappers, obviously.)

@_swift_native_objc_runtime_base(Foo)
class Bar { }

let x: AnyObject = Bar()
let selector = Selector("doTheThing")
if x.responds(to: selector) {
    x.performSelector(onMainThread: selector, with: nil, waitUntilDone: true)
}

It will change the semantics of the code if Foo implements method "doTheThing"

Oh.

Well, I was wrong then.

2 Likes

But I do agree, my example is super artificial and almost always the result would be either code not compiling at all, or still working well

1 Like

When it comes to performance, @inline(__always) and @_specialize should not be needed anymore. @inlinable should cover any performance‐related uses of either of them. And if it doesn’t, that fact should be reported as a bug.

If @inline(__always) is being used for security reasons—which it isn’t reliable for in the first place—then you really do not want it to go ignored and open a security hole.

If @_exported is being used, demoting it from error to warning won’t solve anything, since with the re‐export missing, you’ll hit a sudden wall of undefined symbol errors.

Their use cases are not too narrow. As noted above, @inline(__always), @_specialize and their relatives already led to the fully supported @inlinable. And the problem space of @_exported is undergoing active development to transform it into a more robust model that can be declared stable:


They are doing so intentionally. Those attributes are not in any official documentation. If a developer even knows about them, they either discovered them as experimental features buried in the compiler’s source code, or received them as a suggestion from someone else who had. When these attributes pop up in conversation around here, it is always with a disclaimer that they are not finished yet and are a use‐at‐your‐own‐risk sort of thing. And for the most part that is true of the rest of the web as well.

2 Likes