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,
|
ERROR(attr_for_debugger_support_only,none,
|
||||||
"@LLDBDebuggerSupport may only be used when debugger support is on", ())
|
"@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
|
// Type Check Expressions
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -756,7 +756,6 @@ public:
|
|||||||
IGNORED_ATTR(WarnUnqualifiedAccess)
|
IGNORED_ATTR(WarnUnqualifiedAccess)
|
||||||
IGNORED_ATTR(ShowInInterface)
|
IGNORED_ATTR(ShowInInterface)
|
||||||
IGNORED_ATTR(ObjCMembers)
|
IGNORED_ATTR(ObjCMembers)
|
||||||
IGNORED_ATTR(Implements)
|
|
||||||
#undef IGNORED_ATTR
|
#undef IGNORED_ATTR
|
||||||
|
|
||||||
void visitAvailableAttr(AvailableAttr *attr);
|
void visitAvailableAttr(AvailableAttr *attr);
|
||||||
@@ -797,6 +796,7 @@ public:
|
|||||||
void visitInlineableAttr(InlineableAttr *attr);
|
void visitInlineableAttr(InlineableAttr *attr);
|
||||||
|
|
||||||
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
|
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
|
||||||
|
void visitImplementsAttr(ImplementsAttr *attr);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // 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) {
|
void TypeChecker::checkDeclAttributes(Decl *D) {
|
||||||
AttributeChecker Checker(*this, D);
|
AttributeChecker Checker(*this, D);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user