@@ -798,7 +798,56 @@ AssociatedTypeDecl *AssociatedTypeInference::findDefaultedAssociatedType(
798
798
return results.size () == 1 ? results.front () : nullptr ;
799
799
}
800
800
801
- Optional<std::pair<AssociatedTypeDecl *, Type>>
801
+ Type AssociatedTypeInference::computeFixedTypeWitness (
802
+ AssociatedTypeDecl *assocType) {
803
+ Type resultType;
804
+
805
+ // Look at all of the inherited protocols to determine whether they
806
+ // require a fixed type for this associated type.
807
+ for (auto conformedProto : adoptee->getAnyNominal ()->getAllProtocols ()) {
808
+ if (conformedProto != assocType->getProtocol () &&
809
+ !conformedProto->inheritsFrom (assocType->getProtocol ()))
810
+ continue ;
811
+
812
+ auto sig = conformedProto->getGenericSignature ();
813
+
814
+ // FIXME: The RequirementMachine will assert on re-entrant construction.
815
+ // We should find a more principled way of breaking this cycle.
816
+ if (ctx.isRecursivelyConstructingRequirementMachine (sig.getCanonicalSignature ()) ||
817
+ ctx.isRecursivelyConstructingRequirementMachine (conformedProto) ||
818
+ conformedProto->isComputingRequirementSignature ())
819
+ continue ;
820
+
821
+ auto selfTy = conformedProto->getSelfInterfaceType ();
822
+ if (!sig->requiresProtocol (selfTy, assocType->getProtocol ()))
823
+ continue ;
824
+
825
+ auto structuralTy = DependentMemberType::get (selfTy, assocType->getName ());
826
+ const auto ty = sig.getCanonicalTypeInContext (structuralTy);
827
+
828
+ // A dependent member type with an identical base and name indicates that
829
+ // the protocol does not same-type constrain it in any way; move on to
830
+ // the next protocol.
831
+ if (auto *const memberTy = ty->getAs <DependentMemberType>()) {
832
+ if (memberTy->getBase ()->isEqual (selfTy) &&
833
+ memberTy->getName () == assocType->getName ())
834
+ continue ;
835
+ }
836
+
837
+ if (!resultType) {
838
+ resultType = ty;
839
+ continue ;
840
+ }
841
+
842
+ // FIXME: Bailing out on ambiguity.
843
+ if (!resultType->isEqual (ty))
844
+ return Type ();
845
+ }
846
+
847
+ return resultType;
848
+ }
849
+
850
+ Optional<AbstractTypeWitness>
802
851
AssociatedTypeInference::computeDefaultTypeWitness (
803
852
AssociatedTypeDecl *assocType) const {
804
853
// Go find a default definition.
@@ -814,7 +863,7 @@ AssociatedTypeInference::computeDefaultTypeWitness(
814
863
if (defaultType->hasError ())
815
864
return None;
816
865
817
- return std::make_pair (defaultedAssocType , defaultType);
866
+ return AbstractTypeWitness (assocType , defaultType, defaultedAssocType );
818
867
}
819
868
820
869
std::pair<Type, TypeDecl *>
@@ -845,6 +894,29 @@ AssociatedTypeInference::computeDerivedTypeWitness(
845
894
return result;
846
895
}
847
896
897
+ Optional<AbstractTypeWitness>
898
+ AssociatedTypeInference::computeAbstractTypeWitness (
899
+ AssociatedTypeDecl *assocType) {
900
+ // We don't have a type witness for this associated type, so go
901
+ // looking for more options.
902
+ if (Type concreteType = computeFixedTypeWitness (assocType))
903
+ return AbstractTypeWitness (assocType, concreteType);
904
+
905
+ // If we can form a default type, do so.
906
+ if (const auto &typeWitness = computeDefaultTypeWitness (assocType))
907
+ return typeWitness;
908
+
909
+ // If there is a generic parameter of the named type, use that.
910
+ if (auto genericSig = dc->getGenericSignatureOfContext ()) {
911
+ for (auto gp : genericSig.getInnermostGenericParams ()) {
912
+ if (gp->getName () == assocType->getName ())
913
+ return AbstractTypeWitness (assocType, gp);
914
+ }
915
+ }
916
+
917
+ return None;
918
+ }
919
+
848
920
void AssociatedTypeInference::collectAbstractTypeWitnesses (
849
921
TypeWitnessSystem &system,
850
922
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes) const {
@@ -878,8 +950,9 @@ void AssociatedTypeInference::collectAbstractTypeWitnesses(
878
950
}
879
951
880
952
// 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 );
953
+ if (const auto &typeWitness = computeDefaultTypeWitness (assocType)) {
954
+ system.addDefaultTypeWitness (typeWitness->getType (),
955
+ typeWitness->getDefaultedAssocType ());
883
956
} else {
884
957
// As a last resort, look for a generic parameter that matches the name
885
958
// of the associated type.
@@ -1128,26 +1201,56 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
1128
1201
return nullptr ;
1129
1202
}
1130
1203
1131
- TypeWitnessSystem system (unresolvedAssocTypes);
1132
- collectAbstractTypeWitnesses (system, unresolvedAssocTypes);
1204
+ // Attempt to compute abstract type witnesses for associated types that could
1205
+ // not resolve otherwise.
1206
+ llvm::SmallVector<AbstractTypeWitness, 2 > abstractTypeWitnesses;
1133
1207
1134
- if (ctx.LangOpts .DumpTypeWitnessSystems ) {
1135
- system. dump ( llvm::dbgs (), conformance );
1136
- }
1208
+ if (ctx.LangOpts .EnableExperimentalAssociatedTypeInference ) {
1209
+ TypeWitnessSystem system (unresolvedAssocTypes );
1210
+ collectAbstractTypeWitnesses (system, unresolvedAssocTypes);
1137
1211
1138
- // If we couldn't resolve an associated type, bail out.
1139
- for (auto *assocType : unresolvedAssocTypes) {
1140
- if (!system.hasResolvedTypeWitness (assocType->getName ())) {
1141
- return assocType;
1212
+ if (ctx.LangOpts .DumpTypeWitnessSystems ) {
1213
+ system.dump (llvm::dbgs (), conformance);
1142
1214
}
1143
- }
1144
1215
1145
- // Record the tentative type witnesses to make them available during
1146
- // substitutions.
1147
- for (auto *assocType : unresolvedAssocTypes) {
1148
- typeWitnesses.insert (
1149
- assocType,
1150
- {system.getResolvedTypeWitness (assocType->getName ()), reqDepth});
1216
+ // If we couldn't resolve an associated type, bail out.
1217
+ for (auto *assocType : unresolvedAssocTypes) {
1218
+ if (!system.hasResolvedTypeWitness (assocType->getName ())) {
1219
+ return assocType;
1220
+ }
1221
+ }
1222
+
1223
+ // Record the tentative type witnesses to make them available during
1224
+ // substitutions.
1225
+ for (auto *assocType : unresolvedAssocTypes) {
1226
+ auto resolvedTy = system.getResolvedTypeWitness (assocType->getName ());
1227
+
1228
+ typeWitnesses.insert (assocType, {resolvedTy, reqDepth});
1229
+
1230
+ if (auto *defaultedAssocType =
1231
+ system.getDefaultedAssocType (assocType->getName ())) {
1232
+ abstractTypeWitnesses.emplace_back (assocType, resolvedTy,
1233
+ defaultedAssocType);
1234
+ } else {
1235
+ abstractTypeWitnesses.emplace_back (assocType, resolvedTy);
1236
+ }
1237
+ }
1238
+ } else {
1239
+ for (auto *const assocType : unresolvedAssocTypes) {
1240
+ // Try to compute the type without the aid of a specific potential
1241
+ // witness.
1242
+ if (const auto &typeWitness = computeAbstractTypeWitness (assocType)) {
1243
+ // Record the type witness immediately to make it available
1244
+ // for substitutions into other tentative type witnesses.
1245
+ typeWitnesses.insert (assocType, {typeWitness->getType (), reqDepth});
1246
+
1247
+ abstractTypeWitnesses.push_back (std::move (typeWitness.getValue ()));
1248
+ continue ;
1249
+ }
1250
+
1251
+ // The solution is incomplete.
1252
+ return assocType;
1253
+ }
1151
1254
}
1152
1255
1153
1256
// Check each abstract type witness against the generic requirements on the
@@ -1164,8 +1267,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
1164
1267
// associatedtype B: Sequence = Never
1165
1268
// }
1166
1269
const auto substOptions = getSubstOptionsWithCurrentTypeWitnesses ();
1167
- for (auto *const assocType : unresolvedAssocTypes) {
1168
- Type type = system.getResolvedTypeWitness (assocType->getName ());
1270
+ for (const auto &witness : abstractTypeWitnesses) {
1271
+ auto *const assocType = witness.getAssocType ();
1272
+ Type type = witness.getType ();
1273
+
1169
1274
// Replace type parameters with other known or tentative type witnesses.
1170
1275
if (type->hasTypeParameter ()) {
1171
1276
// FIXME: We should find a better way to detect and reason about these
@@ -1177,7 +1282,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
1177
1282
std::function<Type (Type)> substCurrentTypeWitnesses;
1178
1283
substCurrentTypeWitnesses = [&](Type ty) -> Type {
1179
1284
if (auto *gp = ty->getAs <GenericTypeParamType>()) {
1180
- if (isa<ProtocolDecl>(gp->getDecl ()->getDeclContext ()->getAsDecl ())) {
1285
+ // FIXME: 'computeFixedTypeWitness' uses 'getCanonicalTypeInContext',
1286
+ // so if a generic parameter is canonical here, it's 'Self'.
1287
+ if (gp->isCanonical () ||
1288
+ isa<ProtocolDecl>(gp->getDecl ()->getDeclContext ()->getAsDecl ())) {
1181
1289
return adoptee;
1182
1290
}
1183
1291
@@ -1282,8 +1390,7 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
1282
1390
checkTypeWitness (type, assocType, conformance, substOptions)) {
1283
1391
// We failed to satisfy a requirement. If this is a default type
1284
1392
// witness failure and we haven't seen one already, write it down.
1285
- auto *defaultedAssocType =
1286
- system.getDefaultedAssocType (assocType->getName ());
1393
+ auto *defaultedAssocType = witness.getDefaultedAssocType ();
1287
1394
if (defaultedAssocType && !failedDefaultedAssocType &&
1288
1395
!failed.isError ()) {
1289
1396
failedDefaultedAssocType = defaultedAssocType;
@@ -2187,7 +2294,7 @@ Type TypeWitnessSystem::getResolvedTypeWitness(Identifier name) const {
2187
2294
return Type ();
2188
2295
}
2189
2296
2190
- const AssociatedTypeDecl *
2297
+ AssociatedTypeDecl *
2191
2298
TypeWitnessSystem::getDefaultedAssocType (Identifier name) const {
2192
2299
assert (this ->TypeWitnesses .count (name));
2193
2300
@@ -2268,7 +2375,7 @@ void TypeWitnessSystem::addTypeWitness(Identifier name, Type type) {
2268
2375
}
2269
2376
2270
2377
void TypeWitnessSystem::addDefaultTypeWitness (
2271
- Type type, const AssociatedTypeDecl *defaultedAssocType) {
2378
+ Type type, AssociatedTypeDecl *defaultedAssocType) {
2272
2379
const auto name = defaultedAssocType->getName ();
2273
2380
assert (this ->TypeWitnesses .count (name));
2274
2381
0 commit comments