When are we allowed to dynamically cast a @_marker protocol?

as far as i understand, @_marker protocols have no ABI representation, so we cannot do this:

@_marker
protocol FooType
{
}

protocol Barable
{
}
extension Barable
{
    func inspect()
    {
        if self is any FooType
        {
            print("i am a FooType")
        }
        else
        {
            print("i am not a FooType")
        }
    }
}
markers.swift:13:17: error: marker protocol 'FooType' cannot be
                            used in a conditional cast
        if self is any FooType
                ^

but we are allowed to cast the dynamic type itself:

extension Barable
{
    func inspect()
    {
        if Self.self is any FooType.Type
        {
            print("i am a FooType")
        }
        else
        {
            print("i am not a FooType")
        }
    }
}

and somehow this works at runtime:

struct Foo<T>:FooType, Barable
{
}

let x:Foo<Int> = .init()
x.inspect()
i am a FooType

iā€™m having a hard time understanding why self does not support this kind of dynamic cast, but Self does. is this actually specified behavior, or is the compiler missing a diagnostic and i just got lucky?

1 Like