mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
When constructing a generic signature, any redundant explicit requirements
are dropped from the final signature.
We would assume this operation is idempotent, that is, building a new
GenericSignatureBuilder from the resulting minimized signature produces
an equivalent GenericSignatureBuilder to the original one.
Unfortunately, this is not true in the case of conformance requirements.
Namely, if a conformance requirement is made redundant by a superclass
or concrete same-type requirement, then dropping the conformance
requirement changes the canonical type computation.
For example, consider the following:
public protocol P {
associatedtype Element
}
public class C<O: P>: P {
public typealias Element = O.Element
}
public func toe<T, O, E>(_: T, _: O, _: E, _: T.Element)
where T : P, O : P, O.Element == T.Element, T : C<E> {}
In the generic signature of toe(), the superclass requirement 'T : C<E>'
implies the conformance requirement 'T : P' because C conforms to P.
However, the presence of the conformance requirement makes it so that
T.Element is the canonical representative, so previously this signature
was minimized down to:
<T : C<E>, O : P, T.Element == O.Element>
If we build the signature again from the above requirements, then we
see that T.Element is no longer the canonical representative; instead,
T.Element canonicalizes as E.Element.
For this reason, we must rebuild the signature to get the correct
canonical type computation.
I realized that this is not an artifact of incorrect design in the
current GSB; my new rewrite system formalism would produce the same
result. Rather, it is a subtle consequence of the specification of our
minimization algorithm, and therefore it must be formalized in this
manner.
We used to sort-of do this with the HadAnyRedundantRequirements hack,
but it was both overly broad (we only need to rebuild if a conformance
requirement was implied by a superclass or concrete same-type
requirement) and not sufficient (when rebuilding, we need to strip any
bound associated types from our requirements to ensure the canonical
type anchors are re-computed).
Fixes rdar://problem/65263302, rdar://problem/75010156,
rdar://problem/75171977.
18 lines
279 B
Swift
18 lines
279 B
Swift
// RUN: %target-swift-frontend -verify -emit-ir %s
|
|
|
|
public protocol P1 {}
|
|
|
|
public protocol P2 {
|
|
associatedtype A : P1
|
|
associatedtype B : P2
|
|
func f()
|
|
}
|
|
|
|
public extension P2 where B.A == A {
|
|
func f() {}
|
|
}
|
|
|
|
public class C<B: P2>: P2 {
|
|
public typealias A = B.A
|
|
}
|