mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Typecheck contents of @_implements attribute.
This commit is contained in:
@@ -2154,6 +2154,17 @@ ERROR(lazy_not_observable,none,
|
||||
ERROR(attr_for_debugger_support_only,none,
|
||||
"@LLDBDebuggerSupport may only be used when debugger support is on", ())
|
||||
|
||||
// @_implements
|
||||
ERROR(implements_attr_protocol_lacks_member,none,
|
||||
"protocol %0 has no member %1", (DeclName, DeclName))
|
||||
|
||||
ERROR(implements_attr_non_protocol_type,none,
|
||||
"non-protocol type in @_implements attribute", ())
|
||||
|
||||
ERROR(implements_attr_protocol_not_conformed_to,none,
|
||||
"containing type %0 does not conform to protocol %1",
|
||||
(DeclName, DeclName))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Type Check Expressions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -756,7 +756,6 @@ public:
|
||||
IGNORED_ATTR(WarnUnqualifiedAccess)
|
||||
IGNORED_ATTR(ShowInInterface)
|
||||
IGNORED_ATTR(ObjCMembers)
|
||||
IGNORED_ATTR(Implements)
|
||||
#undef IGNORED_ATTR
|
||||
|
||||
void visitAvailableAttr(AvailableAttr *attr);
|
||||
@@ -797,6 +796,7 @@ public:
|
||||
void visitInlineableAttr(InlineableAttr *attr);
|
||||
|
||||
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
|
||||
void visitImplementsAttr(ImplementsAttr *attr);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
@@ -1884,6 +1884,52 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
|
||||
TypeLoc &ProtoTypeLoc = attr->getProtocolType();
|
||||
TypeResolutionOptions options;
|
||||
options |= TR_AllowUnboundGenerics;
|
||||
|
||||
DeclContext *DC = D->getDeclContext();
|
||||
Type T = TC.resolveType(ProtoTypeLoc.getTypeRepr(),
|
||||
DC, options);
|
||||
ProtoTypeLoc.setType(T);
|
||||
|
||||
// Definite error-types were already diagnosed in resolveType.
|
||||
if (!T || T->hasError())
|
||||
return;
|
||||
|
||||
// Check that we got a ProtocolType.
|
||||
if (auto PT = T->getAs<ProtocolType>()) {
|
||||
ProtocolDecl *PD = PT->getDecl();
|
||||
|
||||
// Check that the ProtocolType has the specified member.
|
||||
LookupResult R = TC.lookupMember(PD->getDeclContext(),
|
||||
PT, attr->getMemberName());
|
||||
if (!R) {
|
||||
TC.diagnose(attr->getLocation(),
|
||||
diag::implements_attr_protocol_lacks_member,
|
||||
PD->getBaseName(), attr->getMemberName())
|
||||
.highlight(attr->getMemberNameLoc().getSourceRange());
|
||||
}
|
||||
|
||||
// Check that the decl we're decorating is a member of a type that actually
|
||||
// conforms to the specified protocol.
|
||||
NominalTypeDecl *NTD = DC->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||
SmallVector<ProtocolConformance *, 2> conformances;
|
||||
if (!NTD->lookupConformance(DC->getParentModule(), PD, conformances)) {
|
||||
TC.diagnose(attr->getLocation(),
|
||||
diag::implements_attr_protocol_not_conformed_to,
|
||||
NTD->getFullName(), PD->getFullName())
|
||||
.highlight(ProtoTypeLoc.getTypeRepr()->getSourceRange());
|
||||
}
|
||||
|
||||
} else {
|
||||
TC.diagnose(attr->getLocation(),
|
||||
diag::implements_attr_non_protocol_type)
|
||||
.highlight(ProtoTypeLoc.getTypeRepr()->getSourceRange());
|
||||
}
|
||||
}
|
||||
|
||||
void TypeChecker::checkDeclAttributes(Decl *D) {
|
||||
AttributeChecker Checker(*this, D);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user