I have several examples of this that are likely caused by the same (or very similar) problems (using the 7/17 nightly):
protocol P1 {
associatedtype B: P2
}
protocol P2: P1 where B == Self {
// isn't this redunant with the B == Self constraint?
// if it is removed the code won't compile but it seems like it should be unnecessary
associatedtype B = Self
}
protocol P3 {
associatedtype T: P1
associatedtype U
var s: S<T, U> { get }
}
struct S<T: P1, U>: P1, P3 {
typealias B = T.B
var s: S<T, U> { return self }
func f<F: P3>(_ type: F.Type) -> F where F.T == T, F.U == U {
// the body doesn't matter
fatalError()
}
}
struct AP1: P1 { typealias B = AP2 }
struct AP2: P2 { typealias B = AP2 }
struct AP3: P3 {
typealias T = AP1
typealias U = String
var s: S<T, U> { return S() }
}
extension P3 where T == T.B {
func foo() -> String { return "foo" }
}
let ap3 = AP3()
print(ap3.foo()) // prints foo
print(AP3.T.self) // prints AP1
print(AP3.T.B.self) // prints AP2
In the above example, clearly `AP3.T != AP3.T.B` but the extension on `P3` that declares `foo` clearly requires them to be equal. `foo` should not be available on `AP3`. The same incorrect behavior is exhibited when the constraint is `T: P2` instead of `T == T.B`.
protocol P1 {
associatedtype B: P2
}
protocol P2: P1 where B == Self {
// isn't this redunant with the B == Self constraint?
// if it is removed the code won't compile but it seems like it should be unnecessary
associatedtype B = Self
}
protocol P3 {
associatedtype T: P1
associatedtype U
var s: S<T, U> { get }
}
protocol P4: P3 where T: P3, T.B == T.T.B {
typealias T2 = T.T
typealias U2 = T.U
}
struct S<T: P1, U>: P1, P3 {
typealias B = T.B
var s: S<T, U> { return self }
func f<F: P3>(_ type: F.Type) -> F where F.T == T, F.U == U {
// the body doesn't matter
fatalError()
}
}
struct AP1: P1 { typealias B = AP2 }
struct AP2: P2 { typealias B = AP2 }
struct AP4: P4 {
typealias T = S<S<AP2, String>, String>
typealias U = String
var s: S<T, U> { return S() }
}
extension P4 where T: P3, T2 == T.B {
func foo() -> String { return "foo" }
}
let ap4 = AP4()
print(ap4.foo()) // prints foo
print(AP4.T.self) // prints S<S<AP2, String>, String>
print(AP4.T.T.self) // prints S<AP2, String>
print(AP4.T2.self) // prints S<AP2, String>
print(AP4.T.B.self) // prints AP2
In the above example, clearly `AP4.T.T ![](= AP4.T.BandAP4.T2 )= AP4.T.B` but the extension on `P4` that declares `foo` clearly requires them to be equal. `foo` should not be available on `AP4`. The same incorrect behavior is exhibited when the constraint uses `T.T == T.B` or `T.T: P2` instead of `T2 == T.B`. Interestingly however, placing the extension on `P3` instead of `P4` produces the correct behavior of `foo` not being available on `AP4` and thus a no member error for the expression `ap4.foo()`.
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: c94304280ea88de749652ea896c67cf7Issue Description:
I have several examples of this that are likely caused by the same (or very similar) problems (using the 7/17 nightly):
In the above example, clearly `AP3.T != AP3.T.B` but the extension on `P3` that declares `foo` clearly requires them to be equal. `foo` should not be available on `AP3`. The same incorrect behavior is exhibited when the constraint is `T: P2` instead of `T == T.B`.
In the above example, clearly `AP4.T.T ![](= AP4.T.B
and
AP4.T2 )= AP4.T.B` but the extension on `P4` that declares `foo` clearly requires them to be equal. `foo` should not be available on `AP4`. The same incorrect behavior is exhibited when the constraint uses `T.T == T.B` or `T.T: P2` instead of `T2 == T.B`. Interestingly however, placing the extension on `P3` instead of `P4` produces the correct behavior of `foo` not being available on `AP4` and thus a no member error for the expression `ap4.foo()`.