@@ -4281,8 +4281,25 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
4281
4281
ProtocolDecl *PD = attr->getProtocol (DC);
4282
4282
4283
4283
if (!PD) {
4284
- diagnose (attr->getLocation (), diag::implements_attr_non_protocol_type)
4285
- .highlight (attr->getProtocolTypeRepr ()->getSourceRange ());
4284
+ // `ImplementsAttr::getProtocol()` returns `nullptr` both when a type fails
4285
+ // to resolve, and when it resolves to something other than a protocol.
4286
+ // Due to layering concerns, it doesn't resolve in a way that emits
4287
+ // diagnostics.
4288
+ //
4289
+ // Distinguish between these situations by trying to resolve the type again.
4290
+ // If it doesn't resolve, TypeResolution will have diagnosed the problem; if
4291
+ // it does, it must have resolved to a non-protocol, so emit a diagnostic to
4292
+ // that effect.
4293
+ TypeResolutionOptions options (TypeResolverContext::None);
4294
+ auto resolvedType = TypeResolution::resolveContextualType (
4295
+ attr->getProtocolTypeRepr (), DC, options,
4296
+ // Unbound generics and placeholders are not allowed within this attr.
4297
+ /* unboundTyOpener*/ nullptr , /* placeholderHandler*/ nullptr ,
4298
+ /* packElementOpener*/ nullptr );
4299
+
4300
+ if (resolvedType && !resolvedType->hasError ())
4301
+ diagnose (attr->getLocation (), diag::implements_attr_non_protocol_type)
4302
+ .highlight (attr->getProtocolTypeRepr ()->getSourceRange ());
4286
4303
return ;
4287
4304
}
4288
4305
0 commit comments