mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
If we have a conformance requirement T : P, and a concrete type requirement T == G<...>, and G _conditionally_ conforms to P, we would infer the conditional requirements of G needed to satisfy the conformance. However, if the conformance requirement T : P was not explicit, this would mean in practice that we would need to infer an infinite number of conditional requirements, because there might be an infinite number of types T for which T : P. Previously we would infer these up to some limit, based on how many levels of nested types the GSB had expanded. Since this is untenable, let's instead change the rules so that conditional requirement inference is only performed when the concretizing requirement was explicit.
53 lines
1.8 KiB
Swift
53 lines
1.8 KiB
Swift
// RUN: %target-typecheck-verify-swift
|
|
// RUN: not %target-swift-frontend -typecheck -debug-generic-signatures %s 2>&1 | %FileCheck %s
|
|
|
|
|
|
// Valid example
|
|
struct EquatableBox<T : Equatable> {
|
|
// CHECK: Generic signature: <T, U where T == Array<U>, U : Equatable>
|
|
func withArray<U>(_: U) where T == Array<U> {}
|
|
}
|
|
|
|
|
|
// A very elaborate invalid example (see comment in mergeP1AndP2())
|
|
struct G<T> {}
|
|
|
|
protocol P {}
|
|
extension G : P where T : P {}
|
|
|
|
protocol P1 {
|
|
associatedtype T
|
|
associatedtype U where U == G<T>
|
|
associatedtype R : P1
|
|
}
|
|
|
|
protocol P2 {
|
|
associatedtype U : P
|
|
associatedtype R : P2
|
|
}
|
|
|
|
func takesP<T : P>(_: T.Type) {}
|
|
// expected-note@-1 {{where 'T' = 'T.T'}}
|
|
// expected-note@-2 {{where 'T' = 'T.R.T'}}
|
|
// expected-note@-3 {{where 'T' = 'T.R.R.T'}}
|
|
// expected-note@-4 {{where 'T' = 'T.R.R.R.T'}}
|
|
|
|
// CHECK: Generic signature: <T where T : P1, T : P2>
|
|
func mergeP1AndP2<T : P1 & P2>(_: T) {
|
|
// P1 implies that T.(R)*.U == G<T.(R)*.T>, and P2 implies that T.(R)*.U : P.
|
|
//
|
|
// These together would seem to imply that G<T.(R)*.T> : P, therefore
|
|
// the conditional conformance G : P should imply that T.(R)*.T : P.
|
|
//
|
|
// However, this would require us to infer an infinite number of
|
|
// conformance requirements in the signature of mergeP1AndP2() of the
|
|
// form T.(R)*.T : P.
|
|
//
|
|
// Since we're unable to represent that, make sure that a) we don't crash,
|
|
// b) we reject the conformance T.(R)*.T : P.
|
|
|
|
takesP(T.T.self) // expected-error {{global function 'takesP' requires that 'T.T' conform to 'P'}}
|
|
takesP(T.R.T.self) // expected-error {{global function 'takesP' requires that 'T.R.T' conform to 'P'}}
|
|
takesP(T.R.R.T.self) // expected-error {{global function 'takesP' requires that 'T.R.R.T' conform to 'P'}}
|
|
takesP(T.R.R.R.T.self) // expected-error {{global function 'takesP' requires that 'T.R.R.R.T' conform to 'P'}}
|
|
} |