@@ -526,12 +526,15 @@ pub enum StashKey {
526526 UndeterminedMacroResolution ,
527527}
528528
529- fn default_track_diagnostic ( diag : DiagInner , f : & mut dyn FnMut ( DiagInner ) ) {
529+ fn default_track_diagnostic < R > ( diag : DiagInner , f : & mut dyn FnMut ( DiagInner ) -> R ) -> R {
530530 ( * f) ( diag)
531531}
532532
533- pub static TRACK_DIAGNOSTIC : AtomicRef < fn ( DiagInner , & mut dyn FnMut ( DiagInner ) ) > =
534- AtomicRef :: new ( & ( default_track_diagnostic as _ ) ) ;
533+ /// Diagnostics emitted by `DiagCtxtInner::emit_diagnostic` are passed through this function. Used
534+ /// for tracking by incremental, to replay diagnostics as necessary.
535+ pub static TRACK_DIAGNOSTIC : AtomicRef <
536+ fn ( DiagInner , & mut dyn FnMut ( DiagInner ) -> Option < ErrorGuaranteed > ) -> Option < ErrorGuaranteed > ,
537+ > = AtomicRef :: new ( & ( default_track_diagnostic as _ ) ) ;
535538
536539#[ derive( Copy , Clone , Default ) ]
537540pub struct DiagCtxtFlags {
@@ -1422,74 +1425,103 @@ impl DiagCtxtInner {
14221425
14231426 // Return value is only `Some` if the level is `Error` or `DelayedBug`.
14241427 fn emit_diagnostic ( & mut self , mut diagnostic : DiagInner ) -> Option < ErrorGuaranteed > {
1425- assert ! ( diagnostic. level. can_be_top_or_sub( ) . 0 ) ;
1426-
1427- if let Some ( expectation_id) = diagnostic. level . get_expectation_id ( ) {
1428- // The `LintExpectationId` can be stable or unstable depending on when it was created.
1429- // Diagnostics created before the definition of `HirId`s are unstable and can not yet
1430- // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by
1431- // a stable one by the `LintLevelsBuilder`.
1432- if let LintExpectationId :: Unstable { .. } = expectation_id {
1433- self . unstable_expect_diagnostics . push ( diagnostic) ;
1434- return None ;
1435- }
1436- self . suppressed_expected_diag = true ;
1437- self . fulfilled_expectations . insert ( expectation_id. normalize ( ) ) ;
1438- }
1439-
14401428 if diagnostic. has_future_breakage ( ) {
14411429 // Future breakages aren't emitted if they're `Level::Allow`,
14421430 // but they still need to be constructed and stashed below,
14431431 // so they'll trigger the must_produce_diag check.
1444- self . suppressed_expected_diag = true ;
1432+ assert ! ( matches! ( diagnostic . level , Error | Warning | Allow ) ) ;
14451433 self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
14461434 }
14471435
1448- // Note that because this comes before the `match` below,
1449- // `-Zeagerly-emit-delayed-bugs` continues to work even after we've
1450- // issued an error and stopped recording new delayed bugs.
1451- if diagnostic. level == DelayedBug && self . flags . eagerly_emit_delayed_bugs {
1452- diagnostic. level = Error ;
1453- }
1454-
1436+ // We call TRACK_DIAGNOSTIC with an empty closure for the cases that
1437+ // return early *and* have some kind of side-effect, except where
1438+ // noted.
14551439 match diagnostic. level {
1456- // This must come after the possible promotion of `DelayedBug` to
1457- // `Error` above.
1458- Fatal | Error if self . treat_next_err_as_bug ( ) => {
1459- diagnostic. level = Bug ;
1440+ Bug => { }
1441+ Fatal | Error => {
1442+ if self . treat_next_err_as_bug ( ) {
1443+ // `Fatal` and `Error` can be promoted to `Bug`.
1444+ diagnostic. level = Bug ;
1445+ }
14601446 }
14611447 DelayedBug => {
1462- // If we have already emitted at least one error, we don't need
1463- // to record the delayed bug, because it'll never be used.
1464- return if let Some ( guar) = self . has_errors ( ) {
1465- Some ( guar)
1448+ // Note that because we check these conditions first,
1449+ // `-Zeagerly-emit-delayed-bugs` and `-Ztreat-err-as-bug`
1450+ // continue to work even after we've issued an error and
1451+ // stopped recording new delayed bugs.
1452+ if self . flags . eagerly_emit_delayed_bugs {
1453+ // `DelayedBug` can be promoted to `Error` or `Bug`.
1454+ if self . treat_next_err_as_bug ( ) {
1455+ diagnostic. level = Bug ;
1456+ } else {
1457+ diagnostic. level = Error ;
1458+ }
14661459 } else {
1467- let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
1468- // This `unchecked_error_guaranteed` is valid. It is where the
1469- // `ErrorGuaranteed` for delayed bugs originates. See
1470- // `DiagCtxtInner::drop`.
1471- #[ allow( deprecated) ]
1472- let guar = ErrorGuaranteed :: unchecked_error_guaranteed ( ) ;
1473- self . delayed_bugs
1474- . push ( ( DelayedDiagInner :: with_backtrace ( diagnostic, backtrace) , guar) ) ;
1475- Some ( guar)
1476- } ;
1460+ // If we have already emitted at least one error, we don't need
1461+ // to record the delayed bug, because it'll never be used.
1462+ return if let Some ( guar) = self . has_errors ( ) {
1463+ Some ( guar)
1464+ } else {
1465+ // No `TRACK_DIAGNOSTIC` call is needed, because the
1466+ // incremental session is deleted if there is a delayed
1467+ // bug. This also saves us from cloning the diagnostic.
1468+ let backtrace = std:: backtrace:: Backtrace :: capture ( ) ;
1469+ // This `unchecked_error_guaranteed` is valid. It is where the
1470+ // `ErrorGuaranteed` for delayed bugs originates. See
1471+ // `DiagCtxtInner::drop`.
1472+ #[ allow( deprecated) ]
1473+ let guar = ErrorGuaranteed :: unchecked_error_guaranteed ( ) ;
1474+ self . delayed_bugs
1475+ . push ( ( DelayedDiagInner :: with_backtrace ( diagnostic, backtrace) , guar) ) ;
1476+ Some ( guar)
1477+ } ;
1478+ }
1479+ }
1480+ ForceWarning ( None ) => { } // `ForceWarning(Some(...))` is below, with `Expect`
1481+ Warning => {
1482+ if !self . flags . can_emit_warnings {
1483+ // We are not emitting warnings.
1484+ if diagnostic. has_future_breakage ( ) {
1485+ // The side-effect is at the top of this method.
1486+ TRACK_DIAGNOSTIC ( diagnostic, & mut |_| None ) ;
1487+ }
1488+ return None ;
1489+ }
14771490 }
1478- Warning if !self . flags . can_emit_warnings => {
1491+ Note | Help | FailureNote => { }
1492+ OnceNote | OnceHelp => panic ! ( "bad level: {:?}" , diagnostic. level) ,
1493+ Allow => {
1494+ // Nothing emitted for allowed lints.
14791495 if diagnostic. has_future_breakage ( ) {
1480- ( * TRACK_DIAGNOSTIC ) ( diagnostic, & mut |_| { } ) ;
1496+ // The side-effect is at the top of this method.
1497+ TRACK_DIAGNOSTIC ( diagnostic, & mut |_| None ) ;
1498+ self . suppressed_expected_diag = true ;
14811499 }
14821500 return None ;
14831501 }
1484- Allow | Expect ( _) => {
1485- ( * TRACK_DIAGNOSTIC ) ( diagnostic, & mut |_| { } ) ;
1486- return None ;
1502+ Expect ( expect_id) | ForceWarning ( Some ( expect_id) ) => {
1503+ // Diagnostics created before the definition of `HirId`s are
1504+ // unstable and can not yet be stored. Instead, they are
1505+ // buffered until the `LintExpectationId` is replaced by a
1506+ // stable one by the `LintLevelsBuilder`.
1507+ if let LintExpectationId :: Unstable { .. } = expect_id {
1508+ // We don't call TRACK_DIAGNOSTIC because we wait for the
1509+ // unstable ID to be updated, whereupon the diagnostic will
1510+ // be passed into this method again.
1511+ self . unstable_expect_diagnostics . push ( diagnostic) ;
1512+ return None ;
1513+ }
1514+ self . fulfilled_expectations . insert ( expect_id. normalize ( ) ) ;
1515+ if let Expect ( _) = diagnostic. level {
1516+ // Nothing emitted here for expected lints.
1517+ TRACK_DIAGNOSTIC ( diagnostic, & mut |_| None ) ;
1518+ self . suppressed_expected_diag = true ;
1519+ return None ;
1520+ }
14871521 }
1488- _ => { }
14891522 }
14901523
1491- let mut guaranteed = None ;
1492- ( * TRACK_DIAGNOSTIC ) ( diagnostic, & mut |mut diagnostic| {
1524+ TRACK_DIAGNOSTIC ( diagnostic, & mut |mut diagnostic| {
14931525 if let Some ( code) = diagnostic. code {
14941526 self . emitted_diagnostic_codes . insert ( code) ;
14951527 }
@@ -1552,17 +1584,17 @@ impl DiagCtxtInner {
15521584 // `ErrorGuaranteed` for errors and lint errors originates.
15531585 #[ allow( deprecated) ]
15541586 let guar = ErrorGuaranteed :: unchecked_error_guaranteed ( ) ;
1555- guaranteed = Some ( guar) ;
15561587 if is_lint {
15571588 self . lint_err_guars . push ( guar) ;
15581589 } else {
15591590 self . err_guars . push ( guar) ;
15601591 }
15611592 self . panic_if_treat_err_as_bug ( ) ;
1593+ Some ( guar)
1594+ } else {
1595+ None
15621596 }
1563- } ) ;
1564-
1565- guaranteed
1597+ } )
15661598 }
15671599
15681600 fn treat_err_as_bug ( & self ) -> bool {
@@ -1863,23 +1895,13 @@ impl Level {
18631895 matches ! ( * self , FailureNote )
18641896 }
18651897
1866- pub fn get_expectation_id ( & self ) -> Option < LintExpectationId > {
1867- match self {
1868- Expect ( id) | ForceWarning ( Some ( id) ) => Some ( * id) ,
1869- _ => None ,
1870- }
1871- }
1872-
1873- // Can this level be used in a top-level diagnostic message and/or a
1874- // subdiagnostic message?
1875- fn can_be_top_or_sub ( & self ) -> ( bool , bool ) {
1898+ // Can this level be used in a subdiagnostic message?
1899+ fn can_be_subdiag ( & self ) -> bool {
18761900 match self {
18771901 Bug | DelayedBug | Fatal | Error | ForceWarning ( _) | FailureNote | Allow
1878- | Expect ( _) => ( true , false ) ,
1879-
1880- Warning | Note | Help => ( true , true ) ,
1902+ | Expect ( _) => false ,
18811903
1882- OnceNote | OnceHelp => ( false , true ) ,
1904+ Warning | Note | Help | OnceNote | OnceHelp => true ,
18831905 }
18841906 }
18851907}
0 commit comments