Underscore attributes: @_marker


Greetings, traveler!

You may have heard about marker protocols. They used to mark entities without providing any requirements. But did you know Swift has a specific underscore attribute for such protocols? I am talking about the @_marker attribute.

Note

There is a warning in Swift documentation about underscore attributes:

Usage of these attributes outside of the Swift monorepo is STRONGLY DISCOURAGED.

The semantics of these attributes are subject to change and most likely need to go through the Swift evolution process before being stabilized.

All the stable attributes are described here.

The only example in Swift we can find is the Sendable protocol, which basically does only one thing — separate the wheat from the chaff.

Note

By the way, if you want to read more about Sendable and @Sendable closures, you can do so here.

So, we can do the same thing. Checkout this example:

@_marker protocol ThreadSafeProtocol {}

class Object: ThreadSafeProtocol {}

func doSomething(with object: ThreadSafeProtocol) {
    DispatchQueue.global().async {
        // do something
    }
    
    DispatchQueue.global().async {
        // do something
    }
}

let object = Object()
doSomething(with: object)

But this is a really only marker protocol. So, you can’t add any requirements.

@_marker protocol ThreadSafeProtocol {
    var isTrue: Bool { get set } // ❌ Error
}

❌ Marker protocol ‘ThreadSafeProtocol’ cannot have any requirements

Also, you can’t use casting with such protocols. That means you can’t do something like that:

@_marker protocol MarkerProtocol {}

class A: UIView {}

class B: UIView {}

extension A: MarkerProtocol {}

let array = [A(), B()]
array.filter { ($0 as? MarkerProtocol) != nil } // ❌ Error

❌ Marker protocol ‘MarkerProtocol’ cannot be used in a conditional cast

Conclusion

There isn’t a significant chance of encountering a situation where this attribute will be a lifesaver. Moreover, it is not recommended to use it before becoming stable.