Skip to content

Commit a926bea

Browse files
committed
[GSB] Hack to limit recursion in the type graph.
This stops after 5 recurrences of the same associated type. It is a gross hack and a terrible idea, here as a placeholder to prevent us from running off the rails in ill-formed code. This will go away when we get further along the path with recursive protocol constraints.
1 parent 29a15ce commit a926bea

File tree

5 files changed

+62
-18
lines changed

5 files changed

+62
-18
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,9 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11081108
Inferred,
11091109
/// A requirement source augmented by an abstract protocol requirement
11101110
AbstractProtocol,
1111+
/// A requirement source for a nested-type-name match introduced by
1112+
/// the given source.
1113+
NestedTypeNameMatch,
11111114
} kind;
11121115

11131116
using Storage =
@@ -1117,11 +1120,15 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11171120
Storage storage;
11181121

11191122
// Additional storage for an abstract protocol requirement.
1120-
struct {
1121-
ProtocolDecl *protocol = nullptr;
1122-
WrittenRequirementLoc written;
1123-
bool inferred = false;
1124-
} protocolReq;
1123+
union {
1124+
struct {
1125+
ProtocolDecl *protocol = nullptr;
1126+
WrittenRequirementLoc written;
1127+
bool inferred = false;
1128+
} protocolReq;
1129+
1130+
Identifier nestedName;
1131+
};
11251132

11261133
FloatingRequirementSource(Kind kind, Storage storage)
11271134
: kind(kind), storage(storage) { }
@@ -1170,6 +1177,14 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11701177
return result;
11711178
}
11721179

1180+
static FloatingRequirementSource forNestedTypeNameMatch(
1181+
const RequirementSource *base,
1182+
Identifier nestedName) {
1183+
FloatingRequirementSource result{ NestedTypeNameMatch, base };
1184+
result.nestedName = nestedName;
1185+
return result;
1186+
};
1187+
11731188
/// Retrieve the complete requirement source rooted at the given potential
11741189
/// archetype.
11751190
const RequirementSource *getSource(PotentialArchetype *pa) const;

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,9 @@ const RequirementSource *FloatingRequirementSource::getSource(
846846
protocolReq.protocol, protocolReq.inferred,
847847
protocolReq.written);
848848
}
849+
850+
case NestedTypeNameMatch:
851+
return RequirementSource::forNestedTypeNameMatch(pa);
849852
}
850853

851854
llvm_unreachable("Unhandled FloatingPointRequirementSourceKind in switch.");
@@ -878,6 +881,7 @@ bool FloatingRequirementSource::isExplicit() const {
878881
return true;
879882

880883
case Inferred:
884+
case NestedTypeNameMatch:
881885
return false;
882886

883887
case AbstractProtocol:
@@ -926,6 +930,7 @@ FloatingRequirementSource FloatingRequirementSource::asInferred(
926930

927931
case Inferred:
928932
case Resolved:
933+
case NestedTypeNameMatch:
929934
return *this;
930935

931936
case AbstractProtocol:
@@ -950,6 +955,22 @@ bool FloatingRequirementSource::isRecursive(
950955
return true;
951956
}
952957

958+
// For a nested type match, look for another type with that name.
959+
// FIXME: Actually, look for 5 of them. This is totally bogus.
960+
if (kind == NestedTypeNameMatch) {
961+
unsigned grossCount = 0;
962+
auto pa = storage.dyn_cast<const RequirementSource *>()
963+
->getAffectedPotentialArchetype();
964+
while (auto parent = pa->getParent()) {
965+
if (pa->getNestedName() == nestedName) {
966+
if (++grossCount > 4) return true;
967+
}
968+
969+
970+
pa = parent;
971+
}
972+
}
973+
953974
return false;
954975
}
955976

@@ -1442,7 +1463,13 @@ PotentialArchetype *PotentialArchetype::getArchetypeAnchor(
14421463
if (auto parent = getParent()) {
14431464
// For a nested type, retrieve the parent archetype anchor first.
14441465
auto parentAnchor = parent->getArchetypeAnchor(builder);
1445-
anchor = parentAnchor->getNestedArchetypeAnchor(getNestedName(), builder);
1466+
anchor = parentAnchor->getNestedArchetypeAnchor(
1467+
getNestedName(), builder,
1468+
NestedTypeUpdate::ResolveExisting);
1469+
1470+
// FIXME: Hack for cases where we couldn't resolve the nested type.
1471+
if (!anchor)
1472+
anchor = rep;
14461473
} else {
14471474
anchor = rep;
14481475
}
@@ -2835,14 +2862,16 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
28352862
}
28362863

28372864
// Recursively merge the associated types of T2 into T1.
2865+
auto dependentT1 = T1->getDependentType({ }, /*allowUnresolved=*/true);
28382866
for (auto equivT2 : equivClass2Members) {
28392867
for (auto T2Nested : equivT2->NestedTypes) {
2840-
auto T1Nested = T1->getNestedType(T2Nested.first, *this);
2841-
if (isErrorResult(addSameTypeRequirement(
2842-
T1Nested, T2Nested.second.front(),
2843-
RequirementSource::forNestedTypeNameMatch(T1Nested),
2844-
UnresolvedHandlingKind::GenerateConstraints,
2845-
DiagnoseSameTypeConflict{Diags, Source, T1Nested})))
2868+
Type nestedT1 = DependentMemberType::get(dependentT1, T2Nested.first);
2869+
if (isErrorResult(
2870+
addSameTypeRequirement(
2871+
nestedT1, T2Nested.second.front(),
2872+
FloatingRequirementSource::forNestedTypeNameMatch(
2873+
Source, T2Nested.first),
2874+
UnresolvedHandlingKind::GenerateConstraints)))
28462875
return ConstraintResult::Conflicting;
28472876
}
28482877
}

test/Generics/associated_type_typo.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
3939
// CHECK-GENERIC-LABEL: .typoAssoc4@
4040
// CHECK-GENERIC-NEXT: Requirements:
4141
// CHECK-GENERIC-NEXT: τ_0_0 : P2 [τ_0_0: Explicit @ {{.*}}:21]
42-
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)]
42+
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2 : P1 [τ_0_0: Explicit @ {{.*}}:21 -> Protocol requirement (via Self.AssocP2 in P2)
4343
// CHECK-GENERIC-NEXT: τ_0_0[.P2].AssocP2[.P1].Assoc : P3 [τ_0_0[.P2].AssocP2[.P1].Assoc: Explicit @ {{.*}}:53]
4444
// CHECK-GENERIC-NEXT: Potential archetypes
4545

test/Generics/protocol_type_aliases.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ protocol Q {
1616
// CHECK-LABEL: .requirementOnNestedTypeAlias@
1717
// CHECK-NEXT: Requirements:
1818
// CHECK-NEXT: τ_0_0 : Q [τ_0_0: Explicit @ 22:51]
19-
// CHECK-NEXT: τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (via Self.B in Q)]
19+
// CHECK-NEXT: τ_0_0[.Q].B : P [τ_0_0: Explicit @ 22:51 -> Protocol requirement (via Self.B in Q)
2020
// CHECK-NEXT: τ_0_0[.Q].B[.P].A == Int [τ_0_0[.Q].B[.P].X: Explicit @ 22:62]
2121
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q, τ_0_0.B.A == Int>
2222
func requirementOnNestedTypeAlias<T>(_: T) where T: Q, T.B.X == Int {}
@@ -35,7 +35,7 @@ protocol Q2 {
3535
// CHECK-LABEL: .requirementOnConcreteNestedTypeAlias@
3636
// CHECK-NEXT: Requirements:
3737
// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 42:59]
38-
// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)]
38+
// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 42:59 -> Protocol requirement (via Self.B in Q2)
3939
// CHECK-NEXT: τ_0_0[.Q2].C == S<T.B.A> [τ_0_0[.Q2].C: Explicit]
4040
// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Nested type match]
4141
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == S<τ_0_0.B.A>>
@@ -44,7 +44,7 @@ func requirementOnConcreteNestedTypeAlias<T>(_: T) where T: Q2, T.C == T.B.X {}
4444
// CHECK-LABEL: .concreteRequirementOnConcreteNestedTypeAlias@
4545
// CHECK-NEXT: Requirements:
4646
// CHECK-NEXT: τ_0_0 : Q2 [τ_0_0: Explicit @ 51:67]
47-
// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (via Self.B in Q2)]
47+
// CHECK-NEXT: τ_0_0[.Q2].B : P2 [τ_0_0: Explicit @ 51:67 -> Protocol requirement (via Self.B in Q2)
4848
// CHECK-NEXT: τ_0_0[.Q2].C == τ_0_0[.Q2].B[.P2].A [τ_0_0[.Q2].C: Explicit]
4949
// CHECK-NEXT: τ_0_0[.Q2].B[.P2].X == S<T.B.A> [τ_0_0[.Q2].B[.P2].X: Nested type match]
5050
// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : Q2, τ_0_0.C == τ_0_0.B.A>

test/Generics/requirement_inference.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct Model_P3_P4_Eq<T : P3, U : P4> where T.P3Assoc == U.P4Assoc {}
117117
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Inferred @ {{.*}}:32]
118118
// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Inferred @ {{.*}}:32]
119119
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P4Assoc in P4)
120-
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)]
120+
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Inferred @ {{.*}}:32 -> Protocol requirement (via Self.P3Assoc in P3)
121121
// FIXME: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0: Inferred]
122122
func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
123123

@@ -126,7 +126,7 @@ func inferSameType1<T, U>(_ x: Model_P3_P4_Eq<T, U>) { }
126126
// CHECK-NEXT: τ_0_0 : P3 [τ_0_0: Explicit @ {{.*}}:25]
127127
// CHECK-NEXT: τ_0_1 : P4 [τ_0_1: Explicit @ {{.*}}:33]
128128
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P1 [τ_0_1: Explicit @ {{.*}}:33 -> Protocol requirement (via Self.P4Assoc in P4)
129-
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)]
129+
// CHECK-NEXT: τ_0_0[.P3].P3Assoc : P2 [τ_0_0: Explicit @ {{.*}}:25 -> Protocol requirement (via Self.P3Assoc in P3)
130130
// CHECK-NEXT: τ_0_0[.P3].P3Assoc == τ_0_1[.P4].P4Assoc [τ_0_0[.P3].P3Assoc: Explicit]
131131
func inferSameType2<T : P3, U : P4>(_: T, _: U) where U.P4Assoc : P2, T.P3Assoc == U.P4Assoc {}
132132
// expected-warning@-1{{redundant conformance constraint 'T.P3Assoc': 'P2'}}

0 commit comments

Comments
 (0)