Skip to content

Commit 378231c

Browse files
committed
RequirementMachine: A better trick to tie off type witness recursion
This will replace the 'concrete type in domain' hack. Instead of finding some other type parameter with the same concrete type and a compatible starting symbol, this finds a prefix of the original term. This allows the induced same-type requirement to be described with a rewrite path.
1 parent a3c230e commit 378231c

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,39 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
945945
return result;
946946
}
947947

948+
// If the type witness is completely concrete, check if one of our prefix
949+
// types has the same concrete type, and if so, introduce a same-type
950+
// requirement between the subject type and the prefix.
951+
if (!typeWitness->hasTypeParameter()) {
952+
auto begin = key.begin();
953+
auto end = key.end();
954+
955+
while (begin != end) {
956+
MutableTerm prefix(begin, end);
957+
if (auto *props = lookUpProperties(prefix)) {
958+
if (props->isConcreteType() &&
959+
props->getConcreteType() == typeWitness) {
960+
auto result = props->getKey();
961+
962+
RewriteSystem::TypeWitness witness(Term::get(subjectType, Context),
963+
result);
964+
unsigned witnessID = System.recordTypeWitness(witness);
965+
path.add(RewriteStep::forAbstractTypeWitness(
966+
witnessID, /*inverse=*/false));
967+
968+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
969+
llvm::dbgs() << "^^ Type witness can re-use property bag of "
970+
<< result << "\n";
971+
}
972+
973+
return MutableTerm(result);
974+
}
975+
}
976+
977+
--end;
978+
}
979+
}
980+
948981
// Otherwise the type witness is concrete, but may contain type
949982
// parameters in structural position.
950983

test/Generics/unify_nested_types_4.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,28 @@ struct G<T : P1 & P2> {}
3737
// we solve this by merging the repeated types with T.A or T.B:
3838
//
3939
// T.A.A => T.A
40-
// T.A.B => T.B
4140
// T.B.A => T.B
42-
// T.B.B => T.A
4341
// ...
4442

4543
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
4644
// CHECK-LABEL: Rewrite system: {
45+
// CHECK: - τ_0_0.[P1&P2:A].[concrete: S1 : P1] => τ_0_0.[P1&P2:A]
4746
// CHECK: - τ_0_0.[P1&P2:A].[P1:A] => τ_0_0.[P1&P2:A]
48-
// CHECK: - τ_0_0.[P1&P2:A].[P1:B] => τ_0_0.[P1&P2:B]
47+
// CHECK: - τ_0_0.[P1&P2:A].[P1:B].[concrete: S2] => τ_0_0.[P1&P2:A].[P1:B]
48+
// CHECK: - τ_0_0.[P1&P2:B].[concrete: S2 : P1] => τ_0_0.[P1&P2:B]
4949
// CHECK: - τ_0_0.[P1&P2:B].[P1:A] => τ_0_0.[P1&P2:B]
50-
// CHECK: - τ_0_0.[P1&P2:B].[P1:B] => τ_0_0.[P1&P2:A]
50+
// CHECK: - τ_0_0.[P1&P2:B].[P1:B].[concrete: S1] => τ_0_0.[P1&P2:B].[P1:B]
51+
// CHECK: - τ_0_0.[P1&P2:A].[P1:B].[concrete: S2 : P1] => τ_0_0.[P1&P2:A].[P1:B]
52+
// CHECK: - τ_0_0.[P1&P2:A].[P1:B].[P1:A] => τ_0_0.[P1&P2:A].[P1:B]
53+
// CHECK: - τ_0_0.[P1&P2:A].[P1:B].[P1:B] => τ_0_0.[P1&P2:A]
54+
// CHECK: - τ_0_0.[P1&P2:B].[P1:B].[concrete: S1 : P1] => τ_0_0.[P1&P2:B].[P1:B]
55+
// CHECK: - τ_0_0.[P1&P2:B].[P1:B].[P1:A] => τ_0_0.[P1&P2:B].[P1:B]
56+
// CHECK: - τ_0_0.[P1&P2:B].[P1:B].[P1:B] => τ_0_0.[P1&P2:B]
5157
// CHECK: }
5258
// CHECK-LABEL: Property map: {
5359
// CHECK: τ_0_0.[P1&P2:A] => { conforms_to: [P1] concrete_type: [concrete: S1] }
5460
// CHECK: τ_0_0.[P1&P2:B] => { conforms_to: [P1] concrete_type: [concrete: S2] }
61+
// CHECK: τ_0_0.[P1&P2:A].[P1:B] => { conforms_to: [P1] concrete_type: [concrete: S2] }
62+
// CHECK: τ_0_0.[P1&P2:B].[P1:B] => { conforms_to: [P1] concrete_type: [concrete: S1] }
5563
// CHECK: }
5664
// CHECK: }

0 commit comments

Comments
 (0)