@@ -5252,6 +5252,30 @@ void DefaultWitnessChecker::recordWitness(
5252
5252
void TypeChecker::inferDefaultWitnesses (ProtocolDecl *proto) {
5253
5253
DefaultWitnessChecker checker (*this , proto);
5254
5254
5255
+ // Find the default for the given associated type.
5256
+ auto findAssociatedTypeDefault =
5257
+ [&](AssociatedTypeDecl *assocType,
5258
+ AssociatedTypeDecl **defaultedAssocTypeOut = nullptr ) -> Type {
5259
+ auto defaultedAssocType =
5260
+ AssociatedTypeInference::findDefaultedAssociatedType (*this , assocType);
5261
+ if (!defaultedAssocType)
5262
+ return nullptr ;;
5263
+
5264
+ Type defaultType = defaultedAssocType->getDefaultDefinitionLoc ().getType ();
5265
+ if (!defaultType)
5266
+ return nullptr ;
5267
+
5268
+ // Map out of its protocol context...
5269
+ defaultType = defaultType->mapTypeOutOfContext ();
5270
+ if (defaultType->hasError ())
5271
+ return nullptr ;
5272
+
5273
+ if (defaultedAssocTypeOut)
5274
+ *defaultedAssocTypeOut = defaultedAssocType;
5275
+
5276
+ return defaultType;
5277
+ };
5278
+
5255
5279
for (auto *requirement : proto->getMembers ()) {
5256
5280
if (requirement->isInvalid ())
5257
5281
continue ;
@@ -5262,19 +5286,8 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
5262
5286
5263
5287
if (auto assocType = dyn_cast<AssociatedTypeDecl>(valueDecl)) {
5264
5288
if (assocType->getOverriddenDecls ().empty ()) {
5265
- if (auto defaultedAssocType =
5266
- AssociatedTypeInference::findDefaultedAssociatedType (
5267
- *this , assocType)) {
5268
- Type defaultType =
5269
- defaultedAssocType->getDefaultDefinitionLoc ().getType ();
5270
-
5271
- // Map out of its protocol context...
5272
- defaultType = defaultType->mapTypeOutOfContext ();
5273
-
5274
- if (!defaultType->hasError ()) {
5275
- proto->setDefaultTypeWitness (assocType, defaultType);
5276
- }
5277
- }
5289
+ if (Type defaultType = findAssociatedTypeDefault (assocType))
5290
+ proto->setDefaultTypeWitness (assocType, defaultType);
5278
5291
}
5279
5292
5280
5293
continue ;
@@ -5288,6 +5301,78 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) {
5288
5301
5289
5302
checker.resolveWitnessViaLookup (valueDecl);
5290
5303
}
5304
+
5305
+ // Find defaults for any associated conformances rooted on defaulted
5306
+ // associated types.
5307
+ auto requirementSignature = proto->getRequirementSignature ();
5308
+ for (unsigned reqIndex : indices (requirementSignature)) {
5309
+ const auto &req = requirementSignature[reqIndex];
5310
+ if (req.getKind () != RequirementKind::Conformance)
5311
+ continue ;
5312
+ if (req.getFirstType ()->isEqual (proto->getProtocolSelfType ()))
5313
+ continue ;
5314
+
5315
+ // Find the innermost dependent member type (e.g., Self.AssocType), so
5316
+ // we can look at the associated type.
5317
+ auto depMemTy = req.getFirstType ()->getAs <DependentMemberType>();
5318
+ if (!depMemTy)
5319
+ continue ;
5320
+
5321
+ while (auto innerDepMemTy =
5322
+ depMemTy->getBase ()->getAs <DependentMemberType>())
5323
+ depMemTy = innerDepMemTy;
5324
+
5325
+ if (!depMemTy->getBase ()->isEqual (proto->getProtocolSelfType ()))
5326
+ continue ;
5327
+
5328
+ auto assocType = depMemTy->getAssocType ();
5329
+ if (!assocType)
5330
+ continue ;
5331
+
5332
+ // Find the associated type nearest our own protocol, which might have
5333
+ // a default not available in the associated type referenced by the
5334
+ // (canonicalized) requirement.
5335
+ if (assocType->getProtocol () != proto) {
5336
+ SmallVector<ValueDecl *, 2 > found;
5337
+ proto->getModuleContext ()->lookupQualified (
5338
+ proto, assocType->getFullName (),
5339
+ NL_QualifiedDefault|NL_ProtocolMembers|NL_OnlyTypes,
5340
+ found);
5341
+ if (found.size () == 1 && isa<AssociatedTypeDecl>(found[0 ]))
5342
+ assocType = cast<AssociatedTypeDecl>(found[0 ]);
5343
+ }
5344
+
5345
+ // Dig out the default associated type definition.
5346
+ AssociatedTypeDecl *defaultedAssocType = nullptr ;
5347
+ Type defaultAssocType = findAssociatedTypeDefault (assocType,
5348
+ &defaultedAssocType);
5349
+ if (!defaultAssocType)
5350
+ continue ;
5351
+
5352
+ Type defaultAssocTypeInContext =
5353
+ proto->mapTypeIntoContext (defaultAssocType);
5354
+ auto requirementProto =
5355
+ req.getSecondType ()->castTo <ProtocolType>()->getDecl ();
5356
+ auto conformance = conformsToProtocol (defaultAssocTypeInContext,
5357
+ requirementProto, proto,
5358
+ ConformanceCheckFlags::Used);
5359
+ if (!conformance) {
5360
+ // Diagnose the lack of a conformance. This is potentially an ABI
5361
+ // incompatibility.
5362
+ diagnose (proto, diag::assoc_type_default_conformance_failed,
5363
+ defaultAssocType, assocType->getFullName (), req.getFirstType (),
5364
+ req.getSecondType ());
5365
+ diagnose (defaultedAssocType, diag::assoc_type_default_here,
5366
+ assocType->getFullName (), defaultAssocType)
5367
+ .highlight (
5368
+ defaultedAssocType->getDefaultDefinitionLoc ().getSourceRange ());
5369
+
5370
+ continue ;
5371
+ }
5372
+
5373
+ // Record the default associated conformance.
5374
+ proto->setDefaultAssociatedConformanceWitness (reqIndex, *conformance);
5375
+ }
5291
5376
}
5292
5377
5293
5378
void TypeChecker::recordKnownWitness (NormalProtocolConformance *conformance,
0 commit comments