@@ -526,12 +526,15 @@ pub enum StashKey {
526
526
UndeterminedMacroResolution ,
527
527
}
528
528
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 {
530
530
( * f) ( diag)
531
531
}
532
532
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 _ ) ) ;
535
538
536
539
#[ derive( Copy , Clone , Default ) ]
537
540
pub struct DiagCtxtFlags {
@@ -1422,74 +1425,103 @@ impl DiagCtxtInner {
1422
1425
1423
1426
// Return value is only `Some` if the level is `Error` or `DelayedBug`.
1424
1427
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
-
1440
1428
if diagnostic. has_future_breakage ( ) {
1441
1429
// Future breakages aren't emitted if they're `Level::Allow`,
1442
1430
// but they still need to be constructed and stashed below,
1443
1431
// so they'll trigger the must_produce_diag check.
1444
- self . suppressed_expected_diag = true ;
1432
+ assert ! ( matches! ( diagnostic . level , Error | Warning | Allow ) ) ;
1445
1433
self . future_breakage_diagnostics . push ( diagnostic. clone ( ) ) ;
1446
1434
}
1447
1435
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.
1455
1439
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
+ }
1460
1446
}
1461
1447
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
+ }
1466
1459
} 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
+ }
1477
1490
}
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.
1479
1495
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 ;
1481
1499
}
1482
1500
return None ;
1483
1501
}
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
+ }
1487
1521
}
1488
- _ => { }
1489
1522
}
1490
1523
1491
- let mut guaranteed = None ;
1492
- ( * TRACK_DIAGNOSTIC ) ( diagnostic, & mut |mut diagnostic| {
1524
+ TRACK_DIAGNOSTIC ( diagnostic, & mut |mut diagnostic| {
1493
1525
if let Some ( code) = diagnostic. code {
1494
1526
self . emitted_diagnostic_codes . insert ( code) ;
1495
1527
}
@@ -1552,17 +1584,17 @@ impl DiagCtxtInner {
1552
1584
// `ErrorGuaranteed` for errors and lint errors originates.
1553
1585
#[ allow( deprecated) ]
1554
1586
let guar = ErrorGuaranteed :: unchecked_error_guaranteed ( ) ;
1555
- guaranteed = Some ( guar) ;
1556
1587
if is_lint {
1557
1588
self . lint_err_guars . push ( guar) ;
1558
1589
} else {
1559
1590
self . err_guars . push ( guar) ;
1560
1591
}
1561
1592
self . panic_if_treat_err_as_bug ( ) ;
1593
+ Some ( guar)
1594
+ } else {
1595
+ None
1562
1596
}
1563
- } ) ;
1564
-
1565
- guaranteed
1597
+ } )
1566
1598
}
1567
1599
1568
1600
fn treat_err_as_bug ( & self ) -> bool {
@@ -1863,23 +1895,13 @@ impl Level {
1863
1895
matches ! ( * self , FailureNote )
1864
1896
}
1865
1897
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 {
1876
1900
match self {
1877
1901
Bug | DelayedBug | Fatal | Error | ForceWarning ( _) | FailureNote | Allow
1878
- | Expect ( _) => ( true , false ) ,
1879
-
1880
- Warning | Note | Help => ( true , true ) ,
1902
+ | Expect ( _) => false ,
1881
1903
1882
- OnceNote | OnceHelp => ( false , true ) ,
1904
+ Warning | Note | Help | OnceNote | OnceHelp => true ,
1883
1905
}
1884
1906
}
1885
1907
}
0 commit comments