@@ -589,7 +589,8 @@ struct DiagCtxtInner {
589
589
/// add more information). All stashed diagnostics must be emitted with
590
590
/// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
591
591
/// otherwise an assertion failure will occur.
592
- stashed_diagnostics : FxIndexMap < ( Span , StashKey ) , ( DiagInner , Option < ErrorGuaranteed > ) > ,
592
+ stashed_diagnostics :
593
+ FxIndexMap < StashKey , FxIndexMap < Span , ( DiagInner , Option < ErrorGuaranteed > ) > > ,
593
594
594
595
future_breakage_diagnostics : Vec < DiagInner > ,
595
596
@@ -912,8 +913,12 @@ impl<'a> DiagCtxtHandle<'a> {
912
913
// FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
913
914
// if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
914
915
// See the PR for a discussion.
915
- let key = ( span. with_parent ( None ) , key) ;
916
- self . inner . borrow_mut ( ) . stashed_diagnostics . insert ( key, ( diag, guar) ) ;
916
+ self . inner
917
+ . borrow_mut ( )
918
+ . stashed_diagnostics
919
+ . entry ( key)
920
+ . or_default ( )
921
+ . insert ( span. with_parent ( None ) , ( diag, guar) ) ;
917
922
918
923
guar
919
924
}
@@ -922,9 +927,10 @@ impl<'a> DiagCtxtHandle<'a> {
922
927
/// and [`StashKey`] as the key. Panics if the found diagnostic is an
923
928
/// error.
924
929
pub fn steal_non_err ( self , span : Span , key : StashKey ) -> Option < Diag < ' a , ( ) > > {
925
- let key = ( span. with_parent ( None ) , key) ;
926
930
// FIXME(#120456) - is `swap_remove` correct?
927
- let ( diag, guar) = self . inner . borrow_mut ( ) . stashed_diagnostics . swap_remove ( & key) ?;
931
+ let ( diag, guar) = self . inner . borrow_mut ( ) . stashed_diagnostics . get_mut ( & key) . and_then (
932
+ |stashed_diagnostics| stashed_diagnostics. swap_remove ( & span. with_parent ( None ) ) ,
933
+ ) ?;
928
934
assert ! ( !diag. is_error( ) ) ;
929
935
assert ! ( guar. is_none( ) ) ;
930
936
Some ( Diag :: new_diagnostic ( self , diag) )
@@ -943,9 +949,10 @@ impl<'a> DiagCtxtHandle<'a> {
943
949
where
944
950
F : FnMut ( & mut Diag < ' _ > ) ,
945
951
{
946
- let key = ( span. with_parent ( None ) , key) ;
947
952
// FIXME(#120456) - is `swap_remove` correct?
948
- let err = self . inner . borrow_mut ( ) . stashed_diagnostics . swap_remove ( & key) ;
953
+ let err = self . inner . borrow_mut ( ) . stashed_diagnostics . get_mut ( & key) . and_then (
954
+ |stashed_diagnostics| stashed_diagnostics. swap_remove ( & span. with_parent ( None ) ) ,
955
+ ) ;
949
956
err. map ( |( err, guar) | {
950
957
// The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
951
958
assert_eq ! ( err. level, Error ) ;
@@ -966,9 +973,10 @@ impl<'a> DiagCtxtHandle<'a> {
966
973
key : StashKey ,
967
974
new_err : Diag < ' _ > ,
968
975
) -> ErrorGuaranteed {
969
- let key = ( span. with_parent ( None ) , key) ;
970
976
// FIXME(#120456) - is `swap_remove` correct?
971
- let old_err = self . inner . borrow_mut ( ) . stashed_diagnostics . swap_remove ( & key) ;
977
+ let old_err = self . inner . borrow_mut ( ) . stashed_diagnostics . get_mut ( & key) . and_then (
978
+ |stashed_diagnostics| stashed_diagnostics. swap_remove ( & span. with_parent ( None ) ) ,
979
+ ) ;
972
980
match old_err {
973
981
Some ( ( old_err, guar) ) => {
974
982
assert_eq ! ( old_err. level, Error ) ;
@@ -983,7 +991,14 @@ impl<'a> DiagCtxtHandle<'a> {
983
991
}
984
992
985
993
pub fn has_stashed_diagnostic ( & self , span : Span , key : StashKey ) -> bool {
986
- self . inner . borrow ( ) . stashed_diagnostics . get ( & ( span. with_parent ( None ) , key) ) . is_some ( )
994
+ let inner = self . inner . borrow ( ) ;
995
+ if let Some ( stashed_diagnostics) = inner. stashed_diagnostics . get ( & key)
996
+ && !stashed_diagnostics. is_empty ( )
997
+ {
998
+ stashed_diagnostics. contains_key ( & span. with_parent ( None ) )
999
+ } else {
1000
+ false
1001
+ }
987
1002
}
988
1003
989
1004
/// Emit all stashed diagnostics.
@@ -997,7 +1012,11 @@ impl<'a> DiagCtxtHandle<'a> {
997
1012
let inner = self . inner . borrow ( ) ;
998
1013
inner. err_guars . len ( )
999
1014
+ inner. lint_err_guars . len ( )
1000
- + inner. stashed_diagnostics . values ( ) . filter ( |( _diag, guar) | guar. is_some ( ) ) . count ( )
1015
+ + inner
1016
+ . stashed_diagnostics
1017
+ . values ( )
1018
+ . map ( |a| a. values ( ) . filter ( |( _, guar) | guar. is_some ( ) ) . count ( ) )
1019
+ . sum :: < usize > ( )
1001
1020
}
1002
1021
1003
1022
/// This excludes lint errors and delayed bugs. Unless absolutely
@@ -1486,16 +1505,18 @@ impl DiagCtxtInner {
1486
1505
fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
1487
1506
let mut guar = None ;
1488
1507
let has_errors = !self . err_guars . is_empty ( ) ;
1489
- for ( _, ( diag, _guar) ) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1490
- if !diag. is_error ( ) {
1491
- // Unless they're forced, don't flush stashed warnings when
1492
- // there are errors, to avoid causing warning overload. The
1493
- // stash would've been stolen already if it were important.
1494
- if !diag. is_force_warn ( ) && has_errors {
1495
- continue ;
1508
+ for ( _, stashed_diagnostics) in std:: mem:: take ( & mut self . stashed_diagnostics ) . into_iter ( ) {
1509
+ for ( _, ( diag, _guar) ) in stashed_diagnostics {
1510
+ if !diag. is_error ( ) {
1511
+ // Unless they're forced, don't flush stashed warnings when
1512
+ // there are errors, to avoid causing warning overload. The
1513
+ // stash would've been stolen already if it were important.
1514
+ if !diag. is_force_warn ( ) && has_errors {
1515
+ continue ;
1516
+ }
1496
1517
}
1518
+ guar = guar. or ( self . emit_diagnostic ( diag, None ) ) ;
1497
1519
}
1498
- guar = guar. or ( self . emit_diagnostic ( diag, None ) ) ;
1499
1520
}
1500
1521
guar
1501
1522
}
@@ -1688,6 +1709,7 @@ impl DiagCtxtInner {
1688
1709
if let Some ( ( _diag, guar) ) = self
1689
1710
. stashed_diagnostics
1690
1711
. values ( )
1712
+ . flat_map ( |stashed_diagnostics| stashed_diagnostics. values ( ) )
1691
1713
. find ( |( diag, guar) | guar. is_some ( ) && diag. is_lint . is_none ( ) )
1692
1714
{
1693
1715
* guar
@@ -1700,13 +1722,9 @@ impl DiagCtxtInner {
1700
1722
fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
1701
1723
self . err_guars . get ( 0 ) . copied ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) ) . or_else (
1702
1724
|| {
1703
- if let Some ( ( _diag, guar) ) =
1704
- self . stashed_diagnostics . values ( ) . find ( |( _diag, guar) | guar. is_some ( ) )
1705
- {
1706
- * guar
1707
- } else {
1708
- None
1709
- }
1725
+ self . stashed_diagnostics . values ( ) . find_map ( |stashed_diagnostics| {
1726
+ stashed_diagnostics. values ( ) . find_map ( |( _, guar) | * guar)
1727
+ } )
1710
1728
} ,
1711
1729
)
1712
1730
}
0 commit comments