@@ -756,7 +756,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
756
756
IGNORED_ATTR (WarnUnqualifiedAccess)
757
757
IGNORED_ATTR (ShowInInterface)
758
758
IGNORED_ATTR (ObjCMembers)
759
- IGNORED_ATTR (Implements)
760
759
#undef IGNORED_ATTR
761
760
762
761
void visitAvailableAttr (AvailableAttr *attr);
@@ -797,6 +796,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
797
796
void visitInlineableAttr (InlineableAttr *attr);
798
797
799
798
void visitDiscardableResultAttr (DiscardableResultAttr *attr);
799
+ void visitImplementsAttr (ImplementsAttr *attr);
800
800
};
801
801
} // end anonymous namespace
802
802
@@ -1884,6 +1884,52 @@ void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
1884
1884
}
1885
1885
}
1886
1886
1887
+ void AttributeChecker::visitImplementsAttr (ImplementsAttr *attr) {
1888
+ TypeLoc &ProtoTypeLoc = attr->getProtocolType ();
1889
+ TypeResolutionOptions options;
1890
+ options |= TR_AllowUnboundGenerics;
1891
+
1892
+ DeclContext *DC = D->getDeclContext ();
1893
+ Type T = TC.resolveType (ProtoTypeLoc.getTypeRepr (),
1894
+ DC, options);
1895
+ ProtoTypeLoc.setType (T);
1896
+
1897
+ // Definite error-types were already diagnosed in resolveType.
1898
+ if (!T || T->hasError ())
1899
+ return ;
1900
+
1901
+ // Check that we got a ProtocolType.
1902
+ if (auto PT = T->getAs <ProtocolType>()) {
1903
+ ProtocolDecl *PD = PT->getDecl ();
1904
+
1905
+ // Check that the ProtocolType has the specified member.
1906
+ LookupResult R = TC.lookupMember (PD->getDeclContext (),
1907
+ PT, attr->getMemberName ());
1908
+ if (!R) {
1909
+ TC.diagnose (attr->getLocation (),
1910
+ diag::implements_attr_protocol_lacks_member,
1911
+ PD->getBaseName (), attr->getMemberName ())
1912
+ .highlight (attr->getMemberNameLoc ().getSourceRange ());
1913
+ }
1914
+
1915
+ // Check that the decl we're decorating is a member of a type that actually
1916
+ // conforms to the specified protocol.
1917
+ NominalTypeDecl *NTD = DC->getAsNominalTypeOrNominalTypeExtensionContext ();
1918
+ SmallVector<ProtocolConformance *, 2 > conformances;
1919
+ if (!NTD->lookupConformance (DC->getParentModule (), PD, conformances)) {
1920
+ TC.diagnose (attr->getLocation (),
1921
+ diag::implements_attr_protocol_not_conformed_to,
1922
+ NTD->getFullName (), PD->getFullName ())
1923
+ .highlight (ProtoTypeLoc.getTypeRepr ()->getSourceRange ());
1924
+ }
1925
+
1926
+ } else {
1927
+ TC.diagnose (attr->getLocation (),
1928
+ diag::implements_attr_non_protocol_type)
1929
+ .highlight (ProtoTypeLoc.getTypeRepr ()->getSourceRange ());
1930
+ }
1931
+ }
1932
+
1887
1933
void TypeChecker::checkDeclAttributes (Decl *D) {
1888
1934
AttributeChecker Checker (*this , D);
1889
1935
0 commit comments