@@ -7,17 +7,15 @@ use rustc_errors::{struct_span_err, Applicability, Diagnostic};
77use rustc_hir as hir;
88use rustc_hir:: { intravisit, HirId } ;
99use rustc_middle:: hir:: nested_filter;
10- use rustc_middle:: lint:: LevelAndSource ;
11- use rustc_middle:: lint:: LintDiagnosticBuilder ;
1210use rustc_middle:: lint:: {
13- struct_lint_level, LintLevelMap , LintLevelSets , LintLevelSource , LintSet , LintStackIndex ,
14- COMMAND_LINE ,
11+ struct_lint_level, LevelAndSource , LintDiagnosticBuilder , LintExpectation , LintLevelMap ,
12+ LintLevelSets , LintLevelSource , LintSet , LintStackIndex , COMMAND_LINE ,
1513} ;
1614use rustc_middle:: ty:: query:: Providers ;
1715use rustc_middle:: ty:: { RegisteredTools , TyCtxt } ;
1816use rustc_session:: lint:: {
1917 builtin:: { self , FORBIDDEN_LINT_GROUPS } ,
20- Level , Lint , LintId ,
18+ Level , Lint , LintExpectationId , LintId ,
2119} ;
2220use rustc_session:: parse:: feature_err;
2321use rustc_session:: Session ;
@@ -44,6 +42,7 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
4442
4543pub struct LintLevelsBuilder < ' s > {
4644 sess : & ' s Session ,
45+ lint_expectations : FxHashMap < LintExpectationId , LintExpectation > ,
4746 sets : LintLevelSets ,
4847 id_to_set : FxHashMap < HirId , LintStackIndex > ,
4948 cur : LintStackIndex ,
@@ -66,6 +65,7 @@ impl<'s> LintLevelsBuilder<'s> {
6665 ) -> Self {
6766 let mut builder = LintLevelsBuilder {
6867 sess,
68+ lint_expectations : Default :: default ( ) ,
6969 sets : LintLevelSets :: new ( ) ,
7070 cur : COMMAND_LINE ,
7171 id_to_set : Default :: default ( ) ,
@@ -231,7 +231,7 @@ impl<'s> LintLevelsBuilder<'s> {
231231 let sess = self . sess ;
232232 let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
233233 for attr in attrs {
234- let Some ( level) = Level :: from_symbol ( attr. name_or_empty ( ) ) else {
234+ let Some ( level) = Level :: from_symbol ( attr. name_or_empty ( ) , attr . id . as_u32 ( ) ) else {
235235 continue
236236 } ;
237237
@@ -476,6 +476,26 @@ impl<'s> LintLevelsBuilder<'s> {
476476 }
477477 }
478478 }
479+
480+ if !specs. is_empty ( ) {
481+ // Only lints that are currently registered in the lint store
482+ // have been found and added to `specs`. Creating the expectation
483+ // here ensures that it can be fulfilled during this compilation
484+ // session.
485+ if let Level :: Expect ( expect_id) = level {
486+ let has_lints = specs
487+ . values ( )
488+ . any ( |( lvl, _src) | matches ! ( lvl, Level :: Expect ( check_id) if check_id. eq( & expect_id) ) ) ;
489+
490+ if has_lints {
491+ let lint = builtin:: UNFULFILLED_LINT_EXPECTATIONS ;
492+ let ( lvl, src) =
493+ self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , & sess) ;
494+ let expectation = LintExpectation :: new ( reason, attr. span , lvl, src) ;
495+ self . lint_expectations . insert ( expect_id, expectation) ;
496+ }
497+ }
498+ }
479499 }
480500
481501 if !is_crate_node {
@@ -563,7 +583,11 @@ impl<'s> LintLevelsBuilder<'s> {
563583 }
564584
565585 pub fn build_map ( self ) -> LintLevelMap {
566- LintLevelMap { sets : self . sets , id_to_set : self . id_to_set }
586+ LintLevelMap {
587+ sets : self . sets ,
588+ id_to_set : self . id_to_set ,
589+ lint_expectations : self . lint_expectations ,
590+ }
567591 }
568592}
569593
0 commit comments