Why "error: covariant 'Self' type cannot be referenced from a stored property initializer"

struct Foo {
    let blah: String
}

class Bar {
    static let ala = "Me"
    let foo = Foo(blah: Self.ala)   // error: covariant 'Self' type cannot be referenced from a stored property initializer
    let foo2 = Foo(blah: Bar.ala)   // this is okay
}

What is "covariant 'Self' type"?

Why this error here? And change Self to Bar is fine? I always use Self instead of type name. But in a class type, this is an error, where as in a struct Self is fine.

1 Like

In a non-final class, Self is not the same as the type name because the type can be subclassed.

In Foo(blah: Self.ala), Self is covariant; in other words, if you have a subclass of Bar named Bar2, then Self here refers to Bar2. This use of covariant Self is not supported, for obvious reasons.

1 Like

I've filed https://bugs.swift.org/browse/SR-13892 to improve the diagnostic.

1 Like

I was guessing it must be due to class can do inheritance but did not see why it should be a problem: even if Self now is Bar2, since Bar2 inherits from Bar, so now "Self.ala" is "Bar2.ala" and ala is in the base class, so it should be reachable from Bar2? It's just simple inheritance relationship, as I understand.

Edit: I tried

final class Bar { ... }

still cannot use Self, same error.

This is a bug/previously-proposed enhancement, SR-11176.

1 Like
class Bar {
    static let ala = "Me"
    let foo: Foo
    init() {
        foo = Foo(blah: Self.ala)
    }
}

you could init foo in this way

So Self works in init, I’m even more puzzle at the original compile error. Foo initialized in hand written init or just assign in property; it's the same Self: why the compiler not accept in one place and okay in another?

Why is Self is okay in #selector()?

class WhySelfIsOkaySometime {
    static let ala = "Me"
    let me = Self.ala   // error: covariant 'Self' type cannot be referenced from a stored property initializer
    var whatwhat = #selector(Self.someFunc) // Self is fine here!

    @objc
    func someFunc() { }
}
1 Like

That’s a great question! #selector is a compiler builtin for creating Objective-C selectors, which are ultimately just strings. Since the selector produced only depends on the method signature (and not on the actual type which ultimately provides the implementation for that signature), there’s no issue when generating a selector from a dynamic Self type.

Terms of Service

Privacy Policy

Cookie Policy