@@ -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
382395private:
@@ -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