@@ -658,6 +658,23 @@ impl Handler {
658658 result
659659 }
660660
661+ /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
662+ /// The `id` is used for lint emissions which should also fulfill a lint expectation.
663+ ///
664+ /// Attempting to `.emit()` the builder will only emit if either:
665+ /// * `can_emit_warnings` is `true`
666+ /// * `is_force_warn` was set in `DiagnosticId::Lint`
667+ pub fn struct_span_warn_with_expectation (
668+ & self ,
669+ span : impl Into < MultiSpan > ,
670+ msg : impl Into < DiagnosticMessage > ,
671+ id : LintExpectationId ,
672+ ) -> DiagnosticBuilder < ' _ , ( ) > {
673+ let mut result = self . struct_warn_with_expectation ( msg, id) ;
674+ result. set_span ( span) ;
675+ result
676+ }
677+
661678 /// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
662679 pub fn struct_span_allow (
663680 & self ,
@@ -688,7 +705,21 @@ impl Handler {
688705 /// * `can_emit_warnings` is `true`
689706 /// * `is_force_warn` was set in `DiagnosticId::Lint`
690707 pub fn struct_warn ( & self , msg : impl Into < DiagnosticMessage > ) -> DiagnosticBuilder < ' _ , ( ) > {
691- DiagnosticBuilder :: new ( self , Level :: Warning , msg)
708+ DiagnosticBuilder :: new ( self , Level :: Warning ( None ) , msg)
709+ }
710+
711+ /// Construct a builder at the `Warning` level with the `msg`. The `id` is used for
712+ /// lint emissions which should also fulfill a lint expectation.
713+ ///
714+ /// Attempting to `.emit()` the builder will only emit if either:
715+ /// * `can_emit_warnings` is `true`
716+ /// * `is_force_warn` was set in `DiagnosticId::Lint`
717+ pub fn struct_warn_with_expectation (
718+ & self ,
719+ msg : impl Into < DiagnosticMessage > ,
720+ id : LintExpectationId ,
721+ ) -> DiagnosticBuilder < ' _ , ( ) > {
722+ DiagnosticBuilder :: new ( self , Level :: Warning ( Some ( id) ) , msg)
692723 }
693724
694725 /// Construct a builder at the `Allow` level with the `msg`.
@@ -842,7 +873,7 @@ impl Handler {
842873 }
843874
844875 pub fn span_warn ( & self , span : impl Into < MultiSpan > , msg : impl Into < DiagnosticMessage > ) {
845- self . emit_diag_at_span ( Diagnostic :: new ( Warning , msg) , span) ;
876+ self . emit_diag_at_span ( Diagnostic :: new ( Warning ( None ) , msg) , span) ;
846877 }
847878
848879 pub fn span_warn_with_code (
@@ -851,7 +882,7 @@ impl Handler {
851882 msg : impl Into < DiagnosticMessage > ,
852883 code : DiagnosticId ,
853884 ) {
854- self . emit_diag_at_span ( Diagnostic :: new_with_code ( Warning , Some ( code) , msg) , span) ;
885+ self . emit_diag_at_span ( Diagnostic :: new_with_code ( Warning ( None ) , Some ( code) , msg) , span) ;
855886 }
856887
857888 pub fn span_bug ( & self , span : impl Into < MultiSpan > , msg : impl Into < DiagnosticMessage > ) -> ! {
@@ -905,7 +936,7 @@ impl Handler {
905936 }
906937
907938 pub fn warn ( & self , msg : impl Into < DiagnosticMessage > ) {
908- let mut db = DiagnosticBuilder :: new ( self , Warning , msg) ;
939+ let mut db = DiagnosticBuilder :: new ( self , Warning ( None ) , msg) ;
909940 db. emit ( ) ;
910941 }
911942
@@ -1010,13 +1041,10 @@ impl Handler {
10101041 for mut diag in diags. into_iter ( ) {
10111042 diag. update_unstable_expectation_id ( unstable_to_stable) ;
10121043
1013- let stable_id = diag
1014- . level
1015- . get_expectation_id ( )
1016- . expect ( "all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`" ) ;
1017- inner. fulfilled_expectations . insert ( stable_id) ;
1018-
1019- ( * TRACK_DIAGNOSTICS ) ( & diag) ;
1044+ // Here the diagnostic is given back to `emit_diagnostic` where it was first
1045+ // intercepted. Now it should be processed as usual, since the unstable expectation
1046+ // id is now stable.
1047+ inner. emit_diagnostic ( & mut diag) ;
10201048 }
10211049 }
10221050
@@ -1066,6 +1094,15 @@ impl HandlerInner {
10661094
10671095 // FIXME(eddyb) this should ideally take `diagnostic` by value.
10681096 fn emit_diagnostic ( & mut self , diagnostic : & mut Diagnostic ) -> Option < ErrorGuaranteed > {
1097+ // The `LintExpectationId` can be stable or unstable depending on when it was created.
1098+ // Diagnostics created before the definition of `HirId`s are unstable and can not yet
1099+ // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
1100+ // a stable one by the `LintLevelsBuilder`.
1101+ if let Some ( LintExpectationId :: Unstable { .. } ) = diagnostic. level . get_expectation_id ( ) {
1102+ self . unstable_expect_diagnostics . push ( diagnostic. clone ( ) ) ;
1103+ return None ;
1104+ }
1105+
10691106 if diagnostic. level == Level :: DelayedBug {
10701107 // FIXME(eddyb) this should check for `has_errors` and stop pushing
10711108 // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1082,7 +1119,12 @@ impl HandlerInner {
10821119 self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
10831120 }
10841121
1085- if diagnostic. level == Warning
1122+ if let Some ( expectation_id) = diagnostic. level . get_expectation_id ( ) {
1123+ self . suppressed_expected_diag = true ;
1124+ self . fulfilled_expectations . insert ( expectation_id) ;
1125+ }
1126+
1127+ if matches ! ( diagnostic. level, Warning ( _) )
10861128 && !self . flags . can_emit_warnings
10871129 && !diagnostic. is_force_warn ( )
10881130 {
@@ -1092,22 +1134,9 @@ impl HandlerInner {
10921134 return None ;
10931135 }
10941136
1095- // The `LintExpectationId` can be stable or unstable depending on when it was created.
1096- // Diagnostics created before the definition of `HirId`s are unstable and can not yet
1097- // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
1098- // a stable one by the `LintLevelsBuilder`.
1099- if let Level :: Expect ( LintExpectationId :: Unstable { .. } ) = diagnostic. level {
1100- self . unstable_expect_diagnostics . push ( diagnostic. clone ( ) ) ;
1101- return None ;
1102- }
1103-
11041137 ( * TRACK_DIAGNOSTICS ) ( diagnostic) ;
11051138
1106- if let Level :: Expect ( expectation_id) = diagnostic. level {
1107- self . suppressed_expected_diag = true ;
1108- self . fulfilled_expectations . insert ( expectation_id) ;
1109- return None ;
1110- } else if diagnostic. level == Allow {
1139+ if matches ! ( diagnostic. level, Level :: Expect ( _) | Level :: Allow ) {
11111140 return None ;
11121141 }
11131142
@@ -1144,7 +1173,7 @@ impl HandlerInner {
11441173 self . emitter . emit_diagnostic ( & diagnostic) ;
11451174 if diagnostic. is_error ( ) {
11461175 self . deduplicated_err_count += 1 ;
1147- } else if diagnostic . level == Warning {
1176+ } else if let Warning ( _ ) = diagnostic . level {
11481177 self . deduplicated_warn_count += 1 ;
11491178 }
11501179 }
@@ -1197,7 +1226,7 @@ impl HandlerInner {
11971226 match ( errors. len ( ) , warnings. len ( ) ) {
11981227 ( 0 , 0 ) => return ,
11991228 ( 0 , _) => self . emitter . emit_diagnostic ( & Diagnostic :: new (
1200- Level :: Warning ,
1229+ Level :: Warning ( None ) ,
12011230 DiagnosticMessage :: Str ( warnings) ,
12021231 ) ) ,
12031232 ( _, 0 ) => {
@@ -1430,7 +1459,10 @@ pub enum Level {
14301459 /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
14311460 lint : bool ,
14321461 } ,
1433- Warning ,
1462+ /// This [`LintExpectationId`] is used for expected lint diagnostics, which should
1463+ /// also emit a warning due to the `force-warn` flag. In all other cases this should
1464+ /// be `None`.
1465+ Warning ( Option < LintExpectationId > ) ,
14341466 Note ,
14351467 /// A note that is only emitted once.
14361468 OnceNote ,
@@ -1453,7 +1485,7 @@ impl Level {
14531485 Bug | DelayedBug | Fatal | Error { .. } => {
14541486 spec. set_fg ( Some ( Color :: Red ) ) . set_intense ( true ) ;
14551487 }
1456- Warning => {
1488+ Warning ( _ ) => {
14571489 spec. set_fg ( Some ( Color :: Yellow ) ) . set_intense ( cfg ! ( windows) ) ;
14581490 }
14591491 Note | OnceNote => {
@@ -1472,7 +1504,7 @@ impl Level {
14721504 match self {
14731505 Bug | DelayedBug => "error: internal compiler error" ,
14741506 Fatal | Error { .. } => "error" ,
1475- Warning => "warning" ,
1507+ Warning ( _ ) => "warning" ,
14761508 Note | OnceNote => "note" ,
14771509 Help => "help" ,
14781510 FailureNote => "failure-note" ,
@@ -1487,7 +1519,7 @@ impl Level {
14871519
14881520 pub fn get_expectation_id ( & self ) -> Option < LintExpectationId > {
14891521 match self {
1490- Level :: Expect ( id) => Some ( * id) ,
1522+ Level :: Expect ( id) | Level :: Warning ( Some ( id ) ) => Some ( * id) ,
14911523 _ => None ,
14921524 }
14931525 }
0 commit comments