Skip to content

Commit 0f4ebfd

Browse files
authored
Merge pull request #8593 from DougGregor/stdlib-se-0142
2 parents 815a68b + 5eebd08 commit 0f4ebfd

22 files changed

+205
-250
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ class GenericSignatureBuilder {
193193
/// Determine whether conformance to the given protocol is satisfied by
194194
/// a superclass requirement.
195195
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;
196+
197+
/// Dump a debugging representation of this equivalence class.
198+
void dump(llvm::raw_ostream &out) const;
199+
200+
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
201+
"only for use in the debugger");
196202
};
197203

198204
friend class RequirementSource;
@@ -1103,6 +1109,9 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11031109
Inferred,
11041110
/// A requirement source augmented by an abstract protocol requirement
11051111
AbstractProtocol,
1112+
/// A requirement source for a nested-type-name match introduced by
1113+
/// the given source.
1114+
NestedTypeNameMatch,
11061115
} kind;
11071116

11081117
using Storage =
@@ -1112,11 +1121,15 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11121121
Storage storage;
11131122

11141123
// Additional storage for an abstract protocol requirement.
1115-
struct {
1116-
ProtocolDecl *protocol = nullptr;
1117-
WrittenRequirementLoc written;
1118-
bool inferred = false;
1119-
} protocolReq;
1124+
union {
1125+
struct {
1126+
ProtocolDecl *protocol = nullptr;
1127+
WrittenRequirementLoc written;
1128+
bool inferred = false;
1129+
} protocolReq;
1130+
1131+
Identifier nestedName;
1132+
};
11201133

11211134
FloatingRequirementSource(Kind kind, Storage storage)
11221135
: kind(kind), storage(storage) { }
@@ -1165,6 +1178,14 @@ class GenericSignatureBuilder::FloatingRequirementSource {
11651178
return result;
11661179
}
11671180

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

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 108 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ static Type formProtocolRelativeType(ProtocolDecl *proto,
803803
PotentialArchetype *basePA,
804804
PotentialArchetype *pa) {
805805
// Basis case: we've hit the base potential archetype.
806-
if (basePA->isInSameEquivalenceClassAs(pa))
806+
if (basePA == pa)
807807
return proto->getSelfInterfaceType();
808808

809809
// Recursive case: form a dependent member type.
@@ -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:
@@ -941,7 +946,7 @@ bool FloatingRequirementSource::isRecursive(
941946
llvm::SmallSet<std::pair<CanType, ProtocolDecl *>, 4> visitedAssocReqs;
942947
for (auto storedSource = storage.dyn_cast<const RequirementSource *>();
943948
storedSource; storedSource = storedSource->parent) {
944-
if (storedSource->kind != RequirementSource::ProtocolRequirement)
949+
if (!storedSource->isProtocolRequirement())
945950
continue;
946951

947952
if (!visitedAssocReqs.insert(
@@ -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

@@ -1083,6 +1104,50 @@ bool EquivalenceClass::isConformanceSatisfiedBySuperclass(
10831104
return false;
10841105
}
10851106

1107+
void EquivalenceClass::dump(llvm::raw_ostream &out) const {
1108+
out << "Equivalence class represented by "
1109+
<< members.front()->getRepresentative()->getDebugName() << ":\n";
1110+
out << "Members: ";
1111+
interleave(members, [&](PotentialArchetype *pa) {
1112+
out << pa->getDebugName();
1113+
}, [&]() {
1114+
out << ", ";
1115+
});
1116+
out << "\nConformances:";
1117+
interleave(conformsTo,
1118+
[&](const std::pair<
1119+
ProtocolDecl *,
1120+
std::vector<Constraint<ProtocolDecl *>>> &entry) {
1121+
out << entry.first->getNameStr();
1122+
},
1123+
[&] { out << ", "; });
1124+
out << "\nSame-type constraints:";
1125+
for (const auto &entry : sameTypeConstraints) {
1126+
out << "\n " << entry.first->getDebugName() << " == ";
1127+
interleave(entry.second,
1128+
[&](const Constraint<PotentialArchetype *> &constraint) {
1129+
out << constraint.value->getDebugName();
1130+
1131+
if (constraint.source->isDerivedRequirement())
1132+
out << " [derived]";
1133+
}, [&] {
1134+
out << ", ";
1135+
});
1136+
}
1137+
if (concreteType)
1138+
out << "\nConcrete type: " << concreteType.getString();
1139+
if (superclass)
1140+
out << "\nSuperclass: " << superclass.getString();
1141+
if (layout)
1142+
out << "\nLayout: " << layout.getString();
1143+
1144+
out << "\n";
1145+
}
1146+
1147+
void EquivalenceClass::dump() const {
1148+
dump(llvm::errs());
1149+
}
1150+
10861151
ConstraintResult GenericSignatureBuilder::handleUnresolvedRequirement(
10871152
RequirementKind kind,
10881153
UnresolvedType lhs,
@@ -1398,7 +1463,13 @@ PotentialArchetype *PotentialArchetype::getArchetypeAnchor(
13981463
if (auto parent = getParent()) {
13991464
// For a nested type, retrieve the parent archetype anchor first.
14001465
auto parentAnchor = parent->getArchetypeAnchor(builder);
1401-
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;
14021473
} else {
14031474
anchor = rep;
14041475
}
@@ -2791,14 +2862,16 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenArchetypes(
27912862
}
27922863

27932864
// Recursively merge the associated types of T2 into T1.
2865+
auto dependentT1 = T1->getDependentType({ }, /*allowUnresolved=*/true);
27942866
for (auto equivT2 : equivClass2Members) {
27952867
for (auto T2Nested : equivT2->NestedTypes) {
2796-
auto T1Nested = T1->getNestedType(T2Nested.first, *this);
2797-
if (isErrorResult(addSameTypeRequirement(
2798-
T1Nested, T2Nested.second.front(),
2799-
RequirementSource::forNestedTypeNameMatch(T1Nested),
2800-
UnresolvedHandlingKind::GenerateConstraints,
2801-
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)))
28022875
return ConstraintResult::Conflicting;
28032876
}
28042877
}
@@ -3809,8 +3882,12 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
38093882

38103883
namespace {
38113884
/// Remove self-derived sources from the given vector of constraints.
3885+
///
3886+
/// \returns true if any derived-via-concrete constraints were found.
38123887
template<typename T>
3813-
void removeSelfDerived(std::vector<Constraint<T>> &constraints) {
3888+
bool removeSelfDerived(std::vector<Constraint<T>> &constraints,
3889+
bool dropDerivedViaConcrete = true) {
3890+
bool anyDerivedViaConcrete = false;
38143891
// Remove self-derived constraints.
38153892
Optional<Constraint<T>> remainingConcrete;
38163893
constraints.erase(
@@ -3824,6 +3901,11 @@ namespace {
38243901
if (!derivedViaConcrete)
38253902
return false;
38263903

3904+
anyDerivedViaConcrete = true;
3905+
3906+
if (!dropDerivedViaConcrete)
3907+
return false;
3908+
38273909
// Drop derived-via-concrete requirements.
38283910
if (!remainingConcrete)
38293911
remainingConcrete = constraint;
@@ -3836,6 +3918,7 @@ namespace {
38363918
constraints.push_back(*remainingConcrete);
38373919

38383920
assert(!constraints.empty() && "All constraints were self-derived!");
3921+
return anyDerivedViaConcrete;
38393922
}
38403923
}
38413924

@@ -4191,11 +4274,13 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
41914274
equivClass = pa->getEquivalenceClassIfPresent();
41924275
assert(equivClass && "Equivalence class disappeared?");
41934276

4277+
bool anyDerivedViaConcrete = false;
41944278
for (auto &entry : equivClass->sameTypeConstraints) {
41954279
auto &constraints = entry.second;
41964280

41974281
// Remove self-derived constraints.
4198-
removeSelfDerived(constraints);
4282+
if (removeSelfDerived(constraints, /*dropDerivedViaConcrete=*/false))
4283+
anyDerivedViaConcrete = true;
41994284

42004285
// Sort the constraints, so we get a deterministic ordering of diagnostics.
42014286
llvm::array_pod_sort(constraints.begin(), constraints.end());
@@ -4272,6 +4357,18 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
42724357
}
42734358
}
42744359

4360+
// If there were any derived-via-concrete constraints, drop them now before
4361+
// we emit other diagnostics.
4362+
if (anyDerivedViaConcrete) {
4363+
for (auto &entry : equivClass->sameTypeConstraints) {
4364+
auto &constraints = entry.second;
4365+
4366+
// Remove derived-via-concrete constraints.
4367+
(void)removeSelfDerived(constraints);
4368+
anyDerivedViaConcrete = true;
4369+
}
4370+
}
4371+
42754372
// Walk through each of the components, checking the intracomponent edges.
42764373
// This will diagnose any explicitly-specified requirements within a
42774374
// component, all of which are redundant.

0 commit comments

Comments
 (0)