@@ -4281,8 +4281,25 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
42814281 ProtocolDecl *PD = attr->getProtocol (DC);
42824282
42834283 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 ());
42864303 return ;
42874304 }
42884305
0 commit comments