Skip to content

Commit 3454db6

Browse files
authored
Merge pull request #35808 from slavapestov/more-gsb-optimizations
A couple more GenericSignatureBuilder optimizations
2 parents 28a6d24 + fd809ca commit 3454db6

File tree

4 files changed

+54
-70
lines changed

4 files changed

+54
-70
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ class GenericSignatureBuilder::FloatingRequirementSource {
14241424

14251425
/// Retrieve the complete requirement source rooted at the given type.
14261426
const RequirementSource *getSource(GenericSignatureBuilder &builder,
1427-
Type type) const;
1427+
ResolvedType type) const;
14281428

14291429
/// Retrieve the source location for this requirement.
14301430
SourceLoc getLoc() const;

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 52 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,40 +1458,49 @@ static Type formProtocolRelativeType(ProtocolDecl *proto,
14581458

14591459
const RequirementSource *FloatingRequirementSource::getSource(
14601460
GenericSignatureBuilder &builder,
1461-
Type type) const {
1461+
ResolvedType type) const {
14621462
switch (kind) {
14631463
case Resolved:
14641464
return storage.get<const RequirementSource *>();
14651465

1466-
case Explicit:
1466+
case Explicit: {
1467+
auto depType = type.getDependentType(builder);
1468+
14671469
if (auto requirementRepr = storage.dyn_cast<const RequirementRepr *>())
1468-
return RequirementSource::forExplicit(builder, type, requirementRepr);
1470+
return RequirementSource::forExplicit(builder, depType, requirementRepr);
14691471
if (auto typeRepr = storage.dyn_cast<const TypeRepr *>())
1470-
return RequirementSource::forExplicit(builder, type, typeRepr);
1471-
return RequirementSource::forAbstract(builder, type);
1472+
return RequirementSource::forExplicit(builder, depType, typeRepr);
1473+
return RequirementSource::forAbstract(builder, depType);
1474+
}
14721475

1473-
case Inferred:
1474-
return RequirementSource::forInferred(builder, type,
1476+
case Inferred: {
1477+
auto depType = type.getDependentType(builder);
1478+
return RequirementSource::forInferred(builder, depType,
14751479
storage.get<const TypeRepr *>());
1480+
}
14761481

14771482
case AbstractProtocol: {
1483+
auto depType = type.getDependentType();
1484+
14781485
// Derive the dependent type on which this requirement was written. It is
14791486
// the path from the requirement source on which this requirement is based
14801487
// to the potential archetype on which the requirement is being placed.
14811488
auto baseSource = storage.get<const RequirementSource *>();
14821489
auto baseSourceType = baseSource->getAffectedType();
14831490

14841491
auto dependentType =
1485-
formProtocolRelativeType(protocolReq.protocol, baseSourceType, type);
1492+
formProtocolRelativeType(protocolReq.protocol, baseSourceType, depType);
14861493

14871494
return storage.get<const RequirementSource *>()
14881495
->viaProtocolRequirement(builder, dependentType,
14891496
protocolReq.protocol, protocolReq.inferred,
14901497
protocolReq.written);
14911498
}
14921499

1493-
case NestedTypeNameMatch:
1494-
return RequirementSource::forNestedTypeNameMatch(builder, type);
1500+
case NestedTypeNameMatch: {
1501+
auto depType = type.getDependentType(builder);
1502+
return RequirementSource::forNestedTypeNameMatch(builder, depType);
1503+
}
14951504
}
14961505

14971506
llvm_unreachable("Unhandled FloatingPointRequirementSourceKind in switch.");
@@ -1712,8 +1721,7 @@ bool EquivalenceClass::recordConformanceConstraint(
17121721

17131722
// Record this conformance source.
17141723
known->second.push_back({type.getUnresolvedType(), proto,
1715-
source.getSource(builder,
1716-
type.getDependentType(builder))});
1724+
source.getSource(builder, type)});
17171725
++NumConformanceConstraints;
17181726

17191727
return inserted;
@@ -4131,8 +4139,7 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
41314139
if (!equivClass->recordConformanceConstraint(*this, type, proto, source))
41324140
return ConstraintResult::Resolved;
41334141

4134-
auto resolvedSource = source.getSource(*this,
4135-
type.getDependentType(*this));
4142+
auto resolvedSource = source.getSource(*this, type);
41364143
return expandConformanceRequirement(type, proto, resolvedSource,
41374144
/*onlySameTypeRequirements=*/false);
41384145
}
@@ -4159,7 +4166,7 @@ ConstraintResult GenericSignatureBuilder::addLayoutRequirementDirect(
41594166

41604167
// Record this layout constraint.
41614168
equivClass->layoutConstraints.push_back({type.getUnresolvedType(),
4162-
layout, source.getSource(*this, type.getDependentType(*this))});
4169+
layout, source.getSource(*this, type)});
41634170
equivClass->modified(*this);
41644171
++NumLayoutConstraints;
41654172
if (!anyChanges) ++NumLayoutConstraintsExtra;
@@ -4236,8 +4243,7 @@ bool GenericSignatureBuilder::updateSuperclass(
42364243
// Presence of a superclass constraint implies a _Class layout
42374244
// constraint.
42384245
auto layoutReqSource =
4239-
source.getSource(*this,
4240-
type.getDependentType(*this))->viaDerived(*this);
4246+
source.getSource(*this, type)->viaDerived(*this);
42414247
addLayoutRequirementDirect(type,
42424248
LayoutConstraint::getLayoutConstraint(
42434249
superclass->getClassOrBoundGenericClass()->isObjC()
@@ -4275,8 +4281,7 @@ ConstraintResult GenericSignatureBuilder::addSuperclassRequirementDirect(
42754281
ResolvedType type,
42764282
Type superclass,
42774283
FloatingRequirementSource source) {
4278-
auto resolvedSource =
4279-
source.getSource(*this, type.getDependentType(*this));
4284+
auto resolvedSource = source.getSource(*this, type);
42804285

42814286
// Record the constraint.
42824287
auto equivClass = type.getEquivalenceClass(*this);
@@ -4322,37 +4327,6 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
43224327
assert(constraintType && "No type to express resolved constraint?");
43234328
}
43244329

4325-
// Check whether we have a reasonable constraint type at all.
4326-
if (!constraintType->isExistentialType() &&
4327-
!constraintType->getClassOrBoundGenericClass()) {
4328-
if (source.getLoc().isValid() && !constraintType->hasError()) {
4329-
auto subjectType = subject.dyn_cast<Type>();
4330-
if (!subjectType)
4331-
subjectType = subject.get<PotentialArchetype *>()
4332-
->getDependentType(getGenericParams());
4333-
4334-
Impl->HadAnyError = true;
4335-
4336-
if (subjectType->is<DependentMemberType>()) {
4337-
subjectType = resolveDependentMemberTypes(*this, subjectType);
4338-
}
4339-
4340-
if (!subjectType->is<DependentMemberType>()) {
4341-
// If we end up here, it means either the subject type was never a
4342-
// a dependent member type, or it was initially a dependent member
4343-
// type, but resolving it lead to some other type. Let's map this
4344-
// to an error type so we can emit correct diagnostics.
4345-
subjectType = ErrorType::get(subjectType);
4346-
}
4347-
4348-
auto invalidConstraint = Constraint<Type>(
4349-
{subject, constraintType, source.getSource(*this, subjectType)});
4350-
invalidIsaConstraints.push_back(invalidConstraint);
4351-
}
4352-
4353-
return ConstraintResult::Conflicting;
4354-
}
4355-
43564330
// Resolve the subject. If we can't, delay the constraint.
43574331
auto resolvedSubject = resolve(subject, source);
43584332
if (!resolvedSubject) {
@@ -4392,7 +4366,7 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
43924366

43934367
// One cannot explicitly write a constraint on a concrete type.
43944368
if (source.isExplicit()) {
4395-
if (source.getLoc().isValid()) {
4369+
if (source.getLoc().isValid() && !subjectType->hasError()) {
43964370
Impl->HadAnyError = true;
43974371
Diags.diagnose(source.getLoc(), diag::requires_not_suitable_archetype,
43984372
subjectType);
@@ -4404,6 +4378,20 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
44044378
return ConstraintResult::Resolved;
44054379
}
44064380

4381+
// Check whether we have a reasonable constraint type at all.
4382+
if (!constraintType->isExistentialType() &&
4383+
!constraintType->getClassOrBoundGenericClass()) {
4384+
if (source.getLoc().isValid() && !constraintType->hasError()) {
4385+
Impl->HadAnyError = true;
4386+
4387+
auto invalidConstraint = Constraint<Type>(
4388+
{subject, constraintType, source.getSource(*this, resolvedSubject)});
4389+
invalidIsaConstraints.push_back(invalidConstraint);
4390+
}
4391+
4392+
return ConstraintResult::Conflicting;
4393+
}
4394+
44074395
// Protocol requirements.
44084396
if (constraintType->isExistentialType()) {
44094397
bool anyErrors = false;
@@ -4626,7 +4614,7 @@ GenericSignatureBuilder::addSameTypeRequirementBetweenTypeParameters(
46264614
const RequirementSource *source2;
46274615
if (auto existingSource2 =
46284616
equivClass2->findAnySuperclassConstraintAsWritten(
4629-
OrigT2->getDependentType(getGenericParams())))
4617+
OrigT2->getDependentType()))
46304618
source2 = existingSource2->source;
46314619
else
46324620
source2 = equivClass2->superclassConstraints.front().source;
@@ -4859,17 +4847,17 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementDirect(
48594847
// If one side is concrete, map the other side to that concrete type.
48604848
if (concreteType1) {
48614849
return addSameTypeRequirementToConcrete(type2, concreteType1,
4862-
source.getSource(*this, type2.getDependentType(*this)));
4850+
source.getSource(*this, type2));
48634851
}
48644852

48654853
if (concreteType2) {
48664854
return addSameTypeRequirementToConcrete(type1, concreteType2,
4867-
source.getSource(*this, type1.getDependentType(*this)));
4855+
source.getSource(*this, type1));
48684856
}
48694857

48704858
return addSameTypeRequirementBetweenTypeParameters(
48714859
type1, type2,
4872-
source.getSource(*this, type2.getDependentType(*this)));
4860+
source.getSource(*this, type2));
48734861
}
48744862

48754863
ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
@@ -6900,14 +6888,6 @@ namespace {
69006888

69016889
} // end anonymous namespace
69026890

6903-
static int compareSameTypeComponents(const SameTypeComponentRef *lhsPtr,
6904-
const SameTypeComponentRef *rhsPtr){
6905-
Type lhsType = lhsPtr->first->derivedSameTypeComponents[lhsPtr->second].type;
6906-
Type rhsType = rhsPtr->first->derivedSameTypeComponents[rhsPtr->second].type;
6907-
6908-
return compareDependentTypes(lhsType, rhsType);
6909-
}
6910-
69116891
void GenericSignatureBuilder::enumerateRequirements(
69126892
TypeArrayView<GenericTypeParamType> genericParams,
69136893
llvm::function_ref<
@@ -6926,10 +6906,6 @@ void GenericSignatureBuilder::enumerateRequirements(
69266906
subjects.push_back({&equivClass, i});
69276907
}
69286908

6929-
// Sort the subject types in canonical order.
6930-
llvm::array_pod_sort(subjects.begin(), subjects.end(),
6931-
compareSameTypeComponents);
6932-
69336909
for (const auto &subject : subjects) {
69346910
// Dig out the subject type and its corresponding component.
69356911
auto equivClass = subject.first;
@@ -7163,6 +7139,15 @@ static void collectRequirements(GenericSignatureBuilder &builder,
71637139

71647140
requirements.push_back(Requirement(kind, depTy, repTy));
71657141
});
7142+
7143+
// Sort the subject types in canonical order. This needs to be a stable sort
7144+
// so that the relative order of requirements that have the same subject type
7145+
// is preserved.
7146+
std::stable_sort(requirements.begin(), requirements.end(),
7147+
[](const Requirement &lhs, const Requirement &rhs) {
7148+
return compareDependentTypes(lhs.getFirstType(),
7149+
rhs.getFirstType()) < 0;
7150+
});
71667151
}
71677152

71687153
GenericSignature GenericSignatureBuilder::computeGenericSignature(

test/Generics/function_defs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ func badTypeConformance6<T>(_: T) where [T] : Collection { }
308308
// expected-error@-1{{type '[T]' in conformance requirement does not refer to a generic parameter or associated type}}
309309

310310
func badTypeConformance7<T, U>(_: T, _: U) where T? : U { }
311-
// expected-error@-1{{type 'T?' constrained to non-protocol, non-class type 'U'}}
311+
// expected-error@-1{{type 'T?' in conformance requirement does not refer to a generic parameter or associated type}}
312312

313313
func badSameType<T, U : GeneratesAnElement, V>(_ : T, _ : U)
314314
where T == U.Element, U.Element == V {} // expected-error{{same-type requirement makes generic parameters 'T' and 'V' equivalent}}

validation-test/compiler_crashers_2_fixed/0163-sr8033.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@ protocol P1 {
77
}
88
extension Foo: P1 where A : P1 {} // expected-error {{unsupported recursion for reference to associated type 'A' of type 'Foo<T>'}}
99
// expected-error@-1 {{type 'Foo<T>' does not conform to protocol 'P1'}}
10-
// expected-error@-2 {{type '<<error type>>' in conformance requirement does not refer to a generic parameter or associated type}}

0 commit comments

Comments
 (0)