@@ -10,7 +10,7 @@ use rustc_hir::{GenericArg, HirId, MutTy, Mutability, Path, PathSegment, QPath,
10
10
use rustc_middle:: ty;
11
11
use rustc_session:: { declare_lint_pass, declare_tool_lint, impl_lint_pass} ;
12
12
use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
13
- use rustc_span:: symbol:: { sym, Ident , Symbol } ;
13
+ use rustc_span:: symbol:: { kw , sym, Ident , Symbol } ;
14
14
15
15
declare_tool_lint ! {
16
16
pub rustc:: DEFAULT_HASH_TYPES ,
@@ -267,3 +267,47 @@ impl EarlyLintPass for LintPassImpl {
267
267
}
268
268
}
269
269
}
270
+
271
+ declare_tool_lint ! {
272
+ pub rustc:: EXISTING_DOC_KEYWORD ,
273
+ Allow ,
274
+ "Check that documented keywords in std and core actually exist" ,
275
+ report_in_external_macro: true
276
+ }
277
+
278
+ declare_lint_pass ! ( ExistingDocKeyword => [ EXISTING_DOC_KEYWORD ] ) ;
279
+
280
+ fn is_doc_keyword ( s : Symbol ) -> bool {
281
+ s <= kw:: Union
282
+ }
283
+
284
+ impl < ' tcx > LateLintPass < ' tcx > for ExistingDocKeyword {
285
+ fn check_item ( & mut self , cx : & LateContext < ' _ > , item : & rustc_hir:: Item < ' _ > ) {
286
+ for attr in item. attrs {
287
+ if !attr. has_name ( sym:: doc) {
288
+ continue ;
289
+ }
290
+ if let Some ( list) = attr. meta_item_list ( ) {
291
+ for nested in list {
292
+ if nested. has_name ( sym:: keyword) {
293
+ let v = nested
294
+ . value_str ( )
295
+ . expect ( "#[doc(keyword = \" ...\" )] expected a value!" ) ;
296
+ if is_doc_keyword ( v) {
297
+ return ;
298
+ }
299
+ cx. struct_span_lint ( EXISTING_DOC_KEYWORD , attr. span , |lint| {
300
+ lint. build ( & format ! (
301
+ "Found non-existing keyword `{}` used in \
302
+ `#[doc(keyword = \" ...\" )]`",
303
+ v,
304
+ ) )
305
+ . help ( "only existing keywords are allowed in core/std" )
306
+ . emit ( ) ;
307
+ } ) ;
308
+ }
309
+ }
310
+ }
311
+ }
312
+ }
313
+ }
0 commit comments