mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Fix @_implements type resolution diagnostics
If a type in an `@_implements` attribute failed to resolve, Sema would assume it was because the type existed but wasn’t a protocol, even if there was another reason for the problem (such as the type not existing). Explicitly resolve the TypeRepr again through a path that will produce diagnostics.
This commit is contained in:
@@ -4281,8 +4281,25 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
|
||||
ProtocolDecl *PD = attr->getProtocol(DC);
|
||||
|
||||
if (!PD) {
|
||||
diagnose(attr->getLocation(), diag::implements_attr_non_protocol_type)
|
||||
.highlight(attr->getProtocolTypeRepr()->getSourceRange());
|
||||
// `ImplementsAttr::getProtocol()` returns `nullptr` both when a type fails
|
||||
// to resolve, and when it resolves to something other than a protocol.
|
||||
// Due to layering concerns, it doesn't resolve in a way that emits
|
||||
// diagnostics.
|
||||
//
|
||||
// Distinguish between these situations by trying to resolve the type again.
|
||||
// If it doesn't resolve, TypeResolution will have diagnosed the problem; if
|
||||
// it does, it must have resolved to a non-protocol, so emit a diagnostic to
|
||||
// that effect.
|
||||
TypeResolutionOptions options(TypeResolverContext::None);
|
||||
auto resolvedType = TypeResolution::resolveContextualType(
|
||||
attr->getProtocolTypeRepr(), DC, options,
|
||||
// Unbound generics and placeholders are not allowed within this attr.
|
||||
/*unboundTyOpener*/ nullptr, /*placeholderHandler*/ nullptr,
|
||||
/*packElementOpener*/ nullptr);
|
||||
|
||||
if (resolvedType && !resolvedType->hasError())
|
||||
diagnose(attr->getLocation(), diag::implements_attr_non_protocol_type)
|
||||
.highlight(attr->getProtocolTypeRepr()->getSourceRange());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,5 +21,9 @@ struct S0 : NeedsF0 { // expected-error {{type 'S0' does not conform to protoco
|
||||
@_implements(Equatable, ==(_:_:)) // expected-error {{containing type 'S0' does not conform to protocol 'Equatable'}}
|
||||
static func gg2(x:S0, y:S0) -> Bool {
|
||||
}
|
||||
|
||||
@_implements(NonexistentType, ff3()) // expected-error {{cannot find type 'NonexistentType' in scope}}
|
||||
func gg3() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user