Files
swift-mirror/test/Generics/rdar95075552.swift
Slava Pestov 2734f3ca05 stdlib: Add SIMDMaskScalar.SIMDMaskScalar == SIMDMaskScalar requirement to SIMDScalar
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.
2022-06-22 21:26:15 -04:00

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)
}
}