Skip to content

Commit b73df9d

Browse files
authored
Merge pull request #36169 from slavapestov/gsb-prep-work-for-new-redundant-requirement-algorithm
GSB: Some refactoring in preparation for new redundant requirements algorithm
2 parents 7880a2f + 24de191 commit b73df9d

File tree

2 files changed

+88
-155
lines changed

2 files changed

+88
-155
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class GenericSignatureBuilder {
211211
bool recordConformanceConstraint(GenericSignatureBuilder &builder,
212212
ResolvedType type,
213213
ProtocolDecl *proto,
214-
FloatingRequirementSource source);
214+
const RequirementSource *source);
215215

216216
/// Find a source of the same-type constraint that maps a potential
217217
/// archetype in this equivalence class to a concrete type along with
@@ -533,16 +533,9 @@ class GenericSignatureBuilder {
533533

534534
/// Enumerate the requirements that describe the signature of this
535535
/// generic signature builder.
536-
///
537-
/// \param f A function object that will be passed each requirement
538-
/// and requirement source.
539536
void enumerateRequirements(
540537
TypeArrayView<GenericTypeParamType> genericParams,
541-
llvm::function_ref<
542-
void (RequirementKind kind,
543-
Type type,
544-
RequirementRHS constraint,
545-
const RequirementSource *source)> f);
538+
SmallVectorImpl<Requirement> &requirements);
546539

547540
/// Retrieve the generic parameters used to describe the generic
548541
/// signature being built.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 86 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,7 +1710,7 @@ bool EquivalenceClass::recordConformanceConstraint(
17101710
GenericSignatureBuilder &builder,
17111711
ResolvedType type,
17121712
ProtocolDecl *proto,
1713-
FloatingRequirementSource source) {
1713+
const RequirementSource *source) {
17141714
// If we haven't seen a conformance to this protocol yet, add it.
17151715
bool inserted = false;
17161716
auto known = conformsTo.find(proto);
@@ -1730,8 +1730,7 @@ bool EquivalenceClass::recordConformanceConstraint(
17301730
}
17311731

17321732
// Record this conformance source.
1733-
known->second.push_back({type.getUnresolvedType(), proto,
1734-
source.getSource(builder, type)});
1733+
known->second.push_back({type.getUnresolvedType(), proto, source});
17351734
++NumConformanceConstraints;
17361735

17371736
return inserted;
@@ -4167,13 +4166,15 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
41674166
ResolvedType type,
41684167
ProtocolDecl *proto,
41694168
FloatingRequirementSource source) {
4169+
auto resolvedSource = source.getSource(*this, type);
4170+
41704171
// Add the conformance requirement, bailing out earlier if we've already
41714172
// seen it.
41724173
auto equivClass = type.getEquivalenceClass(*this);
4173-
if (!equivClass->recordConformanceConstraint(*this, type, proto, source))
4174+
if (!equivClass->recordConformanceConstraint(*this, type, proto,
4175+
resolvedSource))
41744176
return ConstraintResult::Resolved;
41754177

4176-
auto resolvedSource = source.getSource(*this, type);
41774178
return expandConformanceRequirement(type, proto, resolvedSource,
41784179
/*onlySameTypeRequirements=*/false);
41794180
}
@@ -4325,7 +4326,7 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
43254326
++NumSuperclassConstraints;
43264327

43274328
// Update the equivalence class with the constraint.
4328-
if (!updateSuperclass(type, superclass, source))
4329+
if (!updateSuperclass(type, superclass, resolvedSource))
43294330
++NumSuperclassConstraintsExtra;
43304331

43314332
return ConstraintResult::Resolved;
@@ -6902,14 +6903,14 @@ void GenericSignatureBuilder::checkLayoutConstraints(
69026903
namespace {
69036904
/// Retrieve the best requirement source from a set of constraints.
69046905
template<typename T>
6905-
Optional<const RequirementSource *>
6906+
const RequirementSource *
69066907
getBestConstraintSource(ArrayRef<Constraint<T>> constraints,
69076908
llvm::function_ref<bool(const T&)> matches) {
6908-
Optional<const RequirementSource *> bestSource;
6909+
const RequirementSource *bestSource = nullptr;
69096910
for (const auto &constraint : constraints) {
69106911
if (!matches(constraint.value)) continue;
69116912

6912-
if (!bestSource || constraint.source->compare(*bestSource) < 0)
6913+
if (!bestSource || constraint.source->compare(bestSource) < 0)
69136914
bestSource = constraint.source;
69146915
}
69156916

@@ -6922,11 +6923,34 @@ namespace {
69226923

69236924
void GenericSignatureBuilder::enumerateRequirements(
69246925
TypeArrayView<GenericTypeParamType> genericParams,
6925-
llvm::function_ref<
6926-
void (RequirementKind kind,
6927-
Type type,
6928-
RequirementRHS constraint,
6929-
const RequirementSource *source)> f) {
6926+
SmallVectorImpl<Requirement> &requirements) {
6927+
auto recordRequirement = [&](RequirementKind kind,
6928+
Type depTy,
6929+
RequirementRHS type) {
6930+
depTy = getSugaredDependentType(depTy, genericParams);
6931+
6932+
if (auto concreteTy = type.dyn_cast<Type>()) {
6933+
if (concreteTy->hasError())
6934+
return;
6935+
6936+
// Drop requirements involving concrete types containing
6937+
// unresolved associated types.
6938+
if (concreteTy->findUnresolvedDependentMemberType()) {
6939+
assert(Impl->HadAnyError);
6940+
return;
6941+
}
6942+
6943+
if (concreteTy->isTypeParameter())
6944+
concreteTy = getSugaredDependentType(concreteTy, genericParams);
6945+
6946+
requirements.push_back(Requirement(kind, depTy, concreteTy));
6947+
} else {
6948+
auto layoutConstraint = type.get<LayoutConstraint>();
6949+
requirements.push_back(Requirement(kind, depTy, layoutConstraint));
6950+
return;
6951+
}
6952+
};
6953+
69306954
// Collect all of the subject types that will be involved in constraints.
69316955
SmallVector<SameTypeComponentRef, 8> subjects;
69326956
for (auto &equivClass : Impl->EquivalenceClasses) {
@@ -6944,6 +6968,9 @@ void GenericSignatureBuilder::enumerateRequirements(
69446968
auto &component = equivClass->derivedSameTypeComponents[subject.second];
69456969
Type subjectType = component.type;
69466970

6971+
assert(!subjectType->hasError());
6972+
assert(!subjectType->findUnresolvedDependentMemberType());
6973+
69476974
// If this equivalence class is bound to a concrete type, equate the
69486975
// anchor with a concrete type.
69496976
if (Type concreteType = equivClass->concreteType) {
@@ -6957,17 +6984,22 @@ void GenericSignatureBuilder::enumerateRequirements(
69576984
.getEquivalenceClass(*this)->concreteType)
69586985
continue;
69596986

6960-
auto source =
6961-
component.concreteTypeSource
6962-
? component.concreteTypeSource
6963-
: RequirementSource::forAbstract(*this, subjectType);
6964-
69656987
// Drop recursive and invalid concrete-type constraints.
69666988
if (equivClass->recursiveConcreteType ||
69676989
equivClass->invalidConcreteType)
69686990
continue;
69696991

6970-
f(RequirementKind::SameType, subjectType, concreteType, source);
6992+
// Filter out derived requirements... except for concrete-type
6993+
// requirements on generic parameters. The exception is due to
6994+
// the canonicalization of generic signatures, which never
6995+
// eliminates generic parameters even when they have been
6996+
// mapped to a concrete type.
6997+
if (subjectType->is<GenericTypeParamType>() ||
6998+
component.concreteTypeSource == nullptr ||
6999+
!component.concreteTypeSource->isDerivedRequirement()) {
7000+
recordRequirement(RequirementKind::SameType,
7001+
subjectType, concreteType);
7002+
}
69717003
continue;
69727004
}
69737005

@@ -6982,9 +7014,9 @@ void GenericSignatureBuilder::enumerateRequirements(
69827014
equivClass->derivedSameTypeComponents[subject.second + 1];
69837015
Type otherSubjectType = nextComponent.type;
69847016
deferredSameTypeRequirement =
6985-
[&f, subjectType, otherSubjectType, this] {
6986-
f(RequirementKind::SameType, subjectType, otherSubjectType,
6987-
RequirementSource::forAbstract(*this, otherSubjectType));
7017+
[&recordRequirement, subjectType, otherSubjectType] {
7018+
recordRequirement(RequirementKind::SameType,
7019+
subjectType, otherSubjectType);
69887020
};
69897021
}
69907022

@@ -6998,18 +7030,19 @@ void GenericSignatureBuilder::enumerateRequirements(
69987030
continue;
69997031

70007032
// If we have a superclass, produce a superclass requirement
7001-
if (equivClass->superclass && !equivClass->recursiveSuperclassType) {
7033+
if (equivClass->superclass &&
7034+
!equivClass->recursiveSuperclassType &&
7035+
!equivClass->superclass->hasError()) {
70027036
auto bestSource =
70037037
getBestConstraintSource<Type>(equivClass->superclassConstraints,
70047038
[&](const Type &type) {
70057039
return type->isEqual(equivClass->superclass);
70067040
});
70077041

7008-
if (!bestSource)
7009-
bestSource = RequirementSource::forAbstract(*this, subjectType);
7010-
7011-
f(RequirementKind::Superclass, subjectType, equivClass->superclass,
7012-
*bestSource);
7042+
if (!bestSource->isDerivedRequirement()) {
7043+
recordRequirement(RequirementKind::Superclass,
7044+
subjectType, equivClass->superclass);
7045+
}
70137046
}
70147047

70157048
// If we have a layout constraint, produce a layout requirement.
@@ -7019,27 +7052,25 @@ void GenericSignatureBuilder::enumerateRequirements(
70197052
[&](const LayoutConstraint &layout) {
70207053
return layout == equivClass->layout;
70217054
});
7022-
if (!bestSource)
7023-
bestSource = RequirementSource::forAbstract(*this, subjectType);
70247055

7025-
f(RequirementKind::Layout, subjectType, equivClass->layout, *bestSource);
7056+
if (!bestSource->isDerivedRequirement()) {
7057+
recordRequirement(RequirementKind::Layout,
7058+
subjectType, equivClass->layout);
7059+
}
70267060
}
70277061

70287062
// Enumerate conformance requirements.
70297063
SmallVector<ProtocolDecl *, 4> protocols;
7030-
DenseMap<ProtocolDecl *, const RequirementSource *> protocolSources;
70317064

70327065
for (const auto &conforms : equivClass->conformsTo) {
7033-
protocols.push_back(conforms.first);
7034-
assert(protocolSources.count(conforms.first) == 0 &&
7035-
"redundant protocol requirement?");
7066+
auto *bestSource = getBestConstraintSource<ProtocolDecl *>(
7067+
conforms.second,
7068+
[&](ProtocolDecl *proto) {
7069+
return proto == conforms.first;
7070+
});
70367071

7037-
protocolSources.insert(
7038-
{conforms.first,
7039-
*getBestConstraintSource<ProtocolDecl *>(conforms.second,
7040-
[&](ProtocolDecl *proto) {
7041-
return proto == conforms.first;
7042-
})});
7072+
if (!bestSource->isDerivedRequirement())
7073+
protocols.push_back(conforms.first);
70437074
}
70447075

70457076
// Sort the protocols in canonical order.
@@ -7048,54 +7079,26 @@ void GenericSignatureBuilder::enumerateRequirements(
70487079

70497080
// Enumerate the conformance requirements.
70507081
for (auto proto : protocols) {
7051-
assert(protocolSources.count(proto) == 1 && "Missing conformance?");
7052-
f(RequirementKind::Conformance, subjectType,
7053-
proto->getDeclaredInterfaceType(),
7054-
protocolSources.find(proto)->second);
7082+
recordRequirement(RequirementKind::Conformance, subjectType,
7083+
proto->getDeclaredInterfaceType());
70557084
}
7056-
};
7085+
}
7086+
7087+
// Sort the subject types in canonical order. This needs to be a stable sort
7088+
// so that the relative order of requirements that have the same subject type
7089+
// is preserved.
7090+
std::stable_sort(requirements.begin(), requirements.end(),
7091+
[](const Requirement &lhs, const Requirement &rhs) {
7092+
return compareDependentTypes(lhs.getFirstType(),
7093+
rhs.getFirstType()) < 0;
7094+
});
70577095
}
70587096

70597097
void GenericSignatureBuilder::dump() {
70607098
dump(llvm::errs());
70617099
}
70627100

70637101
void GenericSignatureBuilder::dump(llvm::raw_ostream &out) {
7064-
out << "Requirements:";
7065-
enumerateRequirements(getGenericParams(),
7066-
[&](RequirementKind kind,
7067-
Type type,
7068-
RequirementRHS constraint,
7069-
const RequirementSource *source) {
7070-
switch (kind) {
7071-
case RequirementKind::Conformance:
7072-
case RequirementKind::Superclass:
7073-
out << "\n ";
7074-
out << type.getString() << " : "
7075-
<< constraint.get<Type>().getString() << " [";
7076-
source->print(out, &Context.SourceMgr);
7077-
out << "]";
7078-
break;
7079-
case RequirementKind::Layout:
7080-
out << "\n ";
7081-
out << type.getString() << " : "
7082-
<< constraint.get<LayoutConstraint>().getString() << " [";
7083-
source->print(out, &Context.SourceMgr);
7084-
out << "]";
7085-
break;
7086-
case RequirementKind::SameType:
7087-
out << "\n ";
7088-
out << type.getString() << " == " ;
7089-
auto secondType = constraint.get<Type>();
7090-
out << secondType.getString();
7091-
out << " [";
7092-
source->print(out, &Context.SourceMgr);
7093-
out << "]";
7094-
break;
7095-
}
7096-
});
7097-
out << "\n";
7098-
70997102
out << "Potential archetypes:\n";
71007103
for (auto pa : Impl->PotentialArchetypes) {
71017104
pa->dump(out, &Context.SourceMgr, 2);
@@ -7119,69 +7122,6 @@ void GenericSignatureBuilder::addGenericSignature(GenericSignature sig) {
71197122
addRequirement(reqt, FloatingRequirementSource::forAbstract(), nullptr);
71207123
}
71217124

7122-
/// Collect the set of requirements placed on the given generic parameters and
7123-
/// their associated types.
7124-
static void collectRequirements(GenericSignatureBuilder &builder,
7125-
TypeArrayView<GenericTypeParamType> params,
7126-
SmallVectorImpl<Requirement> &requirements) {
7127-
builder.enumerateRequirements(
7128-
params,
7129-
[&](RequirementKind kind,
7130-
Type depTy,
7131-
RequirementRHS type,
7132-
const RequirementSource *source) {
7133-
// Filter out derived requirements... except for concrete-type requirements
7134-
// on generic parameters. The exception is due to the canonicalization of
7135-
// generic signatures, which never eliminates generic parameters even when
7136-
// they have been mapped to a concrete type.
7137-
if (source->isDerivedRequirement() &&
7138-
!(kind == RequirementKind::SameType &&
7139-
depTy->is<GenericTypeParamType>() &&
7140-
type.is<Type>()))
7141-
return;
7142-
7143-
if (depTy->hasError())
7144-
return;
7145-
7146-
assert(!depTy->findUnresolvedDependentMemberType() &&
7147-
"Unresolved dependent member type in requirements");
7148-
7149-
depTy = getSugaredDependentType(depTy, params);
7150-
7151-
Type repTy;
7152-
if (auto concreteTy = type.dyn_cast<Type>()) {
7153-
// Maybe we were equated to a concrete or dependent type...
7154-
repTy = concreteTy;
7155-
7156-
// Drop requirements involving concrete types containing
7157-
// unresolved associated types.
7158-
if (repTy->findUnresolvedDependentMemberType())
7159-
return;
7160-
7161-
if (repTy->isTypeParameter())
7162-
repTy = getSugaredDependentType(repTy, params);
7163-
} else {
7164-
auto layoutConstraint = type.get<LayoutConstraint>();
7165-
requirements.push_back(Requirement(kind, depTy, layoutConstraint));
7166-
return;
7167-
}
7168-
7169-
if (repTy->hasError())
7170-
return;
7171-
7172-
requirements.push_back(Requirement(kind, depTy, repTy));
7173-
});
7174-
7175-
// Sort the subject types in canonical order. This needs to be a stable sort
7176-
// so that the relative order of requirements that have the same subject type
7177-
// is preserved.
7178-
std::stable_sort(requirements.begin(), requirements.end(),
7179-
[](const Requirement &lhs, const Requirement &rhs) {
7180-
return compareDependentTypes(lhs.getFirstType(),
7181-
rhs.getFirstType()) < 0;
7182-
});
7183-
}
7184-
71857125
GenericSignature GenericSignatureBuilder::computeGenericSignature(
71867126
bool allowConcreteGenericParams,
71877127
bool allowBuilderToMove) && {
@@ -7190,7 +7130,7 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
71907130

71917131
// Collect the requirements placed on the generic parameter types.
71927132
SmallVector<Requirement, 4> requirements;
7193-
collectRequirements(*this, getGenericParams(), requirements);
7133+
enumerateRequirements(getGenericParams(), requirements);
71947134

71957135
// Form the generic signature.
71967136
auto sig = GenericSignature::get(getGenericParams(), requirements);

0 commit comments

Comments
 (0)