mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
In theory this is a source break if someone had a weird custom
conforming type, but I suspect in practice conformances to
this protocol are never defined.
The reason we want this requirement is that often you will see
code like the following:
protocol Point {
associatedtype Scalar: SIMDScalar
associatedtype Vector: SIMD where Vector.Scalar == Scalar
}
extension Point where Vector == SIMD2<Scalar> { ... }
When `Vector` is equated with `SIMD2<Scalar>`, we get an infinite
sequence of implied same-type requirements:
Vector.MaskStorage == SIMD2<Scalar.MaskScalar>
Vector.MaskStorage.MaskStorage == SIMD2<Scalar.MaskScalar.MaskScalar>
...
The protocol fails to typecheck with an error because the requirement
machine cannot build a rewrite system.
If SIMDScalar requires that MaskScalar.MaskScalar == MaskScalar, then
we instead get
Vector.MaskStorage == SIMD2<Scalar.MaskScalar>
Vector.MaskStorage.MaskStorage == SIMD2<Scalar.MaskScalar>
Vector.MaskStorage.MaskStorage == Vector.MaskStorage
...
Which ties off the recursion.
In theory, a more advanced implementation could represent this kind of
infinite recursion in 'closed form', but we don't have that yet, and I
believe adding this same-type requirement makes sense anyway.
Fixes rdar://problem/95075552.
33 lines
1.3 KiB
Swift
33 lines
1.3 KiB
Swift
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
|
|
|
|
// CHECK-LABEL: .Tree@
|
|
// CHECK-NEXT: Requirement signature: <Self where Self.[Tree]Distance : FloatingPoint, Self.[Tree]Distance : SIMDScalar, Self.[Tree]Distance == Self.[Tree]Point.[SIMDStorage]Scalar, Self.[Tree]Point : SIMD>
|
|
protocol Tree {
|
|
associatedtype Distance: FloatingPoint & SIMDScalar
|
|
associatedtype Point: SIMD where Point.Scalar == Distance
|
|
}
|
|
|
|
// CHECK-LABEL: .QuadTree@
|
|
// CHECK-NEXT: Requirement signature: <Self where Self : Tree, Self.[Tree]Point == SIMD2<Self.[Tree]Distance>>
|
|
protocol QuadTree : Tree where Point == SIMD2<Distance> {}
|
|
|
|
// CHECK-LABEL: .OctTree@
|
|
// CHECK-NEXT: Requirement signature: <Self where Self : Tree, Self.[Tree]Point == SIMD3<Self.[Tree]Distance>>
|
|
protocol OctTree : Tree where Point == SIMD3<Distance> {}
|
|
|
|
func sameType<T>(_: T.Type, _: T.Type) {}
|
|
|
|
extension QuadTree {
|
|
func foo() {
|
|
sameType(Point.MaskStorage.self, SIMD2<Distance.SIMDMaskScalar>.self)
|
|
sameType(Point.MaskStorage.MaskStorage.self, SIMD2<Distance.SIMDMaskScalar>.self)
|
|
}
|
|
}
|
|
|
|
extension OctTree {
|
|
func foo() {
|
|
sameType(Point.MaskStorage.self, SIMD3<Distance.SIMDMaskScalar>.self)
|
|
sameType(Point.MaskStorage.MaskStorage.self, SIMD3<Distance.SIMDMaskScalar>.self)
|
|
}
|
|
}
|