mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
RequirementMachine: Concrete contraction needs to substitute the parent type of a subject type sometimes
If you have generic parameters <T, U> and requirements of the form: - T : P - T == ConcreteType<U> - T.[P]U : SomeClass - T.[P]U : SomeProto And furthermore SomeClass does not conform to SomeProto, we can't leave `T.[P]U : SomeClass` unsubstituted; we still have to replace `T` with `ConcreteType<U>` to transform the latter two requirements into: - U : SomeClass - U : SomeProto "Concrete contraction" is easily the hackiest part of the Requirement Machine; I need to come up with a more principled solution for the problem that it solves sooner or later. Fixes rdar://problem/94150249.
This commit is contained in:
@@ -227,8 +227,8 @@ public:
|
||||
Optional<Type> ConcreteContraction::substTypeParameterRec(
|
||||
Type type, Position position) const {
|
||||
|
||||
// If the requirement is of the form 'T == C' or 'T : C', don't
|
||||
// substitute T, since then we end up with 'C == C' or 'C : C',
|
||||
// If we have a superclass (T : C) or same-type requirement (T == C),
|
||||
// don't substitute T, since then we end up with 'C == C' or 'C : C',
|
||||
// losing the requirement.
|
||||
if (position == Position::BaseType ||
|
||||
position == Position::ConformanceRequirement) {
|
||||
@@ -399,9 +399,10 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
|
||||
!module->lookupConformance(substFirstType, proto,
|
||||
allowMissing, allowUnavailable)) {
|
||||
// Handle the case of <T where T : P, T : C> where C is a class and
|
||||
// C does not conform to P by leaving the conformance requirement
|
||||
// unsubstituted.
|
||||
return req;
|
||||
// C does not conform to P and only substitute the parent type of T
|
||||
// by pretending we have a same-type requirement here.
|
||||
substFirstType = substTypeParameter(
|
||||
firstType, Position::SameTypeRequirement);
|
||||
}
|
||||
|
||||
// Otherwise, replace the generic parameter in the conformance
|
||||
@@ -418,9 +419,11 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
|
||||
if (!substFirstType->isTypeParameter() &&
|
||||
!substFirstType->satisfiesClassConstraint() &&
|
||||
req.getLayoutConstraint()->isClass()) {
|
||||
// If the concrete type doesn't satisfy the layout constraint,
|
||||
// leave it unsubstituted so that we produce a better diagnostic.
|
||||
return req;
|
||||
// If the concrete type doesn't satisfy the layout constraint, produce
|
||||
// a better diagnostic and only substitute the parent type by pretending
|
||||
// we have a same-type requirement here.
|
||||
substFirstType = substTypeParameter(
|
||||
firstType, Position::SameTypeRequirement);
|
||||
}
|
||||
|
||||
return Requirement(req.getKind(),
|
||||
|
||||
@@ -12,14 +12,16 @@ class G<Value> : P2 {}
|
||||
|
||||
protocol P3 {}
|
||||
|
||||
class C {}
|
||||
|
||||
extension P1 where Value: P2 {
|
||||
typealias Element = Value.Value
|
||||
|
||||
// Make sure we can resolve 'Element' to 'V' on the left hand side of 'Element: P3'.
|
||||
|
||||
// CHECK-LABEL: .P1 extension.set()@
|
||||
// CHECK-NEXT: Generic signature: <Self, V where Self : P1, V : P3, Self.[P1]Value == G<V>>
|
||||
func set<V>() where Element: P3, Value == G<V> {
|
||||
// CHECK-NEXT: Generic signature: <Self, V where Self : P1, V : C, V : P3, Self.[P1]Value == G<V>>
|
||||
func set<V>() where Element: P3 & C, Value == G<V> {
|
||||
takeP3(V.self)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user