Skip to content

Commit 10b78bb

Browse files
authored
Merge pull request #11833 from DougGregor/gsb-resolve-equivalence-class
2 parents b32b0e5 + aa91e43 commit 10b78bb

File tree

5 files changed

+108
-80
lines changed

5 files changed

+108
-80
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,21 @@ class GenericSignatureBuilder {
679679
ArchetypeResolutionKind resolutionKind);
680680

681681
public:
682+
/// \brief Resolve the equivalence class for the given type parameter,
683+
/// which provides information about that type.
684+
///
685+
/// The \c resolutionKind parameter describes how resolution should be
686+
/// performed. If the potential archetype named by the given dependent type
687+
/// already exists, it will be always returned. If it doesn't exist yet,
688+
/// the \c resolutionKind dictates whether the potential archetype will
689+
/// be created or whether null will be returned.
690+
///
691+
/// For any type that cannot refer to an equivalence class, this routine
692+
/// returns null.
693+
EquivalenceClass *resolveEquivalenceClass(
694+
Type type,
695+
ArchetypeResolutionKind resolutionKind);
696+
682697
/// \brief Resolve the given type to the potential archetype it names.
683698
///
684699
/// The \c resolutionKind parameter describes how resolution should be

lib/AST/GenericSignature.cpp

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -484,31 +484,27 @@ bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
484484
if (!type->isTypeParameter()) return false;
485485

486486
auto &builder = *getGenericSignatureBuilder(mod);
487-
auto pa =
488-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
489-
if (!pa) return false;
490-
491-
if (pa->isConcreteType()) return false;
487+
auto equivClass =
488+
builder.resolveEquivalenceClass(
489+
type,
490+
ArchetypeResolutionKind::CompleteWellFormed);
491+
if (!equivClass) return false;
492492

493493
// If this type was mapped to a concrete type, then there is no
494494
// requirement.
495-
pa = pa->getRepresentative();
496-
497-
if (pa->isConcreteType()) return false;
495+
if (equivClass->concreteType) return false;
498496

499497
// If there is a layout constraint, it might be a class.
500-
if (auto layout = pa->getLayout()) {
501-
if (layout->isClass()) return true;
502-
}
498+
if (equivClass->layout && equivClass->layout->isClass()) return true;
503499

504500
// If there is a superclass bound, then obviously it must be a class.
505501
// FIXME: We shouldn't need this?
506-
if (pa->getSuperclass()) return true;
502+
if (equivClass->superclass) return true;
507503

508504
// If any of the protocols are class-bound, then it must be a class.
509505
// FIXME: We shouldn't need this?
510-
for (auto proto : pa->getConformsTo()) {
511-
if (proto->requiresClass()) return true;
506+
for (const auto &conforms : equivClass->conformsTo) {
507+
if (conforms.first->requiresClass()) return true;
512508
}
513509

514510
return false;
@@ -519,37 +515,41 @@ Type GenericSignature::getSuperclassBound(Type type, ModuleDecl &mod) {
519515
if (!type->isTypeParameter()) return nullptr;
520516

521517
auto &builder = *getGenericSignatureBuilder(mod);
522-
auto pa =
523-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
524-
if (!pa) return nullptr;
518+
auto equivClass =
519+
builder.resolveEquivalenceClass(
520+
type,
521+
ArchetypeResolutionKind::CompleteWellFormed);
522+
if (!equivClass) return nullptr;
525523

526524
// If this type was mapped to a concrete type, then there is no
527525
// requirement.
528-
if (pa->isConcreteType()) return nullptr;
526+
if (equivClass->concreteType) return nullptr;
529527

530528
// Retrieve the superclass bound.
531-
return pa->getSuperclass();
529+
return equivClass->superclass;
532530
}
533531

534532
/// Determine the set of protocols to which the given dependent type
535533
/// must conform.
536-
SmallVector<ProtocolDecl *, 2> GenericSignature::getConformsTo(Type type,
537-
ModuleDecl &mod) {
534+
SmallVector<ProtocolDecl *, 2>
535+
GenericSignature::getConformsTo(Type type, ModuleDecl &mod) {
538536
if (!type->isTypeParameter()) return { };
539537

540538
auto &builder = *getGenericSignatureBuilder(mod);
541-
auto pa =
542-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
543-
if (!pa) return { };
539+
auto equivClass =
540+
builder.resolveEquivalenceClass(
541+
type,
542+
ArchetypeResolutionKind::CompleteWellFormed);
543+
if (!equivClass) return { };
544544

545545
// If this type was mapped to a concrete type, then there are no
546546
// requirements.
547-
if (pa->isConcreteType()) return { };
547+
if (equivClass->concreteType) return { };
548548

549549
// Retrieve the protocols to which this type conforms.
550550
SmallVector<ProtocolDecl *, 2> result;
551-
for (auto proto : pa->getConformsTo())
552-
result.push_back(proto);
551+
for (const auto &conforms : equivClass->conformsTo)
552+
result.push_back(conforms.first);
553553

554554
// Canonicalize the resulting set of protocols.
555555
ProtocolType::canonicalizeProtocols(result);
@@ -563,19 +563,17 @@ bool GenericSignature::conformsToProtocol(Type type, ProtocolDecl *proto,
563563
if (!type->isTypeParameter()) return false;
564564

565565
auto &builder = *getGenericSignatureBuilder(mod);
566-
auto pa =
567-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
568-
if (!pa) return false;
566+
auto equivClass =
567+
builder.resolveEquivalenceClass(
568+
type,
569+
ArchetypeResolutionKind::CompleteWellFormed);
570+
if (!equivClass) return false;
569571

570572
// FIXME: Deal with concrete conformances here?
571-
if (pa->isConcreteType()) return false;
573+
if (equivClass->concreteType) return false;
572574

573575
// Check whether the representative conforms to this protocol.
574-
if (auto equivClass = pa->getEquivalenceClassIfPresent())
575-
if (equivClass->conformsTo.count(proto) > 0)
576-
return true;
577-
578-
return false;
576+
return equivClass->conformsTo.count(proto) > 0;
579577
}
580578

581579
/// Determine whether the given dependent type is equal to a concrete type.
@@ -590,23 +588,27 @@ Type GenericSignature::getConcreteType(Type type, ModuleDecl &mod) {
590588
if (!type->isTypeParameter()) return Type();
591589

592590
auto &builder = *getGenericSignatureBuilder(mod);
593-
auto pa =
594-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
595-
if (!pa) return Type();
591+
auto equivClass =
592+
builder.resolveEquivalenceClass(
593+
type,
594+
ArchetypeResolutionKind::CompleteWellFormed);
595+
if (!equivClass) return Type();
596596

597-
return pa->getConcreteType();
597+
return equivClass->concreteType;
598598
}
599599

600600
LayoutConstraint GenericSignature::getLayoutConstraint(Type type,
601601
ModuleDecl &mod) {
602602
if (!type->isTypeParameter()) return LayoutConstraint();
603603

604604
auto &builder = *getGenericSignatureBuilder(mod);
605-
auto pa =
606-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
607-
if (!pa) return LayoutConstraint();
605+
auto equivClass =
606+
builder.resolveEquivalenceClass(
607+
type,
608+
ArchetypeResolutionKind::CompleteWellFormed);
609+
if (!equivClass) return LayoutConstraint();
608610

609-
return pa->getLayout();
611+
return equivClass->layout;
610612
}
611613

612614
bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2,
@@ -618,21 +620,21 @@ bool GenericSignature::areSameTypeParameterInContext(Type type1, Type type2,
618620
return true;
619621

620622
auto &builder = *getGenericSignatureBuilder(mod);
621-
auto pa1 =
622-
builder.resolveArchetype(type1,
623+
auto equivClass1 =
624+
builder.resolveEquivalenceClass(
625+
type1,
623626
ArchetypeResolutionKind::CompleteWellFormed);
624-
assert(pa1 && "not a valid dependent type of this signature?");
625-
pa1 = pa1->getRepresentative();
626-
assert(!pa1->isConcreteType());
627+
assert(equivClass1 && "not a valid dependent type of this signature?");
628+
assert(!equivClass1->concreteType);
627629

628-
auto pa2 =
629-
builder.resolveArchetype(type2,
630+
auto equivClass2 =
631+
builder.resolveEquivalenceClass(
632+
type2,
630633
ArchetypeResolutionKind::CompleteWellFormed);
631-
assert(pa2 && "not a valid dependent type of this signature?");
632-
pa2 = pa2->getRepresentative();
633-
assert(!pa2->isConcreteType());
634+
assert(equivClass2 && "not a valid dependent type of this signature?");
635+
assert(!equivClass2->concreteType);
634636

635-
return pa1 == pa2;
637+
return equivClass1 == equivClass2;
636638
}
637639

638640
bool GenericSignature::isCanonicalTypeInContext(Type type, ModuleDecl &mod) {
@@ -772,9 +774,10 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
772774

773775
// Resolve this type to a potential archetype.
774776
auto &builder = *getGenericSignatureBuilder(mod);
775-
auto pa =
776-
builder.resolveArchetype(type, ArchetypeResolutionKind::CompleteWellFormed);
777-
auto equivClass = pa->getOrCreateEquivalenceClass();
777+
auto equivClass =
778+
builder.resolveEquivalenceClass(
779+
type,
780+
ArchetypeResolutionKind::CompleteWellFormed);
778781

779782
// Dig out the conformance of this type to the given protocol, because we
780783
// want its requirement source.
@@ -873,11 +876,10 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
873876
Type storedType = eraseAssociatedTypes(source->getStoredType());
874877

875878
// Dig out the potential archetype for this stored type.
876-
auto pa =
877-
inProtoSigBuilder.resolveArchetype(
879+
auto equivClass =
880+
inProtoSigBuilder.resolveEquivalenceClass(
878881
storedType,
879882
ArchetypeResolutionKind::CompleteWellFormed);
880-
auto equivClass = pa->getOrCreateEquivalenceClass();
881883

882884
// Find the conformance of this potential archetype to the protocol in
883885
// question.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,6 +2770,15 @@ auto GenericSignatureBuilder::resolvePotentialArchetype(
27702770
return (EquivalenceClass *)nullptr;
27712771
}
27722772

2773+
EquivalenceClass *GenericSignatureBuilder::resolveEquivalenceClass(
2774+
Type type,
2775+
ArchetypeResolutionKind resolutionKind) {
2776+
auto pa = resolveArchetype(type, resolutionKind);
2777+
if (!pa) return nullptr;
2778+
2779+
return pa->getOrCreateEquivalenceClass();
2780+
}
2781+
27732782
PotentialArchetype *GenericSignatureBuilder::resolveArchetype(
27742783
Type type,
27752784
ArchetypeResolutionKind resolutionKind) {

lib/AST/LookupVisibleDecls.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -564,26 +564,26 @@ static void lookupVisibleMemberDeclsImpl(
564564
// If we're looking into a type parameter and we have a generic signature
565565
// builder, use the GSB to resolve where we should look.
566566
if (BaseTy->isTypeParameter() && GSB) {
567-
auto PA = GSB->resolveArchetype(
568-
BaseTy,
569-
ArchetypeResolutionKind::CompleteWellFormed);
570-
if (!PA) return;
567+
auto EquivClass =
568+
GSB->resolveEquivalenceClass(BaseTy,
569+
ArchetypeResolutionKind::CompleteWellFormed);
570+
if (!EquivClass) return;
571571

572-
if (auto Concrete = PA->getConcreteType()) {
573-
BaseTy = Concrete;
572+
if (EquivClass->concreteType) {
573+
BaseTy = EquivClass->concreteType;
574574
} else {
575575
// Conformances
576-
for (auto Proto : PA->getConformsTo()) {
576+
for (const auto &Conforms : EquivClass->conformsTo) {
577577
lookupVisibleProtocolMemberDecls(
578-
BaseTy, Proto->getDeclaredType(), Consumer, CurrDC, LS,
579-
getReasonForSuper(Reason), TypeResolver, GSB, Visited);
578+
BaseTy, Conforms.first->getDeclaredType(), Consumer, CurrDC,
579+
LS, getReasonForSuper(Reason), TypeResolver, GSB, Visited);
580580
}
581581

582582
// Superclass.
583-
if (auto Superclass = PA->getSuperclass()) {
584-
lookupVisibleMemberDeclsImpl(Superclass, Consumer, CurrDC, LS,
585-
getReasonForSuper(Reason), TypeResolver,
586-
GSB, Visited);
583+
if (EquivClass->superclass) {
584+
lookupVisibleMemberDeclsImpl(EquivClass->superclass, Consumer, CurrDC,
585+
LS, getReasonForSuper(Reason),
586+
TypeResolver, GSB, Visited);
587587
}
588588
return;
589589
}

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,16 @@ bool CompleteGenericTypeResolver::areSameType(Type type1, Type type2) {
222222
if (!type1->hasTypeParameter() && !type2->hasTypeParameter())
223223
return type1->isEqual(type2);
224224

225-
auto pa1 =
226-
Builder.resolveArchetype(type1,
225+
auto equivClass1 =
226+
Builder.resolveEquivalenceClass(
227+
type1,
227228
ArchetypeResolutionKind::CompleteWellFormed);
228-
auto pa2 =
229-
Builder.resolveArchetype(type2,
229+
auto equivClass2 =
230+
Builder.resolveEquivalenceClass(
231+
type2,
230232
ArchetypeResolutionKind::CompleteWellFormed);
231-
if (pa1 && pa2)
232-
return pa1->isInSameEquivalenceClassAs(pa2);
233+
if (equivClass1 && equivClass2)
234+
return equivClass1 == equivClass2;
233235

234236
return type1->isEqual(type2);
235237
}

0 commit comments

Comments
 (0)