@@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
29
29
let mut builder = LintLevelMapBuilder { levels, tcx, store } ;
30
30
let krate = tcx. hir ( ) . krate ( ) ;
31
31
32
- let push = builder. levels . push ( & krate. item . attrs , & store) ;
32
+ let push = builder. levels . push ( & krate. item . attrs , & store, true ) ;
33
33
builder. levels . register_id ( hir:: CRATE_HIR_ID ) ;
34
34
for macro_def in krate. exported_macros {
35
35
builder. levels . register_id ( macro_def. hir_id ) ;
@@ -109,7 +109,12 @@ impl<'s> LintLevelsBuilder<'s> {
109
109
/// `#[allow]`
110
110
///
111
111
/// Don't forget to call `pop`!
112
- pub fn push ( & mut self , attrs : & [ ast:: Attribute ] , store : & LintStore ) -> BuilderPush {
112
+ pub fn push (
113
+ & mut self ,
114
+ attrs : & [ ast:: Attribute ] ,
115
+ store : & LintStore ,
116
+ is_crate_node : bool ,
117
+ ) -> BuilderPush {
113
118
let mut specs = FxHashMap :: default ( ) ;
114
119
let sess = self . sess ;
115
120
let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
@@ -333,6 +338,40 @@ impl<'s> LintLevelsBuilder<'s> {
333
338
}
334
339
}
335
340
341
+ if !is_crate_node {
342
+ for ( id, & ( level, ref src) ) in specs. iter ( ) {
343
+ if !id. lint . crate_level_only {
344
+ continue ;
345
+ }
346
+
347
+ let ( lint_attr_name, lint_attr_span) = match * src {
348
+ LintSource :: Node ( name, span, _) => ( name, span) ,
349
+ _ => continue ,
350
+ } ;
351
+
352
+ let lint = builtin:: UNUSED_ATTRIBUTES ;
353
+ let ( lint_level, lint_src) =
354
+ self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , self . sess ) ;
355
+ struct_lint_level (
356
+ self . sess ,
357
+ lint,
358
+ lint_level,
359
+ lint_src,
360
+ Some ( lint_attr_span. into ( ) ) ,
361
+ |lint| {
362
+ let mut db = lint. build ( & format ! (
363
+ "{}({}) is ignored unless specified at crate level" ,
364
+ level. as_str( ) ,
365
+ lint_attr_name
366
+ ) ) ;
367
+ db. emit ( ) ;
368
+ } ,
369
+ ) ;
370
+ // don't set a separate error for every lint in the group
371
+ break ;
372
+ }
373
+ }
374
+
336
375
for ( id, & ( level, ref src) ) in specs. iter ( ) {
337
376
if level == Level :: Forbid {
338
377
continue ;
@@ -449,7 +488,8 @@ impl LintLevelMapBuilder<'_, '_> {
449
488
where
450
489
F : FnOnce ( & mut Self ) ,
451
490
{
452
- let push = self . levels . push ( attrs, self . store ) ;
491
+ let is_crate_hir = id == hir:: CRATE_HIR_ID ;
492
+ let push = self . levels . push ( attrs, self . store , is_crate_hir) ;
453
493
if push. changed {
454
494
self . levels . register_id ( id) ;
455
495
}
0 commit comments