@@ -660,6 +660,23 @@ impl Handler {
660660 result
661661 }
662662
663+ /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
664+ /// The `id` is used for lint emissions which should also fulfill a lint expectation.
665+ ///
666+ /// Attempting to `.emit()` the builder will only emit if either:
667+ /// * `can_emit_warnings` is `true`
668+ /// * `is_force_warn` was set in `DiagnosticId::Lint`
669+ pub fn struct_span_warn_with_expectation (
670+ & self ,
671+ span : impl Into < MultiSpan > ,
672+ msg : impl Into < DiagnosticMessage > ,
673+ id : LintExpectationId ,
674+ ) -> DiagnosticBuilder < ' _ , ( ) > {
675+ let mut result = self . struct_warn_with_expectation ( msg, id) ;
676+ result. set_span ( span) ;
677+ result
678+ }
679+
663680 /// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
664681 #[ cfg_attr( not( bootstrap) , rustc_lint_diagnostics) ]
665682 pub fn struct_span_allow (
@@ -693,7 +710,21 @@ impl Handler {
693710 /// * `is_force_warn` was set in `DiagnosticId::Lint`
694711 #[ cfg_attr( not( bootstrap) , rustc_lint_diagnostics) ]
695712 pub fn struct_warn ( & self , msg : impl Into < DiagnosticMessage > ) -> DiagnosticBuilder < ' _ , ( ) > {
696- DiagnosticBuilder :: new ( self , Level :: Warning , msg)
713+ DiagnosticBuilder :: new ( self , Level :: Warning ( None ) , msg)
714+ }
715+
716+ /// Construct a builder at the `Warning` level with the `msg`. The `id` is used for
717+ /// lint emissions which should also fulfill a lint expectation.
718+ ///
719+ /// Attempting to `.emit()` the builder will only emit if either:
720+ /// * `can_emit_warnings` is `true`
721+ /// * `is_force_warn` was set in `DiagnosticId::Lint`
722+ pub fn struct_warn_with_expectation (
723+ & self ,
724+ msg : impl Into < DiagnosticMessage > ,
725+ id : LintExpectationId ,
726+ ) -> DiagnosticBuilder < ' _ , ( ) > {
727+ DiagnosticBuilder :: new ( self , Level :: Warning ( Some ( id) ) , msg)
697728 }
698729
699730 /// Construct a builder at the `Allow` level with the `msg`.
@@ -864,7 +895,7 @@ impl Handler {
864895
865896 #[ cfg_attr( not( bootstrap) , rustc_lint_diagnostics) ]
866897 pub fn span_warn ( & self , span : impl Into < MultiSpan > , msg : impl Into < DiagnosticMessage > ) {
867- self . emit_diag_at_span ( Diagnostic :: new ( Warning , msg) , span) ;
898+ self . emit_diag_at_span ( Diagnostic :: new ( Warning ( None ) , msg) , span) ;
868899 }
869900
870901 #[ cfg_attr( not( bootstrap) , rustc_lint_diagnostics) ]
@@ -874,7 +905,7 @@ impl Handler {
874905 msg : impl Into < DiagnosticMessage > ,
875906 code : DiagnosticId ,
876907 ) {
877- self . emit_diag_at_span ( Diagnostic :: new_with_code ( Warning , Some ( code) , msg) , span) ;
908+ self . emit_diag_at_span ( Diagnostic :: new_with_code ( Warning ( None ) , Some ( code) , msg) , span) ;
878909 }
879910
880911 pub fn span_bug ( & self , span : impl Into < MultiSpan > , msg : impl Into < DiagnosticMessage > ) -> ! {
@@ -928,7 +959,7 @@ impl Handler {
928959 }
929960
930961 pub fn warn ( & self , msg : impl Into < DiagnosticMessage > ) {
931- let mut db = DiagnosticBuilder :: new ( self , Warning , msg) ;
962+ let mut db = DiagnosticBuilder :: new ( self , Warning ( None ) , msg) ;
932963 db. emit ( ) ;
933964 }
934965
@@ -1033,13 +1064,10 @@ impl Handler {
10331064 for mut diag in diags. into_iter ( ) {
10341065 diag. update_unstable_expectation_id ( unstable_to_stable) ;
10351066
1036- let stable_id = diag
1037- . level
1038- . get_expectation_id ( )
1039- . expect ( "all diagnostics inside `unstable_expect_diagnostics` must have a `LintExpectationId`" ) ;
1040- inner. fulfilled_expectations . insert ( stable_id) ;
1041-
1042- ( * TRACK_DIAGNOSTICS ) ( & diag) ;
1067+ // Here the diagnostic is given back to `emit_diagnostic` where it was first
1068+ // intercepted. Now it should be processed as usual, since the unstable expectation
1069+ // id is now stable.
1070+ inner. emit_diagnostic ( & mut diag) ;
10431071 }
10441072 }
10451073
@@ -1089,6 +1117,15 @@ impl HandlerInner {
10891117
10901118 // FIXME(eddyb) this should ideally take `diagnostic` by value.
10911119 fn emit_diagnostic ( & mut self , diagnostic : & mut Diagnostic ) -> Option < ErrorGuaranteed > {
1120+ // The `LintExpectationId` can be stable or unstable depending on when it was created.
1121+ // Diagnostics created before the definition of `HirId`s are unstable and can not yet
1122+ // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
1123+ // a stable one by the `LintLevelsBuilder`.
1124+ if let Some ( LintExpectationId :: Unstable { .. } ) = diagnostic. level . get_expectation_id ( ) {
1125+ self . unstable_expect_diagnostics . push ( diagnostic. clone ( ) ) ;
1126+ return None ;
1127+ }
1128+
10921129 if diagnostic. level == Level :: DelayedBug {
10931130 // FIXME(eddyb) this should check for `has_errors` and stop pushing
10941131 // once *any* errors were emitted (and truncate `delayed_span_bugs`
@@ -1105,7 +1142,12 @@ impl HandlerInner {
11051142 self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
11061143 }
11071144
1108- if diagnostic. level == Warning
1145+ if let Some ( expectation_id) = diagnostic. level . get_expectation_id ( ) {
1146+ self . suppressed_expected_diag = true ;
1147+ self . fulfilled_expectations . insert ( expectation_id) ;
1148+ }
1149+
1150+ if matches ! ( diagnostic. level, Warning ( _) )
11091151 && !self . flags . can_emit_warnings
11101152 && !diagnostic. is_force_warn ( )
11111153 {
@@ -1115,22 +1157,9 @@ impl HandlerInner {
11151157 return None ;
11161158 }
11171159
1118- // The `LintExpectationId` can be stable or unstable depending on when it was created.
1119- // Diagnostics created before the definition of `HirId`s are unstable and can not yet
1120- // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
1121- // a stable one by the `LintLevelsBuilder`.
1122- if let Level :: Expect ( LintExpectationId :: Unstable { .. } ) = diagnostic. level {
1123- self . unstable_expect_diagnostics . push ( diagnostic. clone ( ) ) ;
1124- return None ;
1125- }
1126-
11271160 ( * TRACK_DIAGNOSTICS ) ( diagnostic) ;
11281161
1129- if let Level :: Expect ( expectation_id) = diagnostic. level {
1130- self . suppressed_expected_diag = true ;
1131- self . fulfilled_expectations . insert ( expectation_id) ;
1132- return None ;
1133- } else if diagnostic. level == Allow {
1162+ if matches ! ( diagnostic. level, Level :: Expect ( _) | Level :: Allow ) {
11341163 return None ;
11351164 }
11361165
@@ -1167,7 +1196,7 @@ impl HandlerInner {
11671196 self . emitter . emit_diagnostic ( & diagnostic) ;
11681197 if diagnostic. is_error ( ) {
11691198 self . deduplicated_err_count += 1 ;
1170- } else if diagnostic . level == Warning {
1199+ } else if let Warning ( _ ) = diagnostic . level {
11711200 self . deduplicated_warn_count += 1 ;
11721201 }
11731202 }
@@ -1220,7 +1249,7 @@ impl HandlerInner {
12201249 match ( errors. len ( ) , warnings. len ( ) ) {
12211250 ( 0 , 0 ) => return ,
12221251 ( 0 , _) => self . emitter . emit_diagnostic ( & Diagnostic :: new (
1223- Level :: Warning ,
1252+ Level :: Warning ( None ) ,
12241253 DiagnosticMessage :: Str ( warnings) ,
12251254 ) ) ,
12261255 ( _, 0 ) => {
@@ -1453,7 +1482,10 @@ pub enum Level {
14531482 /// If this error comes from a lint, don't abort compilation even when abort_if_errors() is called.
14541483 lint : bool ,
14551484 } ,
1456- Warning ,
1485+ /// This [`LintExpectationId`] is used for expected lint diagnostics, which should
1486+ /// also emit a warning due to the `force-warn` flag. In all other cases this should
1487+ /// be `None`.
1488+ Warning ( Option < LintExpectationId > ) ,
14571489 Note ,
14581490 /// A note that is only emitted once.
14591491 OnceNote ,
@@ -1476,7 +1508,7 @@ impl Level {
14761508 Bug | DelayedBug | Fatal | Error { .. } => {
14771509 spec. set_fg ( Some ( Color :: Red ) ) . set_intense ( true ) ;
14781510 }
1479- Warning => {
1511+ Warning ( _ ) => {
14801512 spec. set_fg ( Some ( Color :: Yellow ) ) . set_intense ( cfg ! ( windows) ) ;
14811513 }
14821514 Note | OnceNote => {
@@ -1495,7 +1527,7 @@ impl Level {
14951527 match self {
14961528 Bug | DelayedBug => "error: internal compiler error" ,
14971529 Fatal | Error { .. } => "error" ,
1498- Warning => "warning" ,
1530+ Warning ( _ ) => "warning" ,
14991531 Note | OnceNote => "note" ,
15001532 Help => "help" ,
15011533 FailureNote => "failure-note" ,
@@ -1510,7 +1542,7 @@ impl Level {
15101542
15111543 pub fn get_expectation_id ( & self ) -> Option < LintExpectationId > {
15121544 match self {
1513- Level :: Expect ( id) => Some ( * id) ,
1545+ Level :: Expect ( id) | Level :: Warning ( Some ( id ) ) => Some ( * id) ,
15141546 _ => None ,
15151547 }
15161548 }
0 commit comments