@@ -3326,17 +3326,21 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
3326
3326
// Retrieve the requirement that a given typealias introduces when it
3327
3327
// overrides an inherited associated type with the same name, as a string
3328
3328
// suitable for use in a where clause.
3329
- auto getTypeAliasReq = [&](TypeAliasDecl *typealias , const char *start) {
3329
+ auto getConcreteTypeReq = [&](TypeDecl *type , const char *start) {
3330
3330
std::string result;
3331
3331
{
3332
3332
llvm::raw_string_ostream out (result);
3333
3333
out << start;
3334
- out << typealias->getFullName () << " == " ;
3335
- if (auto underlyingTypeRepr =
3336
- typealias->getUnderlyingTypeLoc ().getTypeRepr ())
3337
- underlyingTypeRepr->print (out);
3338
- else
3339
- typealias->getUnderlyingTypeLoc ().getType ().print (out);
3334
+ out << type->getFullName () << " == " ;
3335
+ if (auto typealias = dyn_cast<TypeAliasDecl>(type)) {
3336
+ if (auto underlyingTypeRepr =
3337
+ typealias->getUnderlyingTypeLoc ().getTypeRepr ())
3338
+ underlyingTypeRepr->print (out);
3339
+ else
3340
+ typealias->getUnderlyingTypeLoc ().getType ().print (out);
3341
+ } else {
3342
+ type->print (out);
3343
+ }
3340
3344
}
3341
3345
return result;
3342
3346
};
@@ -3466,51 +3470,68 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
3466
3470
inheritedTypeDecls.erase (knownInherited);
3467
3471
continue ;
3468
3472
}
3473
+ }
3469
3474
3470
- if (auto typealias = dyn_cast<TypeAliasDecl>(Member)) {
3471
- // Check whether we inherited any types with the same name.
3472
- auto knownInherited = inheritedTypeDecls.find (typealias->getFullName ());
3473
- if (knownInherited == inheritedTypeDecls.end ()) continue ;
3475
+ // Check all remaining inherited type declarations to determine if
3476
+ // this protocol has a non-associated-type type with the same name.
3477
+ inheritedTypeDecls.remove_if (
3478
+ [&](const std::pair<DeclName, TinyPtrVector<TypeDecl *>> &inherited) {
3479
+ auto name = inherited.first ;
3480
+ for (auto found : proto->lookupDirect (name)) {
3481
+ // We only want concrete type declarations.
3482
+ auto type = dyn_cast<TypeDecl>(found);
3483
+ if (!type || isa<AssociatedTypeDecl>(type)) continue ;
3474
3484
3475
- bool shouldWarnAboutRedeclaration =
3476
- source-> kind == RequirementSource::RequirementSignatureSelf ;
3485
+ // ... from the same module as the protocol.
3486
+ if (type-> getModuleContext () != proto-> getModuleContext ()) continue ;
3477
3487
3478
- for (auto inheritedType : knownInherited->second ) {
3479
- // If we have inherited associated type...
3480
- if (auto inheritedAssocTypeDecl =
3481
- dyn_cast<AssociatedTypeDecl>(inheritedType)) {
3482
- // Infer a same-type requirement between the typealias' underlying
3483
- // type and the inherited associated type.
3484
- addInferredSameTypeReq (inheritedAssocTypeDecl, typealias);
3488
+ // Or is constrained.
3489
+ if (auto ext = dyn_cast<ExtensionDecl>(type->getDeclContext ())) {
3490
+ if (ext->isConstrainedExtension ()) continue ;
3491
+ }
3485
3492
3486
- // Warn that one should use where clauses for this.
3487
- if (shouldWarnAboutRedeclaration) {
3488
- auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol ();
3489
- auto fixItWhere = getProtocolWhereLoc ();
3490
- Diags.diagnose (typealias,
3491
- diag::typealias_override_associated_type,
3492
- typealias->getFullName (),
3493
- inheritedFromProto->getDeclaredInterfaceType ())
3494
- .fixItInsertAfter (fixItWhere.first ,
3495
- getTypeAliasReq (typealias, fixItWhere.second ))
3496
- .fixItRemove (typealias->getSourceRange ());
3497
- Diags.diagnose (inheritedAssocTypeDecl, diag::decl_declared_here,
3498
- inheritedAssocTypeDecl->getFullName ());
3493
+ // We found something.
3494
+ bool shouldWarnAboutRedeclaration =
3495
+ source->kind == RequirementSource::RequirementSignatureSelf;
3496
+
3497
+ for (auto inheritedType : inherited.second ) {
3498
+ // If we have inherited associated type...
3499
+ if (auto inheritedAssocTypeDecl =
3500
+ dyn_cast<AssociatedTypeDecl>(inheritedType)) {
3501
+ // Infer a same-type requirement between the typealias' underlying
3502
+ // type and the inherited associated type.
3503
+ addInferredSameTypeReq (inheritedAssocTypeDecl, type);
3504
+
3505
+ // Warn that one should use where clauses for this.
3506
+ if (shouldWarnAboutRedeclaration) {
3507
+ auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol ();
3508
+ auto fixItWhere = getProtocolWhereLoc ();
3509
+ Diags.diagnose (type,
3510
+ diag::typealias_override_associated_type,
3511
+ name,
3512
+ inheritedFromProto->getDeclaredInterfaceType ())
3513
+ .fixItInsertAfter (fixItWhere.first ,
3514
+ getConcreteTypeReq (type, fixItWhere.second ))
3515
+ .fixItRemove (type->getSourceRange ());
3516
+ Diags.diagnose (inheritedAssocTypeDecl, diag::decl_declared_here,
3517
+ inheritedAssocTypeDecl->getFullName ());
3518
+
3519
+ shouldWarnAboutRedeclaration = false ;
3520
+ }
3499
3521
3500
- shouldWarnAboutRedeclaration = false ;
3522
+ continue ;
3501
3523
}
3502
3524
3503
- continue ;
3525
+ // Two typealiases that should be the same.
3526
+ addInferredSameTypeReq (inheritedType, type);
3504
3527
}
3505
3528
3506
- // Two typealiases that should be the same .
3507
- addInferredSameTypeReq (inheritedType, typealias) ;
3529
+ // We can remove this entry .
3530
+ return true ;
3508
3531
}
3509
3532
3510
- inheritedTypeDecls.erase (knownInherited);
3511
- continue ;
3512
- }
3513
- }
3533
+ return false ;
3534
+ });
3514
3535
3515
3536
// Infer same-type requirements among inherited type declarations.
3516
3537
for (auto &entry : inheritedTypeDecls) {
0 commit comments