@@ -4011,17 +4011,21 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
4011
4011
// Retrieve the requirement that a given typealias introduces when it
4012
4012
// overrides an inherited associated type with the same name, as a string
4013
4013
// suitable for use in a where clause.
4014
- auto getTypeAliasReq = [&](TypeAliasDecl *typealias , const char *start) {
4014
+ auto getConcreteTypeReq = [&](TypeDecl *type , const char *start) {
4015
4015
std::string result;
4016
4016
{
4017
4017
llvm::raw_string_ostream out (result);
4018
4018
out << start;
4019
- out << typealias->getFullName () << " == " ;
4020
- if (auto underlyingTypeRepr =
4021
- typealias->getUnderlyingTypeLoc ().getTypeRepr ())
4022
- underlyingTypeRepr->print (out);
4023
- else
4024
- typealias->getUnderlyingTypeLoc ().getType ().print (out);
4019
+ out << type->getFullName () << " == " ;
4020
+ if (auto typealias = dyn_cast<TypeAliasDecl>(type)) {
4021
+ if (auto underlyingTypeRepr =
4022
+ typealias->getUnderlyingTypeLoc ().getTypeRepr ())
4023
+ underlyingTypeRepr->print (out);
4024
+ else
4025
+ typealias->getUnderlyingTypeLoc ().getType ().print (out);
4026
+ } else {
4027
+ type->print (out);
4028
+ }
4025
4029
}
4026
4030
return result;
4027
4031
};
@@ -4151,51 +4155,68 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
4151
4155
inheritedTypeDecls.erase (knownInherited);
4152
4156
continue ;
4153
4157
}
4158
+ }
4154
4159
4155
- if (auto typealias = dyn_cast<TypeAliasDecl>(Member)) {
4156
- // Check whether we inherited any types with the same name.
4157
- auto knownInherited = inheritedTypeDecls.find (typealias->getFullName ());
4158
- if (knownInherited == inheritedTypeDecls.end ()) continue ;
4160
+ // Check all remaining inherited type declarations to determine if
4161
+ // this protocol has a non-associated-type type with the same name.
4162
+ inheritedTypeDecls.remove_if (
4163
+ [&](const std::pair<DeclName, TinyPtrVector<TypeDecl *>> &inherited) {
4164
+ auto name = inherited.first ;
4165
+ for (auto found : proto->lookupDirect (name)) {
4166
+ // We only want concrete type declarations.
4167
+ auto type = dyn_cast<TypeDecl>(found);
4168
+ if (!type || isa<AssociatedTypeDecl>(type)) continue ;
4159
4169
4160
- bool shouldWarnAboutRedeclaration =
4161
- source-> kind == RequirementSource::RequirementSignatureSelf ;
4170
+ // ... from the same module as the protocol.
4171
+ if (type-> getModuleContext () != proto-> getModuleContext ()) continue ;
4162
4172
4163
- for (auto inheritedType : knownInherited->second ) {
4164
- // If we have inherited associated type...
4165
- if (auto inheritedAssocTypeDecl =
4166
- dyn_cast<AssociatedTypeDecl>(inheritedType)) {
4167
- // Infer a same-type requirement between the typealias' underlying
4168
- // type and the inherited associated type.
4169
- addInferredSameTypeReq (inheritedAssocTypeDecl, typealias);
4173
+ // Or is constrained.
4174
+ if (auto ext = dyn_cast<ExtensionDecl>(type->getDeclContext ())) {
4175
+ if (ext->isConstrainedExtension ()) continue ;
4176
+ }
4170
4177
4171
- // Warn that one should use where clauses for this.
4172
- if (shouldWarnAboutRedeclaration) {
4173
- auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol ();
4174
- auto fixItWhere = getProtocolWhereLoc ();
4175
- Diags.diagnose (typealias,
4176
- diag::typealias_override_associated_type,
4177
- typealias->getFullName (),
4178
- inheritedFromProto->getDeclaredInterfaceType ())
4179
- .fixItInsertAfter (fixItWhere.first ,
4180
- getTypeAliasReq (typealias, fixItWhere.second ))
4181
- .fixItRemove (typealias->getSourceRange ());
4182
- Diags.diagnose (inheritedAssocTypeDecl, diag::decl_declared_here,
4183
- inheritedAssocTypeDecl->getFullName ());
4178
+ // We found something.
4179
+ bool shouldWarnAboutRedeclaration =
4180
+ source->kind == RequirementSource::RequirementSignatureSelf;
4181
+
4182
+ for (auto inheritedType : inherited.second ) {
4183
+ // If we have inherited associated type...
4184
+ if (auto inheritedAssocTypeDecl =
4185
+ dyn_cast<AssociatedTypeDecl>(inheritedType)) {
4186
+ // Infer a same-type requirement between the typealias' underlying
4187
+ // type and the inherited associated type.
4188
+ addInferredSameTypeReq (inheritedAssocTypeDecl, type);
4189
+
4190
+ // Warn that one should use where clauses for this.
4191
+ if (shouldWarnAboutRedeclaration) {
4192
+ auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol ();
4193
+ auto fixItWhere = getProtocolWhereLoc ();
4194
+ Diags.diagnose (type,
4195
+ diag::typealias_override_associated_type,
4196
+ name,
4197
+ inheritedFromProto->getDeclaredInterfaceType ())
4198
+ .fixItInsertAfter (fixItWhere.first ,
4199
+ getConcreteTypeReq (type, fixItWhere.second ))
4200
+ .fixItRemove (type->getSourceRange ());
4201
+ Diags.diagnose (inheritedAssocTypeDecl, diag::decl_declared_here,
4202
+ inheritedAssocTypeDecl->getFullName ());
4203
+
4204
+ shouldWarnAboutRedeclaration = false ;
4205
+ }
4184
4206
4185
- shouldWarnAboutRedeclaration = false ;
4207
+ continue ;
4186
4208
}
4187
4209
4188
- continue ;
4210
+ // Two typealiases that should be the same.
4211
+ addInferredSameTypeReq (inheritedType, type);
4189
4212
}
4190
4213
4191
- // Two typealiases that should be the same .
4192
- addInferredSameTypeReq (inheritedType, typealias) ;
4214
+ // We can remove this entry .
4215
+ return true ;
4193
4216
}
4194
4217
4195
- inheritedTypeDecls.erase (knownInherited);
4196
- continue ;
4197
- }
4198
- }
4218
+ return false ;
4219
+ });
4199
4220
4200
4221
// Infer same-type requirements among inherited type declarations.
4201
4222
for (auto &entry : inheritedTypeDecls) {
0 commit comments