Skip to content

Commit d25b0db

Browse files
committed
RequirementMachine: Fold recordConcreteConformanceRules() into concretizeNestedTypesFromConcreteParent()
1 parent d07812e commit d25b0db

File tree

3 files changed

+42
-102
lines changed

3 files changed

+42
-102
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,6 @@ PropertyMap::buildPropertyMap(unsigned maxIterations,
392392
// the concrete type witnesses in the concrete type's conformance.
393393
concretizeNestedTypesFromConcreteParents(inducedRules);
394394

395-
// Finally, introduce concrete conformance rules, relating conformance rules
396-
// to concrete type and superclass rules.
397-
recordConcreteConformanceRules(inducedRules);
398-
399395
// Some of the induced rules might be trivial; only count the induced rules
400396
// where the left hand side is not already equivalent to the right hand side.
401397
unsigned addedNewRules = 0;

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,14 +207,17 @@ class PropertyMap {
207207

208208
void computeConcreteTypeInDomainMap();
209209
void concretizeNestedTypesFromConcreteParents(
210-
SmallVectorImpl<InducedRule> &inducedRules) const;
210+
SmallVectorImpl<InducedRule> &inducedRules);
211211

212212
void concretizeNestedTypesFromConcreteParent(
213213
Term key, RequirementKind requirementKind,
214-
CanType concreteType, ArrayRef<Term> substitutions,
214+
unsigned concreteRuleID,
215+
CanType concreteType,
216+
ArrayRef<Term> substitutions,
217+
ArrayRef<unsigned> conformsToRules,
215218
ArrayRef<const ProtocolDecl *> conformsTo,
216219
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
217-
SmallVectorImpl<InducedRule> &inducedRules) const;
220+
SmallVectorImpl<InducedRule> &inducedRules);
218221

219222
void concretizeTypeWitnessInConformance(
220223
Term key, RequirementKind requirementKind,
@@ -227,9 +230,6 @@ class PropertyMap {
227230
Term key, CanType concreteType, CanType typeWitness,
228231
const MutableTerm &subjectType, ArrayRef<Term> substitutions) const;
229232

230-
void recordConcreteConformanceRules(
231-
SmallVectorImpl<InducedRule> &inducedRules);
232-
233233
void recordConcreteConformanceRule(
234234
unsigned concreteRuleID,
235235
unsigned conformanceRuleID,

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 36 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ void PropertyMap::computeConcreteTypeInDomainMap() {
404404
}
405405

406406
void PropertyMap::concretizeNestedTypesFromConcreteParents(
407-
SmallVectorImpl<InducedRule> &inducedRules) const {
407+
SmallVectorImpl<InducedRule> &inducedRules) {
408408
for (const auto &props : Entries) {
409409
if (props->getConformsTo().empty())
410410
continue;
@@ -426,8 +426,10 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
426426
concretizeNestedTypesFromConcreteParent(
427427
props->getKey(),
428428
RequirementKind::SameType,
429+
*props->ConcreteTypeRule,
429430
props->ConcreteType->getConcreteType(),
430431
props->ConcreteType->getSubstitutions(),
432+
props->ConformsToRules,
431433
props->ConformsTo,
432434
props->ConcreteConformances,
433435
inducedRules);
@@ -441,9 +443,11 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
441443
concretizeNestedTypesFromConcreteParent(
442444
props->getKey(),
443445
RequirementKind::Superclass,
446+
*props->SuperclassRule,
444447
props->Superclass->getSuperclass(),
445448
props->Superclass->getSubstitutions(),
446-
props->getConformsTo(),
449+
props->ConformsToRules,
450+
props->ConformsTo,
447451
props->SuperclassConformances,
448452
inducedRules);
449453
}
@@ -484,22 +488,45 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
484488
///
485489
void PropertyMap::concretizeNestedTypesFromConcreteParent(
486490
Term key, RequirementKind requirementKind,
487-
CanType concreteType, ArrayRef<Term> substitutions,
491+
unsigned concreteRuleID,
492+
CanType concreteType,
493+
ArrayRef<Term> substitutions,
494+
ArrayRef<unsigned> conformsToRules,
488495
ArrayRef<const ProtocolDecl *> conformsTo,
489496
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
490-
SmallVectorImpl<InducedRule> &inducedRules) const {
497+
SmallVectorImpl<InducedRule> &inducedRules) {
491498
assert(requirementKind == RequirementKind::SameType ||
492499
requirementKind == RequirementKind::Superclass);
500+
assert(conformsTo.size() == conformsToRules.size());
501+
502+
for (unsigned i : indices(conformsTo)) {
503+
auto *proto = conformsTo[i];
504+
unsigned conformanceRuleID = conformsToRules[i];
493505

494-
for (auto *proto : conformsTo) {
495506
// FIXME: Either remove the ModuleDecl entirely from conformance lookup,
496507
// or pass the correct one down in here.
497508
auto *module = proto->getParentModule();
498509

499510
auto conformance = module->lookupConformance(concreteType,
500511
const_cast<ProtocolDecl *>(proto));
501512
if (conformance.isInvalid()) {
502-
// FIXME: Diagnose conflict
513+
// For superclass rules, it is totally fine to have a signature like:
514+
//
515+
// protocol P {}
516+
// class C {}
517+
// <T where T : P, T : C>
518+
//
519+
// There is no relation between P and C here.
520+
//
521+
// With concrete types, a missing conformance is a conflict.
522+
if (requirementKind == RequirementKind::SameType) {
523+
// FIXME: Diagnose conflict
524+
//
525+
// FIXME: We should mark the more specific rule of the two
526+
// as conflicting.
527+
System.getRule(conformanceRuleID).markConflicting();
528+
}
529+
503530
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
504531
llvm::dbgs() << "^^ " << concreteType << " does not conform to "
505532
<< proto->getName() << "\n";
@@ -514,6 +541,9 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
514541

515542
auto *concrete = conformance.getConcrete();
516543

544+
recordConcreteConformanceRule(concreteRuleID, conformanceRuleID, proto,
545+
inducedRules);
546+
517547
// Record the conformance for use by
518548
// PropertyBag::getConformsToExcludingSuperclassConformances().
519549
conformances.push_back(concrete);
@@ -672,92 +702,6 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
672702
return constraintType;
673703
}
674704

675-
void PropertyMap::recordConcreteConformanceRules(
676-
SmallVectorImpl<InducedRule> &inducedRules) {
677-
for (const auto &props : Entries) {
678-
if (props->getConformsTo().empty())
679-
continue;
680-
681-
if (props->ConcreteType) {
682-
unsigned concreteRuleID = *props->ConcreteTypeRule;
683-
684-
// The GSB drops all conformance requirements on a type parameter equated
685-
// to a concrete type, even if the concrete type doesn't conform. That is,
686-
//
687-
// protocol P {}
688-
// <T where T : P, T == Int>
689-
//
690-
// minimizes as
691-
//
692-
// <T where T == Int>.
693-
//
694-
// We model this by marking unsatisfied conformance rules as conflicts.
695-
696-
// The conformances in ConcreteConformances should appear in the same
697-
// order as the protocols in ConformsTo.
698-
auto conformanceIter = props->ConcreteConformances.begin();
699-
700-
for (unsigned i : indices(props->ConformsTo)) {
701-
auto conformanceRuleID = props->ConformsToRules[i];
702-
if (conformanceIter == props->ConcreteConformances.end()) {
703-
// FIXME: We should mark the more specific rule of the conformance and
704-
// concrete type rules as conflicting.
705-
System.getRule(conformanceRuleID).markConflicting();
706-
continue;
707-
}
708-
709-
auto *proto = props->ConformsTo[i];
710-
if (proto != (*conformanceIter)->getProtocol()) {
711-
// FIXME: We should mark the more specific rule of the conformance and
712-
// concrete type rules as conflicting.
713-
System.getRule(conformanceRuleID).markConflicting();
714-
continue;
715-
}
716-
717-
recordConcreteConformanceRule(concreteRuleID, conformanceRuleID, proto,
718-
inducedRules);
719-
++conformanceIter;
720-
}
721-
722-
assert(conformanceIter == props->ConcreteConformances.end());
723-
}
724-
725-
if (props->Superclass) {
726-
unsigned superclassRuleID = *props->SuperclassRule;
727-
728-
// For superclass rules, we only introduce a concrete conformance if the
729-
// superclass actually conforms. Otherwise, it is totally fine to have a
730-
// signature like
731-
//
732-
// protocol P {}
733-
// class C {}
734-
// <T where T : P, T : C>
735-
//
736-
// There is no relation between P and C here.
737-
738-
// The conformances in SuperclassConformances should appear in the same
739-
// order as the protocols in ConformsTo.
740-
auto conformanceIter = props->SuperclassConformances.begin();
741-
742-
for (unsigned i : indices(props->ConformsTo)) {
743-
if (conformanceIter == props->SuperclassConformances.end())
744-
break;
745-
746-
auto *proto = props->ConformsTo[i];
747-
if (proto != (*conformanceIter)->getProtocol())
748-
continue;
749-
750-
unsigned conformanceRuleID = props->ConformsToRules[i];
751-
recordConcreteConformanceRule(superclassRuleID, conformanceRuleID, proto,
752-
inducedRules);
753-
++conformanceIter;
754-
}
755-
756-
assert(conformanceIter == props->SuperclassConformances.end());
757-
}
758-
}
759-
}
760-
761705
void PropertyMap::recordConcreteConformanceRule(
762706
unsigned concreteRuleID,
763707
unsigned conformanceRuleID,

0 commit comments

Comments
 (0)