@@ -93,10 +93,21 @@ impl<'s> LintLevelsBuilder<'s> {
9393 self . store
9494 }
9595
96+ fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
97+ & self . sets . list [ self . cur ] . specs
98+ }
99+
100+ fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
101+ & mut self . sets . list [ self . cur ] . specs
102+ }
103+
96104 fn process_command_line ( & mut self , sess : & Session , store : & LintStore ) {
97- let mut specs = FxHashMap :: default ( ) ;
98105 self . sets . lint_cap = sess. opts . lint_cap . unwrap_or ( Level :: Forbid ) ;
99106
107+ self . cur = self . sets . list . push ( LintSet {
108+ specs : FxHashMap :: default ( ) ,
109+ parent : COMMAND_LINE ,
110+ } ) ;
100111 for & ( ref lint_name, level) in & sess. opts . lint_opts {
101112 store. check_lint_name_cmdline ( sess, & lint_name, level, self . registered_tools ) ;
102113 let orig_level = level;
@@ -108,30 +119,28 @@ impl<'s> LintLevelsBuilder<'s> {
108119 } ;
109120 for id in ids {
110121 // ForceWarn and Forbid cannot be overriden
111- if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = specs . get ( & id) {
122+ if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = self . current_specs ( ) . get ( & id) {
112123 continue ;
113124 }
114125
115- self . check_gated_lint ( id, DUMMY_SP ) ;
116- let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
117- specs. insert ( id, ( level, src) ) ;
126+ if self . check_gated_lint ( id, DUMMY_SP ) {
127+ let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
128+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
129+ }
118130 }
119131 }
120-
121- self . cur = self . sets . list . push ( LintSet { specs, parent : COMMAND_LINE } ) ;
122132 }
123133
124134 /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
125135 /// (e.g. if a forbid was already inserted on the same scope), then emits a
126136 /// diagnostic with no change to `specs`.
127137 fn insert_spec (
128138 & mut self ,
129- specs : & mut FxHashMap < LintId , LevelAndSource > ,
130139 id : LintId ,
131140 ( level, src) : LevelAndSource ,
132141 ) {
133142 let ( old_level, old_src) =
134- self . sets . get_lint_level ( id. lint , self . cur , Some ( & specs ) , & self . sess ) ;
143+ self . sets . get_lint_level ( id. lint , self . cur , Some ( self . current_specs ( ) ) , & self . sess ) ;
135144 // Setting to a non-forbid level is an error if the lint previously had
136145 // a forbid level. Note that this is not necessarily true even with a
137146 // `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -154,7 +163,7 @@ impl<'s> LintLevelsBuilder<'s> {
154163 } ;
155164 debug ! (
156165 "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}" ,
157- fcw_warning, specs , old_src, id_name
166+ fcw_warning, self . current_specs ( ) , old_src, id_name
158167 ) ;
159168
160169 let decorate_diag = |diag : & mut Diagnostic | {
@@ -213,9 +222,9 @@ impl<'s> LintLevelsBuilder<'s> {
213222 }
214223 }
215224 if let Level :: ForceWarn = old_level {
216- specs . insert ( id, ( old_level, old_src) ) ;
225+ self . current_specs_mut ( ) . insert ( id, ( old_level, old_src) ) ;
217226 } else {
218- specs . insert ( id, ( level, src) ) ;
227+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
219228 }
220229 }
221230
@@ -239,7 +248,11 @@ impl<'s> LintLevelsBuilder<'s> {
239248 is_crate_node : bool ,
240249 source_hir_id : Option < HirId > ,
241250 ) -> BuilderPush {
242- let mut specs = FxHashMap :: default ( ) ;
251+ let prev = self . cur ;
252+ self . cur = self . sets . list . push ( LintSet {
253+ specs : FxHashMap :: default ( ) ,
254+ parent : prev,
255+ } ) ;
243256 let sess = self . sess ;
244257 let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
245258 for ( attr_index, attr) in attrs. iter ( ) . enumerate ( ) {
@@ -348,8 +361,9 @@ impl<'s> LintLevelsBuilder<'s> {
348361 reason,
349362 ) ;
350363 for & id in * ids {
351- self . check_gated_lint ( id, attr. span ) ;
352- self . insert_spec ( & mut specs, id, ( level, src) ) ;
364+ if self . check_gated_lint ( id, attr. span ) {
365+ self . insert_spec ( id, ( level, src) ) ;
366+ }
353367 }
354368 if let Level :: Expect ( expect_id) = level {
355369 self . lint_expectations
@@ -368,7 +382,7 @@ impl<'s> LintLevelsBuilder<'s> {
368382 reason,
369383 ) ;
370384 for id in ids {
371- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
385+ self . insert_spec ( * id, ( level, src) ) ;
372386 }
373387 if let Level :: Expect ( expect_id) = level {
374388 self . lint_expectations
@@ -378,7 +392,7 @@ impl<'s> LintLevelsBuilder<'s> {
378392 Err ( ( Some ( ids) , ref new_lint_name) ) => {
379393 let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
380394 let ( lvl, src) =
381- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , & sess) ;
395+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , & sess) ;
382396 struct_lint_level (
383397 self . sess ,
384398 lint,
@@ -408,7 +422,7 @@ impl<'s> LintLevelsBuilder<'s> {
408422 reason,
409423 ) ;
410424 for id in ids {
411- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
425+ self . insert_spec ( * id, ( level, src) ) ;
412426 }
413427 if let Level :: Expect ( expect_id) = level {
414428 self . lint_expectations
@@ -449,7 +463,7 @@ impl<'s> LintLevelsBuilder<'s> {
449463 CheckLintNameResult :: Warning ( msg, renamed) => {
450464 let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
451465 let ( renamed_lint_level, src) =
452- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , & sess) ;
466+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , & sess) ;
453467 struct_lint_level (
454468 self . sess ,
455469 lint,
@@ -473,7 +487,7 @@ impl<'s> LintLevelsBuilder<'s> {
473487 CheckLintNameResult :: NoLint ( suggestion) => {
474488 let lint = builtin:: UNKNOWN_LINTS ;
475489 let ( level, src) =
476- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
490+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
477491 struct_lint_level ( self . sess , lint, level, src, Some ( sp. into ( ) ) , |lint| {
478492 let name = if let Some ( tool_ident) = tool_ident {
479493 format ! ( "{}::{}" , tool_ident. name, name)
@@ -504,8 +518,9 @@ impl<'s> LintLevelsBuilder<'s> {
504518 {
505519 let src = LintLevelSource :: Node ( Symbol :: intern ( & new_name) , sp, reason) ;
506520 for & id in ids {
507- self . check_gated_lint ( id, attr. span ) ;
508- self . insert_spec ( & mut specs, id, ( level, src) ) ;
521+ if self . check_gated_lint ( id, attr. span ) {
522+ self . insert_spec ( id, ( level, src) ) ;
523+ }
509524 }
510525 if let Level :: Expect ( expect_id) = level {
511526 self . lint_expectations
@@ -519,7 +534,7 @@ impl<'s> LintLevelsBuilder<'s> {
519534 }
520535
521536 if !is_crate_node {
522- for ( id, & ( level, ref src) ) in specs . iter ( ) {
537+ for ( id, & ( level, ref src) ) in self . current_specs ( ) . iter ( ) {
523538 if !id. lint . crate_level_only {
524539 continue ;
525540 }
@@ -530,7 +545,7 @@ impl<'s> LintLevelsBuilder<'s> {
530545
531546 let lint = builtin:: UNUSED_ATTRIBUTES ;
532547 let ( lint_level, lint_src) =
533- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
548+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
534549 struct_lint_level (
535550 self . sess ,
536551 lint,
@@ -551,9 +566,9 @@ impl<'s> LintLevelsBuilder<'s> {
551566 }
552567 }
553568
554- let prev = self . cur ;
555- if !specs . is_empty ( ) {
556- self . cur = self . sets . list . push ( LintSet { specs , parent : prev } ) ;
569+ if self . current_specs ( ) . is_empty ( ) {
570+ self . sets . list . pop ( ) ;
571+ self . cur = prev;
557572 }
558573
559574 BuilderPush { prev, changed : prev != self . cur }
@@ -574,18 +589,25 @@ impl<'s> LintLevelsBuilder<'s> {
574589 }
575590
576591 /// Checks if the lint is gated on a feature that is not enabled.
577- fn check_gated_lint ( & self , lint_id : LintId , span : Span ) {
592+ ///
593+ /// Returns `true` if the lint's feature is enabled.
594+ fn check_gated_lint ( & self , lint_id : LintId , span : Span ) -> bool {
578595 if let Some ( feature) = lint_id. lint . feature_gate {
579596 if !self . sess . features_untracked ( ) . enabled ( feature) {
580- feature_err (
581- & self . sess . parse_sess ,
582- feature,
583- span,
584- & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) ) ,
585- )
586- . emit ( ) ;
597+ let ( unknown_lints_level, _) = self . lint_level ( builtin:: UNKNOWN_LINTS ) ;
598+ if unknown_lints_level != Level :: Allow {
599+ feature_err (
600+ & self . sess . parse_sess ,
601+ feature,
602+ span,
603+ & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) ) ,
604+ )
605+ . emit ( ) ;
606+ }
607+ return false ;
587608 }
588609 }
610+ true
589611 }
590612
591613 /// Called after `push` when the scope of a set of attributes are exited.
0 commit comments