Skip to content

Commit be772cc

Browse files
committed
RequirementMachine: Layout requirement implied by superclass is now handled in the property map
1 parent 2737989 commit be772cc

8 files changed

+43
-28
lines changed

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ class PropertyMap {
181181
llvm::DenseMap<std::pair<unsigned, unsigned>, ProtocolConformance *>
182182
ConcreteConformances;
183183

184+
/// Superclass requirements always imply a layout requirement, and
185+
/// concrete type requirements where the type is a class imply a
186+
/// superclass requirement.
187+
///
188+
/// Keep track of such rules to avoid wasted work from recording the
189+
/// same rewrite loop more than once.
190+
llvm::DenseSet<unsigned> CheckedRules;
191+
184192
/// When a type parameter is subject to two requirements of the same
185193
/// kind, we have a pair of rewrite rules T.[p1] => T and T.[p2] => T.
186194
///
@@ -218,6 +226,7 @@ class PropertyMap {
218226
private:
219227
void clear();
220228

229+
bool checkRuleOnce(unsigned ruleID);
221230
bool checkRulePairOnce(unsigned firstRuleID, unsigned secondRuleID);
222231

223232
void addProperty(Term key, Symbol property, unsigned ruleID,

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
using namespace swift;
3838
using namespace rewriting;
3939

40+
/// Returns true if we have not processed this rule before.
41+
bool PropertyMap::checkRuleOnce(unsigned ruleID) {
42+
return CheckedRules.insert(ruleID).second;
43+
}
44+
4045
/// Returns true if we have not processed this pair of rules before.
4146
bool PropertyMap::checkRulePairOnce(unsigned firstRuleID,
4247
unsigned secondRuleID) {
@@ -65,7 +70,7 @@ RewriteSystem::getRelation(unsigned index) const {
6570
}
6671

6772
/// Given a key T, a rule (V.[p1] => V) where T == U.V, and a property [p2]
68-
/// where [p1] < [p2], record a rule (T.[p2] => T) that is implied by
73+
/// where [p1] < [p2], record a rule (T.[p2] => T) that is induced by
6974
/// the original rule (V.[p1] => V).
7075
static void recordRelation(Term key,
7176
unsigned lhsRuleID,
@@ -80,7 +85,9 @@ static void recordRelation(Term key,
8085

8186
assert(lhsProperty.isProperty());
8287
assert(rhsProperty.isProperty());
83-
assert(lhsProperty.getKind() == rhsProperty.getKind());
88+
assert(lhsProperty.getKind() == rhsProperty.getKind() ||
89+
(lhsProperty.getKind() == Symbol::Kind::Superclass &&
90+
rhsProperty.getKind() == Symbol::Kind::Layout));
8491

8592
if (debug) {
8693
llvm::dbgs() << "%% Recording relation: ";
@@ -474,6 +481,21 @@ void PropertyMap::addProperty(
474481
case Symbol::Kind::Superclass: {
475482
// FIXME: Also handle superclass vs concrete
476483

484+
if (checkRuleOnce(ruleID)) {
485+
// A rule (T.[superclass: C] => T) induces a rule (T.[layout: L] => T),
486+
// where L is either AnyObject or _NativeObject.
487+
auto superclass =
488+
property.getSuperclass()->getClassOrBoundGenericClass();
489+
auto layout =
490+
LayoutConstraint::getLayoutConstraint(
491+
superclass->getLayoutConstraintKind(),
492+
Context.getASTContext());
493+
auto layoutSymbol = Symbol::forLayout(layout, Context);
494+
495+
recordRelation(key, ruleID, layoutSymbol, System,
496+
inducedRules, debug);
497+
}
498+
477499
if (!props->Superclass) {
478500
props->Superclass = property;
479501
props->SuperclassRule = ruleID;

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -924,25 +924,6 @@ void RuleBuilder::addRequirement(const Requirement &req,
924924
auto superclassSymbol = Symbol::forSuperclass(otherType, substitutions,
925925
Context);
926926

927-
{
928-
// Build the symbol [layout: L].
929-
auto layout =
930-
LayoutConstraint::getLayoutConstraint(
931-
otherType->getClassOrBoundGenericClass()->getLayoutConstraintKind(),
932-
Context.getASTContext());
933-
auto layoutSymbol = Symbol::forLayout(layout, Context);
934-
935-
MutableTerm layoutSubjectTerm;
936-
layoutSubjectTerm.add(superclassSymbol);
937-
938-
MutableTerm layoutConstraintTerm = layoutSubjectTerm;
939-
layoutConstraintTerm.add(layoutSymbol);
940-
941-
// Add the rule [superclass: C<X, Y>].[layout: L] => [superclass: C<X, Y>].
942-
PermanentRules.emplace_back(layoutConstraintTerm,
943-
layoutSubjectTerm);
944-
}
945-
946927
// Build the term T.[superclass: C<X, Y>].
947928
constraintTerm = subjectTerm;
948929
constraintTerm.add(superclassSymbol);

test/Generics/generic_objc_superclass.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ func foo<T : Generic<U>, U>(_: T, _: U) {
1313

1414
// CHECK-LABEL: Requirement machine for <τ_0_0, τ_0_1 where τ_0_0 : Generic<τ_0_1>>
1515
// CHECK-NEXT: Rewrite system: {
16-
// CHECK-NEXT: - [superclass: Generic<τ_0_0> with <τ_0_1>].[layout: AnyObject] => [superclass: Generic<τ_0_0> with <τ_0_1>] [permanent]
1716
// CHECK-NEXT: - τ_0_0.[superclass: Generic<τ_0_0> with <τ_0_1>] => τ_0_0
1817
// CHECK-NEXT: - τ_0_0.[layout: AnyObject] => τ_0_0
1918
// CHECK-NEXT: }

test/Generics/unify_superclass_types_1.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,12 @@ extension P where Self : Derived {
1616
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : Derived, τ_0_0 : P>
1717
// CHECK-NEXT: Rewrite system: {
1818
// CHECK-NEXT: - [P].[P] => [P] [permanent]
19-
// CHECK-NEXT: - [superclass: Base].[layout: _NativeClass] => [superclass: Base] [permanent]
20-
// CHECK-NEXT: - [superclass: Derived].[layout: _NativeClass] => [superclass: Derived] [permanent]
2119
// CHECK-NEXT: - [P].[superclass: Base] => [P]
2220
// CHECK-NEXT: - τ_0_0.[superclass: Derived] => τ_0_0
2321
// CHECK-NEXT: - τ_0_0.[P] => τ_0_0
22+
// CHECK-NEXT: - τ_0_0.[superclass: Base] => τ_0_0
2423
// CHECK-NEXT: - [P].[layout: _NativeClass] => [P]
2524
// CHECK-NEXT: - τ_0_0.[layout: _NativeClass] => τ_0_0
26-
// CHECK-NEXT: - τ_0_0.[superclass: Base] => τ_0_0
2725
// CHECK-NEXT: }
2826
// CHECK-NEXT: Rewrite loops: {
2927
// CHECK: }

test/Generics/unify_superclass_types_2.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
3131
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
3232
// CHECK-NEXT: Rewrite system: {
3333
// CHECK: - τ_0_0.[P1&P2:X].[superclass: Generic<τ_0_0, String, τ_0_1> with <τ_0_0.[P2:A2], τ_0_0.[P2:B2]>] => τ_0_0.[P1&P2:X]
34-
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
3534
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[superclass: Generic<Int, τ_0_0, τ_0_1> with <τ_0_0.[P1:A1], τ_0_0.[P1:B1]>] => τ_0_0.[P1&P2:X]
3635
// CHECK-NEXT: - τ_0_0.X => τ_0_0.[P1&P2:X]
3736
// CHECK-NEXT: - τ_0_0.[P2:X] => τ_0_0.[P1&P2:X]
37+
// CHECK-NEXT: - [P1:X].[layout: _NativeClass] => [P1:X]
38+
// CHECK-NEXT: - [P2:X].[layout: _NativeClass] => [P2:X]
39+
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
3840
// CHECK-NEXT: - τ_0_0.[P2:A2].[concrete: Int] => τ_0_0.[P2:A2]
3941
// CHECK-NEXT: - τ_0_0.[P1:A1].[concrete: String] => τ_0_0.[P1:A1]
4042
// CHECK-NEXT: - τ_0_0.[P2:B2] => τ_0_0.[P1:B1]

test/Generics/unify_superclass_types_3.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
3333
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
3434
// CHECK-NEXT: Rewrite system: {
3535
// CHECK: - τ_0_0.[P1&P2:X].[superclass: Generic<τ_0_0, String, τ_0_1> with <τ_0_0.[P2:A2], τ_0_0.[P2:B2]>] => τ_0_0.[P1&P2:X]
36-
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
3736
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[superclass: Derived<τ_0_0, τ_0_1> with <τ_0_0.[P1:A1], τ_0_0.[P1:B1]>] => τ_0_0.[P1&P2:X]
3837
// CHECK-NEXT: - τ_0_0.X => τ_0_0.[P1&P2:X]
3938
// CHECK-NEXT: - τ_0_0.[P2:X] => τ_0_0.[P1&P2:X]
39+
// CHECK-NEXT: - [P1:X].[layout: _NativeClass] => [P1:X]
40+
// CHECK-NEXT: - [P2:X].[layout: _NativeClass] => [P2:X]
41+
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
4042
// CHECK-NEXT: - τ_0_0.[P2:A2].[concrete: Int] => τ_0_0.[P2:A2]
4143
// CHECK-NEXT: - τ_0_0.[P1:A1].[concrete: String] => τ_0_0.[P1:A1]
4244
// CHECK-NEXT: - τ_0_0.[P2:B2] => τ_0_0.[P1:B1]

test/Generics/unify_superclass_types_4.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ func unifySuperclassTest<T : P1 & P2>(_: T) {
3636
// CHECK-LABEL: Requirement machine for <τ_0_0 where τ_0_0 : P1, τ_0_0 : P2>
3737
// CHECK-NEXT: Rewrite system: {
3838
// CHECK: - τ_0_0.[P1&P2:X].[superclass: Derived<τ_0_0> with <τ_0_0.[P2:A2]>] => τ_0_0.[P1&P2:X]
39-
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
4039
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[superclass: Base<τ_0_0> with <τ_0_0.[P1:A1]>] => τ_0_0.[P1&P2:X]
4140
// CHECK-NEXT: - τ_0_0.X => τ_0_0.[P1&P2:X]
4241
// CHECK-NEXT: - τ_0_0.[P2:X] => τ_0_0.[P1&P2:X]
42+
// CHECK-NEXT: - [P1:X].[layout: _NativeClass] => [P1:X]
43+
// CHECK-NEXT: - [P2:X].[layout: _NativeClass] => [P2:X]
44+
// CHECK-NEXT: - τ_0_0.[P1&P2:X].[layout: _NativeClass] => τ_0_0.[P1&P2:X]
4345
// CHECK-NEXT: - τ_0_0.[P2:A2].[Q:T] => τ_0_0.[P1:A1]
4446
// CHECK-NEXT: }
4547
// CHECK-NEXT: Rewrite loops: {

0 commit comments

Comments
 (0)