Skip to content

Commit 94b55bd

Browse files
committed
RequirementMachine: Factor out PropertyMap::unifyConcreteTypes() from ::addConcreteTypeProperty()
1 parent 4c6cef0 commit 94b55bd

File tree

2 files changed

+75
-53
lines changed

2 files changed

+75
-53
lines changed

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ class PropertyMap {
250250

251251
void addConformanceProperty(Term key, Symbol property, unsigned ruleID);
252252
void addLayoutProperty(Term key, Symbol property, unsigned ruleID);
253+
254+
void unifyConcreteTypes(Term key,
255+
Optional<Symbol> &existingProperty,
256+
Optional<unsigned> &existingRuleID,
257+
Symbol property,
258+
unsigned ruleID);
259+
253260
void addSuperclassProperty(Term key, Symbol property, unsigned ruleID);
254261
void addConcreteTypeProperty(Term key, Symbol property, unsigned ruleID);
255262

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ static void recordRelation(Term key,
111111
(void) system.addRule(lhs, rhs, &path);
112112
}
113113

114+
/// Given a term T == U.V, an existing rule (V.[C] => V) and a new rule
115+
/// (U.V.[D] => U.V) where [C] and [D] are understood to be two property
116+
/// symbols in conflict with each other, mark the new rule as conflicting,
117+
/// and if the existing rule applies to the entire term T (that is, if
118+
/// |U| == 0) also mark the existing rule as conflicting.
114119
static void recordConflict(Term key,
115120
unsigned existingRuleID,
116121
unsigned newRuleID,
@@ -605,53 +610,36 @@ void PropertyMap::processTypeDifference(const TypeDifference &difference,
605610
lhsRule.markSubstitutionSimplified();
606611
}
607612

608-
/// When a type parameter has two concrete types, we have to unify the
609-
/// type constructor arguments.
610-
///
611-
/// For example, suppose that we have two concrete same-type requirements:
612-
///
613-
/// T == Foo<X.Y, Z, String>
614-
/// T == Foo<Int, A.B, W>
615-
///
616-
/// These lower to the following two rules:
617-
///
618-
/// T.[concrete: Foo<τ_0_0, τ_0_1, String> with {X.Y, Z}] => T
619-
/// T.[concrete: Foo<Int, τ_0_0, τ_0_1> with {A.B, W}] => T
620-
///
621-
/// The two concrete type symbols will be added to the property bag of 'T',
622-
/// and we will eventually end up in this method, where we will generate three
623-
/// induced rules:
624-
///
625-
/// X.Y.[concrete: Int] => X.Y
626-
/// A.B => Z
627-
/// W.[concrete: String] => W
628-
void PropertyMap::addConcreteTypeProperty(
629-
Term key, Symbol property, unsigned ruleID) {
630-
auto *props = getOrCreateProperties(key);
631-
613+
/// Utility used by addSuperclassProperty() and addConcreteTypeProperty().
614+
void PropertyMap::unifyConcreteTypes(
615+
Term key,
616+
Optional<Symbol> &existingProperty,
617+
Optional<unsigned> &existingRuleID,
618+
Symbol property,
619+
unsigned ruleID) {
632620
auto &rule = System.getRule(ruleID);
633621
assert(rule.getRHS() == key);
634622

635623
bool debug = Debug.contains(DebugFlags::ConcreteUnification);
636624

637-
if (!props->ConcreteType) {
638-
props->ConcreteType = property;
639-
props->ConcreteTypeRule = ruleID;
625+
if (!existingProperty.hasValue()) {
626+
existingProperty = property;
627+
existingRuleID = ruleID;
640628
return;
641629
}
642630

643-
assert(props->ConcreteTypeRule.hasValue());
631+
assert(existingRuleID.hasValue());
644632

645633
if (debug) {
646-
llvm::dbgs() << "% Unifying " << *props->ConcreteType;
647-
llvm::dbgs() << " with " << property << "\n";
634+
llvm::dbgs() << "% Unifying " << *existingProperty
635+
<< " with " << property << "\n";
648636
}
649637

650638
Optional<unsigned> lhsDifferenceID;
651639
Optional<unsigned> rhsDifferenceID;
652640

653641
bool conflict = System.computeTypeDifference(key,
654-
*props->ConcreteType, property,
642+
*existingProperty, property,
655643
lhsDifferenceID,
656644
rhsDifferenceID);
657645

@@ -660,7 +648,7 @@ void PropertyMap::addConcreteTypeProperty(
660648
if (debug) {
661649
llvm::dbgs() << "%% Concrete type conflict\n";
662650
}
663-
recordConflict(key, *props->ConcreteTypeRule, ruleID, System);
651+
recordConflict(key, *existingRuleID, ruleID, System);
664652
return;
665653
}
666654

@@ -679,7 +667,7 @@ void PropertyMap::addConcreteTypeProperty(
679667
MutableTerm lhsTerm(key);
680668
lhsTerm.add(newProperty);
681669

682-
if (checkRulePairOnce(*props->ConcreteTypeRule, ruleID)) {
670+
if (checkRulePairOnce(*existingRuleID, ruleID)) {
683671
assert(lhsDifference.RHS == rhsDifference.RHS);
684672

685673
if (debug) {
@@ -707,9 +695,9 @@ void PropertyMap::addConcreteTypeProperty(
707695
unsigned newRuleID = path.begin()->getRuleID();
708696

709697
// Process LHS -> (LHS ∧ RHS).
710-
if (checkRulePairOnce(*props->ConcreteTypeRule, newRuleID))
698+
if (checkRulePairOnce(*existingRuleID, newRuleID))
711699
processTypeDifference(lhsDifference, *lhsDifferenceID,
712-
*props->ConcreteTypeRule, newRuleID);
700+
*existingRuleID, newRuleID);
713701

714702
// Process RHS -> (LHS ∧ RHS).
715703
if (checkRulePairOnce(ruleID, newRuleID))
@@ -718,8 +706,8 @@ void PropertyMap::addConcreteTypeProperty(
718706

719707
// The new property is more specific, so update ConcreteType and
720708
// ConcreteTypeRule.
721-
props->ConcreteType = newProperty;
722-
props->ConcreteTypeRule = ruleID;
709+
existingProperty = newProperty;
710+
existingRuleID = ruleID;
723711

724712
return;
725713
}
@@ -729,17 +717,17 @@ void PropertyMap::addConcreteTypeProperty(
729717
assert(!rhsDifferenceID);
730718

731719
const auto &lhsDifference = System.getTypeDifference(*lhsDifferenceID);
732-
assert(*props->ConcreteType == lhsDifference.LHS);
720+
assert(*existingProperty == lhsDifference.LHS);
733721
assert(property == lhsDifference.RHS);
734722

735-
if (checkRulePairOnce(*props->ConcreteTypeRule, ruleID))
723+
if (checkRulePairOnce(*existingRuleID, ruleID))
736724
processTypeDifference(lhsDifference, *lhsDifferenceID,
737-
*props->ConcreteTypeRule, ruleID);
725+
*existingRuleID, ruleID);
738726

739-
// The new property is more specific, so update ConcreteType and
740-
// ConcreteTypeRule.
741-
props->ConcreteType = property;
742-
props->ConcreteTypeRule = ruleID;
727+
// The new property is more specific, so update existingProperty and
728+
// existingRuleID.
729+
existingProperty = property;
730+
existingRuleID = ruleID;
743731

744732
return;
745733
}
@@ -750,20 +738,20 @@ void PropertyMap::addConcreteTypeProperty(
750738

751739
const auto &rhsDifference = System.getTypeDifference(*rhsDifferenceID);
752740
assert(property == rhsDifference.LHS);
753-
assert(*props->ConcreteType == rhsDifference.RHS);
741+
assert(*existingProperty == rhsDifference.RHS);
754742

755-
if (checkRulePairOnce(*props->ConcreteTypeRule, ruleID))
743+
if (checkRulePairOnce(*existingRuleID, ruleID))
756744
processTypeDifference(rhsDifference, *rhsDifferenceID,
757-
ruleID, *props->ConcreteTypeRule);
745+
ruleID, *existingRuleID);
758746

759-
// The new property is less specific, so ConcreteType and ConcreteTypeRule
747+
// The new property is less specific, so existingProperty and existingRuleID
760748
// remain unchanged.
761749
return;
762750
}
763751

764-
assert(property == *props->ConcreteType);
752+
assert(property == *existingProperty);
765753

766-
if (*props->ConcreteTypeRule != ruleID) {
754+
if (*existingRuleID != ruleID) {
767755
// If the rules are different but the concrete types are identical, then
768756
// the key is some term U.V, the existing rule is a rule of the form:
769757
//
@@ -777,17 +765,44 @@ void PropertyMap::addConcreteTypeProperty(
777765
// the symbol's substitutions.
778766
//
779767
// Since the new rule appears without context, it becomes redundant.
780-
if (checkRulePairOnce(*props->ConcreteTypeRule, ruleID)) {
768+
if (checkRulePairOnce(*existingRuleID, ruleID)) {
781769
RewritePath path;
782-
buildRewritePathForUnifier(*props->ConcreteTypeRule, ruleID, System,
783-
path);
770+
buildRewritePathForUnifier(*existingRuleID, ruleID, System, path);
784771
System.recordRewriteLoop(MutableTerm(rule.getLHS()), path);
785772

786773
rule.markSubstitutionSimplified();
787774
}
788775
}
789776
}
790777

778+
/// When a type parameter has two concrete types, we have to unify the
779+
/// type constructor arguments.
780+
///
781+
/// For example, suppose that we have two concrete same-type requirements:
782+
///
783+
/// T == Foo<X.Y, Z, String>
784+
/// T == Foo<Int, A.B, W>
785+
///
786+
/// These lower to the following two rules:
787+
///
788+
/// T.[concrete: Foo<τ_0_0, τ_0_1, String> with {X.Y, Z}] => T
789+
/// T.[concrete: Foo<Int, τ_0_0, τ_0_1> with {A.B, W}] => T
790+
///
791+
/// The two concrete type symbols will be added to the property bag of 'T',
792+
/// and we will eventually end up in this method, where we will generate three
793+
/// induced rules:
794+
///
795+
/// X.Y.[concrete: Int] => X.Y
796+
/// A.B => Z
797+
/// W.[concrete: String] => W
798+
void PropertyMap::addConcreteTypeProperty(
799+
Term key, Symbol property, unsigned ruleID) {
800+
auto *props = getOrCreateProperties(key);
801+
802+
unifyConcreteTypes(key, props->ConcreteType, props->ConcreteTypeRule,
803+
property, ruleID);
804+
}
805+
791806
/// Record a protocol conformance, layout or superclass constraint on the given
792807
/// key. Must be called in monotonically non-decreasing key order.
793808
void PropertyMap::addProperty(

0 commit comments

Comments
 (0)