@@ -47,6 +47,8 @@ STATISTIC(NumDuplicateSolutionStates,
4747
4848using namespace swift ;
4949
50+ namespace {
51+
5052// / Describes the result of checking a type witness.
5153// /
5254// / This class evaluates true if an error occurred.
@@ -201,6 +203,8 @@ checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
201203 return CheckTypeWitnessResult::forSuccess ();
202204}
203205
206+ }
207+
204208static void recordTypeWitness (NormalProtocolConformance *conformance,
205209 AssociatedTypeDecl *assocType,
206210 Type type,
@@ -542,6 +546,8 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup(
542546 return ResolveWitnessResult::ExplicitFailed;
543547}
544548
549+ namespace {
550+
545551// / The set of associated types that have been inferred by matching
546552// / the given value witness to its corresponding requirement.
547553struct InferredAssociatedTypesByWitness {
@@ -561,6 +567,8 @@ struct InferredAssociatedTypesByWitness {
561567 SWIFT_DEBUG_DUMP;
562568};
563569
570+ }
571+
564572void InferredAssociatedTypesByWitness::dump () const {
565573 dump (llvm::errs (), 0 );
566574}
@@ -602,42 +610,42 @@ using InferredAssociatedTypes =
602610 SmallVector<std::pair<ValueDecl *, InferredAssociatedTypesByWitnesses>, 4 >;
603611
604612namespace {
605- void dumpInferredAssociatedTypesByWitnesses (
606- const InferredAssociatedTypesByWitnesses &inferred,
607- llvm::raw_ostream &out ,
608- unsigned indent) {
609- for ( const auto &value : inferred ) {
610- value. dump (out, indent);
611- }
613+
614+ void dumpInferredAssociatedTypesByWitnesses (
615+ const InferredAssociatedTypesByWitnesses &inferred ,
616+ llvm::raw_ostream &out,
617+ unsigned indent ) {
618+ for ( const auto & value : inferred) {
619+ value. dump (out, indent);
612620 }
621+ }
613622
614- void dumpInferredAssociatedTypesByWitnesses (
615- const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
623+ void dumpInferredAssociatedTypesByWitnesses (
624+ const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
616625
617- void dumpInferredAssociatedTypesByWitnesses (
618- const InferredAssociatedTypesByWitnesses &inferred) {
619- dumpInferredAssociatedTypesByWitnesses (inferred, llvm::errs (), 0 );
620- }
626+ void dumpInferredAssociatedTypesByWitnesses (
627+ const InferredAssociatedTypesByWitnesses &inferred) {
628+ dumpInferredAssociatedTypesByWitnesses (inferred, llvm::errs (), 0 );
629+ }
621630
622- void dumpInferredAssociatedTypes (const InferredAssociatedTypes &inferred,
623- llvm::raw_ostream &out,
624- unsigned indent) {
625- for (const auto &value : inferred) {
626- out << " \n " ;
627- out.indent (indent) << " (" ;
628- value.first ->dumpRef (out);
629- dumpInferredAssociatedTypesByWitnesses (value.second , out, indent + 2 );
630- out << " )" ;
631- }
631+ void dumpInferredAssociatedTypes (const InferredAssociatedTypes &inferred,
632+ llvm::raw_ostream &out,
633+ unsigned indent) {
634+ for (const auto &value : inferred) {
632635 out << " \n " ;
636+ out.indent (indent) << " (" ;
637+ value.first ->dumpRef (out);
638+ dumpInferredAssociatedTypesByWitnesses (value.second , out, indent + 2 );
639+ out << " )" ;
633640 }
641+ out << " \n " ;
642+ }
634643
635- void dumpInferredAssociatedTypes (
636- const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
644+ void dumpInferredAssociatedTypes (
645+ const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
637646
638- void dumpInferredAssociatedTypes (const InferredAssociatedTypes &inferred) {
639- dumpInferredAssociatedTypes (inferred, llvm::errs (), 0 );
640- }
647+ void dumpInferredAssociatedTypes (const InferredAssociatedTypes &inferred) {
648+ dumpInferredAssociatedTypes (inferred, llvm::errs (), 0 );
641649}
642650
643651// / A conflict between two inferred type witnesses for the same
@@ -739,8 +747,137 @@ void InferredTypeWitnessesSolution::dump() const {
739747 }
740748}
741749
750+ // / A system for recording and probing the integrity of a type witness solution
751+ // / for a set of unresolved associated type declarations.
752+ // /
753+ // / Right now can reason only about abstract type witnesses, i.e., same-type
754+ // / constraints, default type definitions, and bindings to generic parameters.
755+ class TypeWitnessSystem final {
756+ // / Equivalence classes are used on demand to express equivalences between
757+ // / witness candidates and reflect changes to resolved types across their
758+ // / members.
759+ class EquivalenceClass final {
760+ // / The pointer:
761+ // / - The resolved type for witness candidates belonging to this equivalence
762+ // / class. The resolved type may be a type parameter, but cannot directly
763+ // / pertain to a name variable in the owning system; instead, witness
764+ // / candidates that should resolve to the same type share an equivalence
765+ // / class.
766+ // / The int:
767+ // / - A flag indicating whether the resolved type is ambiguous. When set,
768+ // / the resolved type is null.
769+ llvm::PointerIntPair<Type, 1 , bool > ResolvedTyAndIsAmbiguous;
770+
771+ public:
772+ EquivalenceClass (Type ty) : ResolvedTyAndIsAmbiguous(ty, false ) {}
773+
774+ EquivalenceClass (const EquivalenceClass &) = delete ;
775+ EquivalenceClass (EquivalenceClass &&) = delete ;
776+ EquivalenceClass &operator =(const EquivalenceClass &) = delete ;
777+ EquivalenceClass &operator =(EquivalenceClass &&) = delete ;
778+
779+ Type getResolvedType () const {
780+ return ResolvedTyAndIsAmbiguous.getPointer ();
781+ }
782+ void setResolvedType (Type ty);
783+
784+ bool isAmbiguous () const {
785+ return ResolvedTyAndIsAmbiguous.getInt ();
786+ }
787+ void setAmbiguous () {
788+ ResolvedTyAndIsAmbiguous = {nullptr , true };
789+ }
790+ };
791+
792+ // / A type witness candidate for a name variable.
793+ struct TypeWitnessCandidate final {
794+ // / The defaulted associated type declaration correlating with this
795+ // / candidate, if present.
796+ AssociatedTypeDecl *DefaultedAssocType;
797+
798+ // / The equivalence class of this candidate.
799+ EquivalenceClass *EquivClass;
800+ };
801+
802+ // / The set of equivalence classes in the system.
803+ llvm::SmallPtrSet<EquivalenceClass *, 4 > EquivalenceClasses;
804+
805+ // / The mapping from name variables (the names of unresolved associated
806+ // / type declarations) to their corresponding type witness candidates.
807+ llvm::SmallDenseMap<Identifier, TypeWitnessCandidate, 4 > TypeWitnesses;
808+
809+ public:
810+ TypeWitnessSystem (ArrayRef<AssociatedTypeDecl *> assocTypes);
811+ ~TypeWitnessSystem ();
812+
813+ TypeWitnessSystem (const TypeWitnessSystem &) = delete ;
814+ TypeWitnessSystem (TypeWitnessSystem &&) = delete ;
815+ TypeWitnessSystem &operator =(const TypeWitnessSystem &) = delete ;
816+ TypeWitnessSystem &operator =(TypeWitnessSystem &&) = delete ;
817+
818+ // / Get the resolved type witness for the associated type with the given name.
819+ Type getResolvedTypeWitness (Identifier name) const ;
820+ bool hasResolvedTypeWitness (Identifier name) const ;
821+
822+ // / Get the defaulted associated type relating to the resolved type witness
823+ // / for the associated type with the given name, if present.
824+ AssociatedTypeDecl *getDefaultedAssocType (Identifier name) const ;
825+
826+ // / Record a type witness for the given associated type name.
827+ // /
828+ // / \note This need not lead to the resolution of a type witness, e.g.
829+ // / an associated type may be defaulted to another.
830+ void addTypeWitness (Identifier name, Type type);
831+
832+ // / Record a default type witness.
833+ // /
834+ // / \param defaultedAssocType The specific associated type declaration that
835+ // / defines the given default type.
836+ // /
837+ // / \note This need not lead to the resolution of a type witness.
838+ void addDefaultTypeWitness (Type type, AssociatedTypeDecl *defaultedAssocType);
839+
840+ // / Record the given same-type requirement, if regarded of interest to
841+ // / the system.
842+ // /
843+ // / \note This need not lead to the resolution of a type witness.
844+ void addSameTypeRequirement (const Requirement &req);
845+
846+ void dump (llvm::raw_ostream &out,
847+ const NormalProtocolConformance *conformance) const ;
848+
849+ private:
850+ // / Form an equivalence between the given name variables.
851+ void addEquivalence (Identifier name1, Identifier name2);
852+
853+ // / Merge \p equivClass2 into \p equivClass1.
854+ // /
855+ // / \note This will delete \p equivClass2 after migrating its members to
856+ // / \p equivClass1.
857+ void mergeEquivalenceClasses (EquivalenceClass *equivClass1,
858+ const EquivalenceClass *equivClass2);
859+
860+ // / The result of comparing two resolved types targeting a single equivalence
861+ // / class, in terms of their relative impact on solving the system.
862+ enum class ResolvedTypeComparisonResult {
863+ // / The first resolved type is a better choice than the second one.
864+ Better,
865+
866+ // / The first resolved type is an equivalent or worse choice than the
867+ // / second one.
868+ EquivalentOrWorse,
869+
870+ // / Both resolved types are concrete and mutually exclusive.
871+ Ambiguity
872+ };
873+
874+ // / Compare the given resolved types as targeting a single equivalence class,
875+ // / in terms of the their relative impact on solving the system.
876+ static ResolvedTypeComparisonResult compareResolvedTypes (Type ty1, Type ty2);
877+ };
878+
742879// / Captures the state needed to infer associated types.
743- class swift :: AssociatedTypeInference {
880+ class AssociatedTypeInference {
744881 // / The type checker we'll need to validate declarations etc.
745882 ASTContext &ctx;
746883
@@ -929,6 +1066,8 @@ class swift::AssociatedTypeInference {
9291066 llvm::Optional<InferredTypeWitnesses> solve (ConformanceChecker &checker);
9301067};
9311068
1069+ }
1070+
9321071AssociatedTypeInference::AssociatedTypeInference (
9331072 ASTContext &ctx, NormalProtocolConformance *conformance)
9341073 : ctx(ctx), conformance(conformance), proto(conformance->getProtocol ()),
@@ -1622,8 +1761,8 @@ Type swift::adjustInferredAssociatedType(TypeAdjustment adjustment, Type type,
16221761 return type;
16231762}
16241763
1625- AssociatedTypeDecl *
1626- swift:: getReferencedAssocTypeOfProtocol (Type type, ProtocolDecl *proto) {
1764+ static AssociatedTypeDecl *
1765+ getReferencedAssocTypeOfProtocol (Type type, ProtocolDecl *proto) {
16271766 if (auto dependentMember = type->getAs <DependentMemberType>()) {
16281767 if (auto assocType = dependentMember->getAssocType ()) {
16291768 if (dependentMember->getBase ()->isEqual (proto->getSelfInterfaceType ())) {
@@ -1865,10 +2004,10 @@ AssociatedTypeInference::computeDefaultTypeWitness(
18652004 return AbstractTypeWitness (assocType, defaultType, defaultedAssocType);
18662005}
18672006
1868- std::pair<Type, TypeDecl *>
1869- TypeChecker:: deriveTypeWitness (DeclContext *DC,
1870- NominalTypeDecl *TypeDecl,
1871- AssociatedTypeDecl *AssocType) {
2007+ static std::pair<Type, TypeDecl *>
2008+ deriveTypeWitness (DeclContext *DC,
2009+ NominalTypeDecl *TypeDecl,
2010+ AssociatedTypeDecl *AssocType) {
18722011 auto *protocol = cast<ProtocolDecl>(AssocType->getDeclContext ());
18732012
18742013 auto knownKind = protocol->getKnownProtocolKind ();
@@ -1913,7 +2052,7 @@ AssociatedTypeInference::computeDerivedTypeWitness(
19132052 return std::make_pair (Type (), nullptr );
19142053
19152054 // Try to derive the type witness.
1916- auto result = TypeChecker:: deriveTypeWitness (dc, derivingTypeDecl, assocType);
2055+ auto result = deriveTypeWitness (dc, derivingTypeDecl, assocType);
19172056 if (!result.first )
19182057 return std::make_pair (Type (), nullptr );
19192058
0 commit comments