@@ -17,7 +17,7 @@ use rustc_session::lint::{
1717 builtin:: { self , FORBIDDEN_LINT_GROUPS } ,
1818 Level , Lint , LintExpectationId , LintId ,
1919} ;
20- use rustc_session:: parse:: feature_err;
20+ use rustc_session:: parse:: { add_feature_diagnostics , feature_err} ;
2121use rustc_session:: Session ;
2222use rustc_span:: symbol:: { sym, Symbol } ;
2323use rustc_span:: { source_map:: MultiSpan , Span , DUMMY_SP } ;
@@ -93,10 +93,19 @@ 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 =
108+ self . sets . list . push ( LintSet { specs : FxHashMap :: default ( ) , parent : COMMAND_LINE } ) ;
100109 for & ( ref lint_name, level) in & sess. opts . lint_opts {
101110 store. check_lint_name_cmdline ( sess, & lint_name, level, self . registered_tools ) ;
102111 let orig_level = level;
@@ -108,30 +117,24 @@ impl<'s> LintLevelsBuilder<'s> {
108117 } ;
109118 for id in ids {
110119 // ForceWarn and Forbid cannot be overriden
111- if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = specs . get ( & id) {
120+ if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = self . current_specs ( ) . get ( & id) {
112121 continue ;
113122 }
114123
115- self . check_gated_lint ( id, DUMMY_SP ) ;
116- let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
117- specs. insert ( id, ( level, src) ) ;
124+ if self . check_gated_lint ( id, DUMMY_SP ) {
125+ let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
126+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
127+ }
118128 }
119129 }
120-
121- self . cur = self . sets . list . push ( LintSet { specs, parent : COMMAND_LINE } ) ;
122130 }
123131
124132 /// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
125133 /// (e.g. if a forbid was already inserted on the same scope), then emits a
126134 /// diagnostic with no change to `specs`.
127- fn insert_spec (
128- & mut self ,
129- specs : & mut FxHashMap < LintId , LevelAndSource > ,
130- id : LintId ,
131- ( level, src) : LevelAndSource ,
132- ) {
135+ fn insert_spec ( & mut self , id : LintId , ( level, src) : LevelAndSource ) {
133136 let ( old_level, old_src) =
134- self . sets . get_lint_level ( id. lint , self . cur , Some ( & specs ) , & self . sess ) ;
137+ self . sets . get_lint_level ( id. lint , self . cur , Some ( self . current_specs ( ) ) , & self . sess ) ;
135138 // Setting to a non-forbid level is an error if the lint previously had
136139 // a forbid level. Note that this is not necessarily true even with a
137140 // `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -154,7 +157,10 @@ impl<'s> LintLevelsBuilder<'s> {
154157 } ;
155158 debug ! (
156159 "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}" ,
157- fcw_warning, specs, old_src, id_name
160+ fcw_warning,
161+ self . current_specs( ) ,
162+ old_src,
163+ id_name
158164 ) ;
159165
160166 let decorate_diag = |diag : & mut Diagnostic | {
@@ -213,9 +219,9 @@ impl<'s> LintLevelsBuilder<'s> {
213219 }
214220 }
215221 if let Level :: ForceWarn = old_level {
216- specs . insert ( id, ( old_level, old_src) ) ;
222+ self . current_specs_mut ( ) . insert ( id, ( old_level, old_src) ) ;
217223 } else {
218- specs . insert ( id, ( level, src) ) ;
224+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
219225 }
220226 }
221227
@@ -239,7 +245,9 @@ impl<'s> LintLevelsBuilder<'s> {
239245 is_crate_node : bool ,
240246 source_hir_id : Option < HirId > ,
241247 ) -> BuilderPush {
242- let mut specs = FxHashMap :: default ( ) ;
248+ let prev = self . cur ;
249+ self . cur = self . sets . list . push ( LintSet { specs : FxHashMap :: default ( ) , parent : prev } ) ;
250+
243251 let sess = self . sess ;
244252 let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
245253 for ( attr_index, attr) in attrs. iter ( ) . enumerate ( ) {
@@ -348,8 +356,9 @@ impl<'s> LintLevelsBuilder<'s> {
348356 reason,
349357 ) ;
350358 for & id in * ids {
351- self . check_gated_lint ( id, attr. span ) ;
352- self . insert_spec ( & mut specs, id, ( level, src) ) ;
359+ if self . check_gated_lint ( id, attr. span ) {
360+ self . insert_spec ( id, ( level, src) ) ;
361+ }
353362 }
354363 if let Level :: Expect ( expect_id) = level {
355364 self . lint_expectations
@@ -368,7 +377,7 @@ impl<'s> LintLevelsBuilder<'s> {
368377 reason,
369378 ) ;
370379 for id in ids {
371- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
380+ self . insert_spec ( * id, ( level, src) ) ;
372381 }
373382 if let Level :: Expect ( expect_id) = level {
374383 self . lint_expectations
@@ -377,8 +386,12 @@ impl<'s> LintLevelsBuilder<'s> {
377386 }
378387 Err ( ( Some ( ids) , ref new_lint_name) ) => {
379388 let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
380- let ( lvl, src) =
381- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , & sess) ;
389+ let ( lvl, src) = self . sets . get_lint_level (
390+ lint,
391+ self . cur ,
392+ Some ( self . current_specs ( ) ) ,
393+ & sess,
394+ ) ;
382395 struct_lint_level (
383396 self . sess ,
384397 lint,
@@ -408,7 +421,7 @@ impl<'s> LintLevelsBuilder<'s> {
408421 reason,
409422 ) ;
410423 for id in ids {
411- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
424+ self . insert_spec ( * id, ( level, src) ) ;
412425 }
413426 if let Level :: Expect ( expect_id) = level {
414427 self . lint_expectations
@@ -448,8 +461,12 @@ impl<'s> LintLevelsBuilder<'s> {
448461
449462 CheckLintNameResult :: Warning ( msg, renamed) => {
450463 let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
451- let ( renamed_lint_level, src) =
452- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , & sess) ;
464+ let ( renamed_lint_level, src) = self . sets . get_lint_level (
465+ lint,
466+ self . cur ,
467+ Some ( self . current_specs ( ) ) ,
468+ & sess,
469+ ) ;
453470 struct_lint_level (
454471 self . sess ,
455472 lint,
@@ -472,8 +489,12 @@ impl<'s> LintLevelsBuilder<'s> {
472489 }
473490 CheckLintNameResult :: NoLint ( suggestion) => {
474491 let lint = builtin:: UNKNOWN_LINTS ;
475- let ( level, src) =
476- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , self . sess ) ;
492+ let ( level, src) = self . sets . get_lint_level (
493+ lint,
494+ self . cur ,
495+ Some ( self . current_specs ( ) ) ,
496+ self . sess ,
497+ ) ;
477498 struct_lint_level ( self . sess , lint, level, src, Some ( sp. into ( ) ) , |lint| {
478499 let name = if let Some ( tool_ident) = tool_ident {
479500 format ! ( "{}::{}" , tool_ident. name, name)
@@ -504,8 +525,9 @@ impl<'s> LintLevelsBuilder<'s> {
504525 {
505526 let src = LintLevelSource :: Node ( Symbol :: intern ( & new_name) , sp, reason) ;
506527 for & id in ids {
507- self . check_gated_lint ( id, attr. span ) ;
508- self . insert_spec ( & mut specs, id, ( level, src) ) ;
528+ if self . check_gated_lint ( id, attr. span ) {
529+ self . insert_spec ( id, ( level, src) ) ;
530+ }
509531 }
510532 if let Level :: Expect ( expect_id) = level {
511533 self . lint_expectations
@@ -519,7 +541,7 @@ impl<'s> LintLevelsBuilder<'s> {
519541 }
520542
521543 if !is_crate_node {
522- for ( id, & ( level, ref src) ) in specs . iter ( ) {
544+ for ( id, & ( level, ref src) ) in self . current_specs ( ) . iter ( ) {
523545 if !id. lint . crate_level_only {
524546 continue ;
525547 }
@@ -530,7 +552,7 @@ impl<'s> LintLevelsBuilder<'s> {
530552
531553 let lint = builtin:: UNUSED_ATTRIBUTES ;
532554 let ( lint_level, lint_src) =
533- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
555+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
534556 struct_lint_level (
535557 self . sess ,
536558 lint,
@@ -551,9 +573,9 @@ impl<'s> LintLevelsBuilder<'s> {
551573 }
552574 }
553575
554- let prev = self . cur ;
555- if !specs . is_empty ( ) {
556- self . cur = self . sets . list . push ( LintSet { specs , parent : prev } ) ;
576+ if self . current_specs ( ) . is_empty ( ) {
577+ self . sets . list . pop ( ) ;
578+ self . cur = prev;
557579 }
558580
559581 BuilderPush { prev, changed : prev != self . cur }
@@ -574,18 +596,24 @@ impl<'s> LintLevelsBuilder<'s> {
574596 }
575597
576598 /// Checks if the lint is gated on a feature that is not enabled.
577- fn check_gated_lint ( & self , lint_id : LintId , span : Span ) {
599+ ///
600+ /// Returns `true` if the lint's feature is enabled.
601+ fn check_gated_lint ( & self , lint_id : LintId , span : Span ) -> bool {
578602 if let Some ( feature) = lint_id. lint . feature_gate {
579603 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 ( ) ;
604+ let lint = builtin:: UNKNOWN_LINTS ;
605+ let ( level, src) = self . lint_level ( builtin:: UNKNOWN_LINTS ) ;
606+ struct_lint_level ( self . sess , lint, level, src, Some ( span. into ( ) ) , |lint_db| {
607+ let mut db =
608+ lint_db. build ( & format ! ( "unknown lint: `{}`" , lint_id. lint. name_lower( ) ) ) ;
609+ db. note ( & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) , ) ) ;
610+ add_feature_diagnostics ( & mut db, & self . sess . parse_sess , feature) ;
611+ db. emit ( ) ;
612+ } ) ;
613+ return false ;
587614 }
588615 }
616+ true
589617 }
590618
591619 /// Called after `push` when the scope of a set of attributes are exited.
0 commit comments