@@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> LintLevelMap {
2929 let mut builder = LintLevelMapBuilder { levels, tcx, store } ;
3030 let krate = tcx. hir ( ) . krate ( ) ;
3131
32- let push = builder. levels . push ( & krate. item . attrs , & store) ;
32+ let push = builder. levels . push ( & krate. item . attrs , & store, true ) ;
3333 builder. levels . register_id ( hir:: CRATE_HIR_ID ) ;
3434 for macro_def in krate. exported_macros {
3535 builder. levels . register_id ( macro_def. hir_id ) ;
@@ -109,7 +109,12 @@ impl<'s> LintLevelsBuilder<'s> {
109109 /// `#[allow]`
110110 ///
111111 /// 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 {
113118 let mut specs = FxHashMap :: default ( ) ;
114119 let sess = self . sess ;
115120 let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
@@ -333,6 +338,40 @@ impl<'s> LintLevelsBuilder<'s> {
333338 }
334339 }
335340
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+
336375 for ( id, & ( level, ref src) ) in specs. iter ( ) {
337376 if level == Level :: Forbid {
338377 continue ;
@@ -449,7 +488,8 @@ impl LintLevelMapBuilder<'_, '_> {
449488 where
450489 F : FnOnce ( & mut Self ) ,
451490 {
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) ;
453493 if push. changed {
454494 self . levels . register_id ( id) ;
455495 }
0 commit comments