@@ -44,6 +44,25 @@ STATISTIC(NumDuplicateSolutionStates,
44
44
45
45
using namespace swift ;
46
46
47
+ AbstractTypeWitness AbstractTypeWitness::forFixed (AssociatedTypeDecl *assocType,
48
+ Type type) {
49
+ return AbstractTypeWitness (AbstractTypeWitnessKind::Fixed, assocType, type,
50
+ nullptr );
51
+ }
52
+
53
+ AbstractTypeWitness
54
+ AbstractTypeWitness::forDefault (AssociatedTypeDecl *assocType, Type type,
55
+ AssociatedTypeDecl *defaultedAssocType) {
56
+ return AbstractTypeWitness (AbstractTypeWitnessKind::Default, assocType, type,
57
+ defaultedAssocType);
58
+ }
59
+
60
+ AbstractTypeWitness
61
+ AbstractTypeWitness::forGenericParam (AssociatedTypeDecl *assocType, Type type) {
62
+ return AbstractTypeWitness (AbstractTypeWitnessKind::GenericParam, assocType,
63
+ type, nullptr );
64
+ }
65
+
47
66
void InferredAssociatedTypesByWitness::dump () const {
48
67
dump (llvm::errs (), 0 );
49
68
}
@@ -798,7 +817,56 @@ AssociatedTypeDecl *AssociatedTypeInference::findDefaultedAssociatedType(
798
817
return results.size () == 1 ? results.front () : nullptr ;
799
818
}
800
819
801
- Optional<std::pair<AssociatedTypeDecl *, Type>>
820
+ Type AssociatedTypeInference::computeFixedTypeWitness (
821
+ AssociatedTypeDecl *assocType) {
822
+ Type resultType;
823
+
824
+ // Look at all of the inherited protocols to determine whether they
825
+ // require a fixed type for this associated type.
826
+ for (auto conformedProto : adoptee->getAnyNominal ()->getAllProtocols ()) {
827
+ if (conformedProto != assocType->getProtocol () &&
828
+ !conformedProto->inheritsFrom (assocType->getProtocol ()))
829
+ continue ;
830
+
831
+ auto sig = conformedProto->getGenericSignature ();
832
+
833
+ // FIXME: The RequirementMachine will assert on re-entrant construction.
834
+ // We should find a more principled way of breaking this cycle.
835
+ if (ctx.isRecursivelyConstructingRequirementMachine (sig.getCanonicalSignature ()) ||
836
+ ctx.isRecursivelyConstructingRequirementMachine (conformedProto) ||
837
+ conformedProto->isComputingRequirementSignature ())
838
+ continue ;
839
+
840
+ auto selfTy = conformedProto->getSelfInterfaceType ();
841
+ if (!sig->requiresProtocol (selfTy, assocType->getProtocol ()))
842
+ continue ;
843
+
844
+ auto structuralTy = DependentMemberType::get (selfTy, assocType->getName ());
845
+ const auto ty = sig.getCanonicalTypeInContext (structuralTy);
846
+
847
+ // A dependent member type with an identical base and name indicates that
848
+ // the protocol does not same-type constrain it in any way; move on to
849
+ // the next protocol.
850
+ if (auto *const memberTy = ty->getAs <DependentMemberType>()) {
851
+ if (memberTy->getBase ()->isEqual (selfTy) &&
852
+ memberTy->getName () == assocType->getName ())
853
+ continue ;
854
+ }
855
+
856
+ if (!resultType) {
857
+ resultType = ty;
858
+ continue ;
859
+ }
860
+
861
+ // FIXME: Bailing out on ambiguity.
862
+ if (!resultType->isEqual (ty))
863
+ return Type ();
864
+ }
865
+
866
+ return resultType;
867
+ }
868
+
869
+ Optional<AbstractTypeWitness>
802
870
AssociatedTypeInference::computeDefaultTypeWitness (
803
871
AssociatedTypeDecl *assocType) const {
804
872
// Go find a default definition.
@@ -814,7 +882,8 @@ AssociatedTypeInference::computeDefaultTypeWitness(
814
882
if (defaultType->hasError ())
815
883
return None;
816
884
817
- return std::make_pair (defaultedAssocType, defaultType);
885
+ return AbstractTypeWitness::forDefault (assocType, defaultType,
886
+ defaultedAssocType);
818
887
}
819
888
820
889
std::pair<Type, TypeDecl *>
@@ -845,6 +914,29 @@ AssociatedTypeInference::computeDerivedTypeWitness(
845
914
return result;
846
915
}
847
916
917
+ Optional<AbstractTypeWitness>
918
+ AssociatedTypeInference::computeAbstractTypeWitness (
919
+ AssociatedTypeDecl *assocType) {
920
+ // We don't have a type witness for this associated type, so go
921
+ // looking for more options.
922
+ if (Type concreteType = computeFixedTypeWitness (assocType))
923
+ return AbstractTypeWitness::forFixed (assocType, concreteType);
924
+
925
+ // If we can form a default type, do so.
926
+ if (const auto &typeWitness = computeDefaultTypeWitness (assocType))
927
+ return typeWitness;
928
+
929
+ // If there is a generic parameter of the named type, use that.
930
+ if (auto genericSig = dc->getGenericSignatureOfContext ()) {
931
+ for (auto gp : genericSig.getInnermostGenericParams ()) {
932
+ if (gp->getName () == assocType->getName ())
933
+ return AbstractTypeWitness::forGenericParam (assocType, gp);
934
+ }
935
+ }
936
+
937
+ return None;
938
+ }
939
+
848
940
void AssociatedTypeInference::collectAbstractTypeWitnesses (
849
941
TypeWitnessSystem &system,
850
942
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes) const {
@@ -878,8 +970,9 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
878
970
}
879
971
880
972
// If we find a default type definition, feed it to the system.
881
- if (const auto declAndType = computeDefaultTypeWitness (assocType)) {
882
- system.addDefaultTypeWitness (declAndType->second , declAndType->first );
973
+ if (const auto &typeWitness = computeDefaultTypeWitness (assocType)) {
974
+ system.addDefaultTypeWitness (typeWitness->getType (),
975
+ typeWitness->getDefaultedAssocType ());
883
976
} else {
884
977
// As a last resort, look for a generic parameter that matches the name
885
978
// of the associated type.
0 commit comments