Skip to content

Commit 56fb3cc

Browse files
committed
RequirementMachine: Refactor nested type concretization a bit
1 parent d25b0db commit 56fb3cc

File tree

2 files changed

+64
-49
lines changed

2 files changed

+64
-49
lines changed

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ class PropertyMap {
221221

222222
void concretizeTypeWitnessInConformance(
223223
Term key, RequirementKind requirementKind,
224-
CanType concreteType, ArrayRef<Term> substitutions,
225-
const ProtocolDecl *proto, ProtocolConformance *concrete,
224+
Symbol concreteConformanceSymbol,
225+
ProtocolConformance *concrete,
226226
AssociatedTypeDecl *assocType,
227227
SmallVectorImpl<InducedRule> &inducedRules) const;
228228

@@ -233,8 +233,9 @@ class PropertyMap {
233233
void recordConcreteConformanceRule(
234234
unsigned concreteRuleID,
235235
unsigned conformanceRuleID,
236-
const ProtocolDecl *proto,
237-
SmallVectorImpl<InducedRule> &inducedRules);
236+
RequirementKind requirementKind,
237+
Symbol concreteConformanceSymbol,
238+
SmallVectorImpl<InducedRule> &inducedRules) const;
238239

239240
void verify() const;
240241
};

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -541,32 +541,47 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
541541

542542
auto *concrete = conformance.getConcrete();
543543

544-
recordConcreteConformanceRule(concreteRuleID, conformanceRuleID, proto,
545-
inducedRules);
546-
547544
// Record the conformance for use by
548545
// PropertyBag::getConformsToExcludingSuperclassConformances().
549546
conformances.push_back(concrete);
550547

548+
// All subsequent logic just records new rewrite rules, and can be
549+
// skipped if we've already processed this pair of rules.
550+
if (!ConcreteConformanceRules.insert(
551+
std::make_pair(concreteRuleID, conformanceRuleID)).second) {
552+
// We've already processed this pair of rules.
553+
continue;
554+
}
555+
556+
auto concreteConformanceSymbol = Symbol::forConcreteConformance(
557+
concreteType, substitutions, proto, Context);
558+
559+
recordConcreteConformanceRule(concreteRuleID, conformanceRuleID,
560+
requirementKind, concreteConformanceSymbol,
561+
inducedRules);
562+
551563
auto assocTypes = proto->getAssociatedTypeMembers();
552564
if (assocTypes.empty())
553565
continue;
554566

555567
for (auto *assocType : assocTypes) {
556568
concretizeTypeWitnessInConformance(key, requirementKind,
557-
concreteType, substitutions,
558-
proto, concrete, assocType,
569+
concreteConformanceSymbol,
570+
concrete, assocType,
559571
inducedRules);
560572
}
561573
}
562574
}
563575

564576
void PropertyMap::concretizeTypeWitnessInConformance(
565577
Term key, RequirementKind requirementKind,
566-
CanType concreteType, ArrayRef<Term> substitutions,
567-
const ProtocolDecl *proto, ProtocolConformance *concrete,
578+
Symbol concreteConformanceSymbol,
579+
ProtocolConformance *concrete,
568580
AssociatedTypeDecl *assocType,
569581
SmallVectorImpl<InducedRule> &inducedRules) const {
582+
auto concreteType = concreteConformanceSymbol.getConcreteType();
583+
auto substitutions = concreteConformanceSymbol.getSubstitutions();
584+
auto *proto = concreteConformanceSymbol.getProtocol();
570585

571586
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
572587
llvm::dbgs() << "^^ " << "Looking up type witness for "
@@ -591,7 +606,9 @@ void PropertyMap::concretizeTypeWitnessInConformance(
591606
<< " of " << concreteType << " is " << typeWitness << "\n";
592607
}
593608

609+
// Build the term T.[concrete: C : P].[P:X].
594610
MutableTerm subjectType(key);
611+
subjectType.add(concreteConformanceSymbol);
595612
subjectType.add(Symbol::forAssociatedType(proto, assocType->getName(),
596613
Context));
597614

@@ -682,19 +699,26 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
682699
// The type witness is a type parameter of the form τ_0_n.X.Y...Z,
683700
// where 'n' is an index into the substitution array.
684701
//
685-
// Add a rule T => S.X.Y...Z, where S is the nth substitution term.
702+
// Add a rule:
703+
//
704+
// T.[concrete: C : P].[P:X] => S[n].X.Y...Z
705+
//
706+
// Where S[n] is the nth substitution term.
686707
return Context.getRelativeTermForType(typeWitness, substitutions);
687708
}
688709

689710
// The type witness is a concrete type.
711+
//
712+
// Add a rule:
713+
//
714+
// T.[concrete: C : P].[P:X].[concrete: Foo.A] => T.[concrete: C : P].[P:A].
690715
MutableTerm constraintType = subjectType;
691716

692717
SmallVector<Term, 3> result;
693718
auto typeWitnessSchema =
694719
remapConcreteSubstitutionSchema(typeWitness, substitutions,
695720
Context, result);
696721

697-
// Add a rule T.[P:A].[concrete: Foo.A] => T.[P:A].
698722
constraintType.add(
699723
Symbol::forConcreteType(
700724
typeWitnessSchema, result, Context));
@@ -705,24 +729,28 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
705729
void PropertyMap::recordConcreteConformanceRule(
706730
unsigned concreteRuleID,
707731
unsigned conformanceRuleID,
708-
const ProtocolDecl *proto,
709-
SmallVectorImpl<InducedRule> &inducedRules) {
710-
if (!ConcreteConformanceRules.insert(
711-
std::make_pair(concreteRuleID, conformanceRuleID)).second) {
712-
// We've already emitted this rule.
713-
return;
714-
}
715-
732+
RequirementKind requirementKind,
733+
Symbol concreteConformanceSymbol,
734+
SmallVectorImpl<InducedRule> &inducedRules) const {
716735
const auto &concreteRule = System.getRule(concreteRuleID);
717736
const auto &conformanceRule = System.getRule(conformanceRuleID);
718737

719-
auto conformanceSymbol = *conformanceRule.isPropertyRule();
720-
assert(conformanceSymbol.getKind() == Symbol::Kind::Protocol);
721-
assert(conformanceSymbol.getProtocol() == proto);
722-
723-
auto concreteSymbol = *concreteRule.isPropertyRule();
724-
assert(concreteSymbol.getKind() == Symbol::Kind::ConcreteType ||
725-
concreteSymbol.getKind() == Symbol::Kind::Superclass);
738+
#ifndef NDEBUG
739+
{
740+
auto conformanceSymbol = *conformanceRule.isPropertyRule();
741+
assert(conformanceSymbol.getKind() == Symbol::Kind::Protocol);
742+
assert(conformanceSymbol.getProtocol() ==
743+
concreteConformanceSymbol.getProtocol());
744+
745+
auto concreteSymbol = *concreteRule.isPropertyRule();
746+
if (concreteSymbol.getKind() == Symbol::Kind::Superclass)
747+
assert(requirementKind == RequirementKind::Superclass);
748+
else {
749+
assert(concreteSymbol.getKind() == Symbol::Kind::ConcreteType);
750+
assert(requirementKind == RequirementKind::SameType);
751+
}
752+
}
753+
#endif
726754

727755
RewritePath path;
728756

@@ -752,32 +780,18 @@ void PropertyMap::recordConcreteConformanceRule(
752780
// than T.
753781
unsigned adjustment = rhs.size() - concreteRule.getRHS().size();
754782
if (adjustment > 0 &&
755-
!concreteSymbol.getSubstitutions().empty()) {
783+
!concreteConformanceSymbol.getSubstitutions().empty()) {
756784
path.add(RewriteStep::forAdjustment(adjustment, /*endOffset=*/1,
757785
/*inverse=*/false));
758-
759-
concreteSymbol = concreteSymbol.prependPrefixToConcreteSubstitutions(
760-
MutableTerm(rhs.begin(), rhs.begin() + adjustment),
761-
Context);
762786
}
763787

764788
// Now, transform T''.[concrete: C].[P] into T''.[concrete: C : P].
765-
Symbol concreteConformanceSymbol = [&]() {
766-
if (concreteSymbol.getKind() == Symbol::Kind::ConcreteType) {
767-
path.add(RewriteStep::forConcreteConformance(/*inverse=*/false));
768-
return Symbol::forConcreteConformance(
769-
concreteSymbol.getConcreteType(),
770-
concreteSymbol.getSubstitutions(),
771-
proto, Context);
772-
} else {
773-
assert(concreteSymbol.getKind() == Symbol::Kind::Superclass);
774-
path.add(RewriteStep::forSuperclassConformance(/*inverse=*/false));
775-
return Symbol::forConcreteConformance(
776-
concreteSymbol.getSuperclass(),
777-
concreteSymbol.getSubstitutions(),
778-
proto, Context);
779-
}
780-
}();
789+
if (requirementKind == RequirementKind::Superclass) {
790+
path.add(RewriteStep::forSuperclassConformance(/*inverse=*/false));
791+
} else {
792+
assert(requirementKind == RequirementKind::SameType);
793+
path.add(RewriteStep::forConcreteConformance(/*inverse=*/false));
794+
}
781795

782796
MutableTerm lhs(rhs);
783797
lhs.add(concreteConformanceSymbol);

0 commit comments

Comments
 (0)