Unable to call instance property from outside the module it is defined in, if a static property of the same name exists

if i have a type named A with an instance property x, and a static property also named x, and i write code like let _: Int? = self.x in an instance method on A, in the same module that A is defined, everything works as expected.

public enum A {
    public var x: Int? { nil }
}
extension A {
    static let x: Bool = true

    func f() {
        let _: Int? = self.x
    }
}

but if i move that exact same code to a different module

import A

extension A {
    static let x: Bool = true

    func f() {
        let _: Int? = self.x
    }
}

i suddenly get the error

/swift/property-test/Sources/B/A (ext).swift:7:23: error: static member 'x' cannot be used on instance of type 'A'
5 | 
6 |     func f() {
7 |         let _: Int? = self.x
  |                       `- error: static member 'x' cannot be used on instance of type 'A'
8 |     }
9 | }

/swift/property-test/Sources/B/A (ext).swift:7:28: error: cannot convert value of type 'Bool' to specified type 'Int'
5 | 
6 |     func f() {
7 |         let _: Int? = self.x
  |                            `- error: cannot convert value of type 'Bool' to specified type 'Int'
8 |     }
9 | }

the instance property A.x, as you can see, is public. so i do not understand why this restriction exists.

This is because of the "shadowing" feature which filters out properties and types from imported modules that have the same name as a declaration in the current module. (For functions, there is a further step which compares their types, so only identical overloads are subject to shadowing. But that is not the case for properties.) Perhaps it was an oversight that this is performed even when one property is static and the other is not, though.

5 Likes