Skip to content

Commit 41c6247

Browse files
authored
Merge pull request #7755 from DougGregor/all-same-type-to-concrete
2 parents b10bc8f + 29256e5 commit 41c6247

File tree

3 files changed

+246
-171
lines changed

3 files changed

+246
-171
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,19 @@ class GenericSignatureBuilder {
377377
using RequirementRHS =
378378
llvm::PointerUnion3<Type, PotentialArchetype *, LayoutConstraint>;
379379

380+
/// Describes an equivalence class of potential archetypes.
381+
struct EquivalenceClass {
382+
/// Concrete type to which this equivalence class is equal.
383+
Type concreteType;
384+
385+
/// The members of the equivalence class.
386+
TinyPtrVector<PotentialArchetype *> members;
387+
388+
/// Construct a new equivalence class containing only the given
389+
/// potential archetype (which represents itself).
390+
EquivalenceClass(PotentialArchetype *representative);
391+
};
392+
380393
friend class RequirementSource;
381394

382395
private:
@@ -690,8 +703,10 @@ class GenericSignatureBuilder::PotentialArchetype {
690703
} identifier;
691704

692705
/// \brief The representative of the equivalence class of potential archetypes
693-
/// to which this potential archetype belongs.
694-
mutable PotentialArchetype *Representative;
706+
/// to which this potential archetype belongs, or (for the representative)
707+
/// the equivalence class itself.
708+
mutable llvm::PointerUnion<PotentialArchetype *, EquivalenceClass *>
709+
representativeOrEquivClass;
695710

696711
/// Same-type constraints between this potential archetype and any other
697712
/// archetype in its equivalence class.
@@ -721,13 +736,15 @@ class GenericSignatureBuilder::PotentialArchetype {
721736
llvm::MapVector<Identifier, llvm::TinyPtrVector<PotentialArchetype *>>
722737
NestedTypes;
723738

724-
/// The concrete type to which a this potential archetype has been
739+
/// The concrete types to which this potential archetype has been
725740
/// constrained.
726-
Type ConcreteType;
741+
///
742+
/// This vector runs parallel to ConcreteTypeSources.
743+
llvm::TinyPtrVector<Type> concreteTypes;
727744

728-
/// The source of the concrete type requirement, if one was written
729-
/// on this potential archetype.
730-
const RequirementSource *ConcreteTypeSource = nullptr;
745+
/// The source of the concrete type requirements that were written on
746+
/// this potential archetype.
747+
llvm::TinyPtrVector<const RequirementSource *> concreteTypeSources;
731748

732749
/// Whether this is an unresolved nested type.
733750
unsigned isUnresolvedNestedType : 1;
@@ -754,63 +771,54 @@ class GenericSignatureBuilder::PotentialArchetype {
754771
/// the old name.
755772
Identifier OrigName;
756773

757-
/// The equivalence class of this potential archetype.
758-
llvm::TinyPtrVector<PotentialArchetype *> EquivalenceClass;
759-
760774
/// \brief Construct a new potential archetype for an unresolved
761775
/// associated type.
762776
PotentialArchetype(PotentialArchetype *parent, Identifier name)
763-
: parentOrBuilder(parent), identifier(name), Representative(this),
764-
isUnresolvedNestedType(true),
777+
: parentOrBuilder(parent), identifier(name), isUnresolvedNestedType(true),
765778
IsRecursive(false), Invalid(false),
766779
RecursiveConcreteType(false), RecursiveSuperclassType(false),
767780
DiagnosedRename(false)
768781
{
769782
assert(parent != nullptr && "Not an associated type?");
770-
EquivalenceClass.push_back(this);
771783
}
772784

773785
/// \brief Construct a new potential archetype for an associated type.
774786
PotentialArchetype(PotentialArchetype *parent, AssociatedTypeDecl *assocType)
775787
: parentOrBuilder(parent), identifier(assocType),
776-
Representative(this), isUnresolvedNestedType(false),
777-
IsRecursive(false), Invalid
778-
(false),
788+
isUnresolvedNestedType(false), IsRecursive(false), Invalid(false),
779789
RecursiveConcreteType(false),
780790
RecursiveSuperclassType(false), DiagnosedRename(false)
781791
{
782792
assert(parent != nullptr && "Not an associated type?");
783-
EquivalenceClass.push_back(this);
784793
}
785794

786795
/// \brief Construct a new potential archetype for a type alias.
787796
PotentialArchetype(PotentialArchetype *parent, TypeAliasDecl *typeAlias)
788797
: parentOrBuilder(parent), identifier(typeAlias),
789-
Representative(this), isUnresolvedNestedType(false),
798+
isUnresolvedNestedType(false),
790799
IsRecursive(false), Invalid(false),
791800
RecursiveConcreteType(false),
792801
RecursiveSuperclassType(false), DiagnosedRename(false)
793802
{
794803
assert(parent != nullptr && "Not an associated type?");
795-
EquivalenceClass.push_back(this);
796804
}
797805

798806
/// \brief Construct a new potential archetype for a generic parameter.
799807
PotentialArchetype(GenericSignatureBuilder *builder, GenericParamKey genericParam)
800808
: parentOrBuilder(builder), identifier(genericParam),
801-
Representative(this), isUnresolvedNestedType(false),
809+
isUnresolvedNestedType(false),
802810
IsRecursive(false), Invalid(false),
803811
RecursiveConcreteType(false), RecursiveSuperclassType(false),
804812
DiagnosedRename(false)
805813
{
806-
EquivalenceClass.push_back(this);
807814
}
808815

809816
/// \brief Retrieve the representative for this archetype, performing
810817
/// path compression on the way.
811818
PotentialArchetype *getRepresentative() const;
812819

813-
/// Retrieve the generic signature builder with which this archetype is associated.
820+
/// Retrieve the generic signature builder with which this archetype is
821+
/// associated.
814822
GenericSignatureBuilder *getBuilder() const {
815823
const PotentialArchetype *pa = this;
816824
while (auto parent = pa->getParent())
@@ -927,9 +935,24 @@ class GenericSignatureBuilder::PotentialArchetype {
927935
/// the number of associated type references.
928936
unsigned getNestingDepth() const;
929937

938+
/// Retrieve the equivalence class, if it's already present.
939+
///
940+
/// Otherwise, return null.
941+
EquivalenceClass *getEquivalenceClassIfPresent() const {
942+
return getRepresentative()->representativeOrEquivClass
943+
.dyn_cast<EquivalenceClass *>();
944+
}
945+
946+
/// Retrieve or create the equivalence class.
947+
EquivalenceClass *getOrCreateEquivalenceClass() const;
948+
930949
/// Retrieve the equivalence class containing this potential archetype.
931-
ArrayRef<PotentialArchetype *> getEquivalenceClass() {
932-
return getRepresentative()->EquivalenceClass;
950+
TinyPtrVector<PotentialArchetype *> getEquivalenceClassMembers() const {
951+
if (auto equivClass = getEquivalenceClassIfPresent())
952+
return equivClass->members;
953+
954+
return TinyPtrVector<PotentialArchetype *>(
955+
const_cast<PotentialArchetype *>(this));
933956
}
934957

935958
/// \brief Retrieve the potential archetype to be used as the anchor for
@@ -950,15 +973,21 @@ class GenericSignatureBuilder::PotentialArchetype {
950973
SameTypeConstraints.end());
951974
}
952975

953-
/// Retrieve the concrete type source as written on this potential archetype.
954-
const RequirementSource *getConcreteTypeSourceAsWritten() const {
955-
return ConcreteTypeSource;
976+
/// Retrieve the concrete types as written on this potential archetype.
977+
const llvm::TinyPtrVector<Type>& getConcreteTypesAsWritten() const {
978+
return concreteTypes;
979+
}
980+
981+
/// Retrieve the concrete type sources as written on this potential archetype.
982+
ArrayRef<const RequirementSource *> getConcreteTypeSourcesAsWritten() const {
983+
return concreteTypeSources;
956984
}
957985

958986
/// Find a source of the same-type constraint that maps this potential
959987
/// archetype to a concrete type somewhere in the equivalence class of this
960-
/// type.
961-
const RequirementSource *findAnyConcreteTypeSourceAsWritten() const;
988+
/// type along with the concrete type that was written there.
989+
Optional<std::pair<Type, const RequirementSource *>>
990+
findAnyConcreteTypeSourceAsWritten() const;
962991

963992
/// \brief Retrieve (or create) a nested type with the given name.
964993
PotentialArchetype *getNestedType(Identifier Name,
@@ -988,17 +1017,18 @@ class GenericSignatureBuilder::PotentialArchetype {
9881017
/// True if the potential archetype has been bound by a concrete type
9891018
/// constraint.
9901019
bool isConcreteType() const {
991-
if (Representative != this)
992-
return Representative->isConcreteType();
1020+
if (auto equivClass = getEquivalenceClassIfPresent())
1021+
return static_cast<bool>(equivClass->concreteType);
9931022

994-
return static_cast<bool>(ConcreteType);
1023+
return false;
9951024
}
9961025

9971026
/// Get the concrete type this potential archetype is constrained to.
9981027
Type getConcreteType() const {
999-
if (Representative != this)
1000-
return Representative->getConcreteType();
1001-
return ConcreteType;
1028+
if (auto equivClass = getEquivalenceClassIfPresent())
1029+
return equivClass->concreteType;
1030+
1031+
return Type();
10021032
}
10031033

10041034
void setIsRecursive() { IsRecursive = true; }

0 commit comments

Comments
 (0)