Why are some Swift annotations starting with uppercase letters, some starting with lowercase letters, and some still underlined?

Why are some Swift annotations starting with uppercase letters, some starting with lowercase letters, and some still underlined, isn't that too messy?


The only official one I know with underscores is @warn_unqualified_access. The ones that start with an underscore are either experimental or otherwise for internal use only, and not meant for public consumption (yet).

Most of the ones starting with capital letters are property wrappers or result builders, with a few exceptions (e.g. @IBAction) that mostly relate to Objective-C frameworks. The only one which is an actual attribute and not related to Objective-C is @Sendable, which is capitalized that way to match the protocol Sendable.


I tried to provoke some discussion around this here:

There seems to be a lot of focus in documentation around naming of methods, protocols, arguments etc... but attributes are the wild west - and with each subsequent Swift release we're overloading the @ symbol with even more functionality.


The warn_unqualified_access and requires_stored_property_inits attributes weren't meant to be public, but removing them now would be source-breaking. We should ignore their names when looking at attribute naming conventions.

See also the past discussion here: Use lowerCamelCase for @warn_unqualified_access attribute?


It is pretty consistent. Capitalized annotations are for things implemented using types such as global actors, property wrappers, result builders, or even protocols in the case of @Sendable.

1 Like

It is no different than non-@ stuff. Just think of @ is more of the meta-level of the language. Classes, Enums, Structs, etc. are also all in the same namespace. Basically, @ with an uppercase letter are 1:1 with types, so there can be no collisions. Everything else is a lower case letter.

1 Like

Yeah totally understand - my issue is that it's getting increasingly difficult to disambiguate macros, result builders, property wrappers, attributes etc in a glanceable way.

I feel like this is becoming ever-more convoluted for newcomers to the language.

Although Swift programmers are used to seeing argument labels everywhere, most programmers from other languages are not used to this and need to look at declarations or documentation to see what something is. In Swift you mainly just need to do that with types. For instance you don't know if a type is a Struct, Class, Actor, or Protocol without looking it up. It is no different for attributes. Fortunately this is super easy. You just click on the attribute in any editor with a Swift Language Server and you instantly see what it is.

It is true that Swift is getting a lot of new features compared to other languages so there is more to learn overall. Most beginners can ignore most of it or learn as they need. This is inevitable for Swift's goals as a system-level language. You just need a lot of features for that.

Although Swift is better for high-level code than any system-level language I've seen before (much better then Rust in this way), but possibly there is room for a Swift-like extension language that transpiles to Swift. Most developers are used to a high level extension language (JavaScript, Java, Kotlin, Python, Dart, C#, etc.) that interfaces with a system-level language, but usually interoperability is a real pain. I've toyed with such a language (closer to a dialect of JavaScript with bi-directional compatibility, but built on top of swift-syntax and adds a Swift-like type system) that transpiles to either JavaScript or plain Swift (interop free), but it is a long way from release.

I would also add that I'm not sure exactly what information you could glean from "this is a property wrapper" or "this is a macro" independent from knowing the precise semantics of the type itself, which of course you'd need to jump into the docs to figure out anyway. And if the meaning of the attribute is sufficiently clear just from the use site, why does it matter whether it's implemented as a macro or a property wrapper?