Skip to content

Commit ac5300c

Browse files
committed
RequirementMachine: Support DependentMemberTypes in remapConcreteSubstitutionSchema()
When concretizing nested types, we need to be able to normalize a concrete type containing DependentMemberTypes to our 'concrete substitution schema' form where all type parameter structural sub-components are actually just generic parameters.
1 parent 5d61083 commit ac5300c

File tree

2 files changed

+63
-22
lines changed

2 files changed

+63
-22
lines changed

lib/AST/RequirementMachine/EquivalenceClassMap.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -204,23 +204,30 @@ static MutableTerm getRelativeTermForType(CanType typeWitness,
204204
return result;
205205
}
206206

207-
/// Given a concrete type that is a structural sub-component of a concrete
208-
/// type produced by RewriteSystemBuilder::getConcreteSubstitutionSchema(),
209-
/// collect the subset of referenced substitutions and renumber the generic
210-
/// parameters in the type.
207+
/// This method takes a concrete type that was derived from a concrete type
208+
/// produced by RewriteSystemBuilder::getConcreteSubstitutionSchema(),
209+
/// either by extracting a structural sub-component or performing a (Swift AST)
210+
/// substitution using subst(). It returns a new concrete substitution schema
211+
/// and a new list of substitution terms.
211212
///
212213
/// For example, suppose we start with the concrete type
213214
///
214215
/// Dictionary<τ_0_0, Array<τ_0_1>> with substitutions {X.Y, Z}
215216
///
216217
/// We can extract out the structural sub-component Array<τ_0_1>. If we wish
217-
/// to turn this into a new concrete substitution schema, we call this method
218-
/// with Array<τ_0_1> and the original substitutions {X.Y, Z}. This will
219-
/// return the type Array<τ_0_0> and the substitutions {Z}.
220-
CanType
218+
/// to build a new concrete substitution schema, we call this method with
219+
/// Array<τ_0_1> and the original substitutions {X.Y, Z}. This will produce
220+
/// the new schema Array<τ_0_0> with substitutions {Z}.
221+
///
222+
/// As another example, consider we start with the schema Bar<τ_0_0> with
223+
/// original substitutions {X.Y}, and perform a Swift AST subst() to get
224+
/// Foo<τ_0_0.A.B>. We can then call this method with Foo<τ_0_0.A.B> and
225+
/// the original substitutions {X.Y} to produce the new schema Foo<τ_0_0>
226+
/// with substitutions {X.Y.A.B}.
227+
static CanType
221228
remapConcreteSubstitutionSchema(CanType concreteType,
222229
ArrayRef<Term> substitutions,
223-
ASTContext &ctx,
230+
RewriteContext &ctx,
224231
SmallVectorImpl<Term> &result) {
225232
assert(!concreteType->isTypeParameter() && "Must have a concrete type here");
226233

@@ -229,16 +236,16 @@ remapConcreteSubstitutionSchema(CanType concreteType,
229236

230237
return CanType(concreteType.transformRec(
231238
[&](Type t) -> Optional<Type> {
232-
assert(!t->is<DependentMemberType>());
233-
234-
if (!t->is<GenericTypeParamType>())
239+
if (!t->isTypeParameter())
235240
return None;
236241

237-
unsigned oldIndex = getGenericParamIndex(t);
242+
auto term = getRelativeTermForType(CanType(t), substitutions, ctx);
243+
238244
unsigned newIndex = result.size();
239-
result.push_back(substitutions[oldIndex]);
245+
result.push_back(Term::get(term, ctx));
240246

241-
return CanGenericTypeParamType::get(/*depth=*/0, newIndex, ctx);
247+
return CanGenericTypeParamType::get(/*depth=*/0, newIndex,
248+
ctx.getASTContext());
242249
}));
243250
}
244251

@@ -326,8 +333,7 @@ static Atom unifyConcreteTypes(
326333
SmallVector<Term, 3> result;
327334
auto concreteType = remapConcreteSubstitutionSchema(CanType(secondType),
328335
rhsSubstitutions,
329-
ctx.getASTContext(),
330-
result);
336+
ctx, result);
331337

332338
MutableTerm constraintTerm(subjectTerm);
333339
constraintTerm.add(Atom::forConcreteType(concreteType, result, ctx));
@@ -350,8 +356,7 @@ static Atom unifyConcreteTypes(
350356
SmallVector<Term, 3> result;
351357
auto concreteType = remapConcreteSubstitutionSchema(CanType(firstType),
352358
lhsSubstitutions,
353-
ctx.getASTContext(),
354-
result);
359+
ctx, result);
355360

356361
MutableTerm constraintTerm(subjectTerm);
357362
constraintTerm.add(Atom::forConcreteType(concreteType, result, ctx));
@@ -676,12 +681,10 @@ void EquivalenceClassMap::concretizeNestedTypesFromConcreteParent(
676681
// The type witness is a concrete type.
677682
constraintType = subjectType;
678683

679-
// FIXME: Handle dependent member types here
680684
SmallVector<Term, 3> result;
681685
auto typeWitnessSchema =
682686
remapConcreteSubstitutionSchema(typeWitness, substitutions,
683-
Context.getASTContext(),
684-
result);
687+
Context, result);
685688

686689
// Add a rule T.[P:A].[concrete: Foo.A] => T.[P:A].
687690
constraintType.add(
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %target-typecheck-verify-swift -enable-requirement-machine -debug-requirement-machine 2>&1 | %FileCheck %s
2+
3+
protocol P1 {
4+
associatedtype T : P1
5+
}
6+
7+
protocol P2 {
8+
associatedtype T
9+
}
10+
11+
struct X<A : P1> : P2 {
12+
typealias T = X<A.T>
13+
}
14+
15+
protocol P2a {
16+
associatedtype T : P2
17+
}
18+
19+
protocol P3a {
20+
associatedtype T where T == X<U>
21+
associatedtype U : P1
22+
}
23+
24+
struct G<T : P2a & P3a> {}
25+
26+
// X.T has a DependentMemberType in it; make sure that we build the
27+
// correct substitution schema.
28+
29+
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P2a, τ_0_0 : P3a>
30+
// CHECK-LABEL: Rewrite system: {
31+
// CHECK: - τ_0_0.[P2a&P3a:T].[concrete: X<τ_0_0> with <τ_0_0.[P3a:U]>] => τ_0_0.[P2a&P3a:T]
32+
// CHECK: - τ_0_0.[P2a&P3a:T].[P2:T].[concrete: X<τ_0_0> with <τ_0_0.[P3a:U].[P1:T]>] => τ_0_0.[P2a&P3a:T].[P2:T]
33+
// CHECK: }
34+
// CHECK-LABEL: Equivalence class map: {
35+
// CHECK: τ_0_0.[P2a&P3a:T] => { conforms_to: [P2] concrete_type: [concrete: X<τ_0_0> with <τ_0_0.[P3a:U]>] }
36+
// CHECK: τ_0_0.[P2a&P3a:T].[P2:T] => { concrete_type: [concrete: X<τ_0_0> with <τ_0_0.[P3a:U].[P1:T]>] }
37+
// CHECK: }
38+
// CHECK: }

0 commit comments

Comments
 (0)