Invalid redeclaration compile error when extending generic type in more than one way

Swift does not compile the following code because B is declared twice

struct Identity<A> {
	let a: A
}

extension Identity where A == Int {
	// Invalid redeclaration of 'B'
	enum B {}
}

extension Identity where A == String {
	// Invalid redeclaration of 'B'
	enum B {}
}

However, if I change the block to

struct Identity<A> {
	let a: A
}

extension Identity where A == Int {
	enum B {}
}

// 'Identity<String>.B' requires the types 'String' and 'Int' be equivalent
Identity<String>.B

This second block should fail to compile (according to my brain). However, the first one should be fine. Is this issue a bug? Is there anyway around these issues without renaming B?

1 Like

I'm curious what the underlying limitation is here, and if we could support this in the future. After all, it's perfectly valid to write:

struct S<T> {}

extension S where T == Int {
    var x: Int { 0 }
}

extension S where T == String {
    var x: String { "" }
}

so it's not quite as simple as "members of disjoint extensions cannot share a name"...

That's what caused my initial confusion. When dealing with generic types I often have an extension like so

extension Identity<A> where A == Int {
    static var production: Int { someExpensiveComputationInt() }

    static var test: Int { 42 }
}

extension Identity<A> where A == String {
    static var production: String { someExpensiveComputationString() }

    static var test: String { "forty two" }
}

This seems like an appropriate topic to raise over in #evolution:discuss, where you may get a bit more attention from people who can definitively answer questions about the technical feasibility of this feature!

You might find some or all of these threads relevant:

Matching behavior with expectations for associated types and typealiases in constrained protocol extensions

How does associatedtype inference work

Typealias in constrained extension, should this compile?

Should this program really compile (is the where clause ignored)?

What kind of magic behavior is this?

1 Like