@@ -589,7 +589,8 @@ struct DiagCtxtInner {
589589 /// add more information). All stashed diagnostics must be emitted with
590590 /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped,
591591 /// 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 > ) > > ,
593594
594595 future_breakage_diagnostics : Vec < DiagInner > ,
595596
@@ -912,8 +913,12 @@ impl<'a> DiagCtxtHandle<'a> {
912913 // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
913914 // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
914915 // 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) ) ;
917922
918923 guar
919924 }
@@ -922,9 +927,10 @@ impl<'a> DiagCtxtHandle<'a> {
922927 /// and [`StashKey`] as the key. Panics if the found diagnostic is an
923928 /// error.
924929 pub fn steal_non_err ( self , span : Span , key : StashKey ) -> Option < Diag < ' a , ( ) > > {
925- let key = ( span. with_parent ( None ) , key) ;
926930 // 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+ ) ?;
928934 assert ! ( !diag. is_error( ) ) ;
929935 assert ! ( guar. is_none( ) ) ;
930936 Some ( Diag :: new_diagnostic ( self , diag) )
@@ -943,9 +949,10 @@ impl<'a> DiagCtxtHandle<'a> {
943949 where
944950 F : FnMut ( & mut Diag < ' _ > ) ,
945951 {
946- let key = ( span. with_parent ( None ) , key) ;
947952 // 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+ ) ;
949956 err. map ( |( err, guar) | {
950957 // The use of `::<ErrorGuaranteed>` is safe because level is `Level::Error`.
951958 assert_eq ! ( err. level, Error ) ;
@@ -966,9 +973,10 @@ impl<'a> DiagCtxtHandle<'a> {
966973 key : StashKey ,
967974 new_err : Diag < ' _ > ,
968975 ) -> ErrorGuaranteed {
969- let key = ( span. with_parent ( None ) , key) ;
970976 // 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+ ) ;
972980 match old_err {
973981 Some ( ( old_err, guar) ) => {
974982 assert_eq ! ( old_err. level, Error ) ;
@@ -983,7 +991,14 @@ impl<'a> DiagCtxtHandle<'a> {
983991 }
984992
985993 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+ }
9871002 }
9881003
9891004 /// Emit all stashed diagnostics.
@@ -997,7 +1012,11 @@ impl<'a> DiagCtxtHandle<'a> {
9971012 let inner = self . inner . borrow ( ) ;
9981013 inner. err_guars . len ( )
9991014 + 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 > ( )
10011020 }
10021021
10031022 /// This excludes lint errors and delayed bugs. Unless absolutely
@@ -1486,16 +1505,18 @@ impl DiagCtxtInner {
14861505 fn emit_stashed_diagnostics ( & mut self ) -> Option < ErrorGuaranteed > {
14871506 let mut guar = None ;
14881507 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+ }
14961517 }
1518+ guar = guar. or ( self . emit_diagnostic ( diag, None ) ) ;
14971519 }
1498- guar = guar. or ( self . emit_diagnostic ( diag, None ) ) ;
14991520 }
15001521 guar
15011522 }
@@ -1688,6 +1709,7 @@ impl DiagCtxtInner {
16881709 if let Some ( ( _diag, guar) ) = self
16891710 . stashed_diagnostics
16901711 . values ( )
1712+ . flat_map ( |stashed_diagnostics| stashed_diagnostics. values ( ) )
16911713 . find ( |( diag, guar) | guar. is_some ( ) && diag. is_lint . is_none ( ) )
16921714 {
16931715 * guar
@@ -1700,13 +1722,9 @@ impl DiagCtxtInner {
17001722 fn has_errors ( & self ) -> Option < ErrorGuaranteed > {
17011723 self . err_guars . get ( 0 ) . copied ( ) . or_else ( || self . lint_err_guars . get ( 0 ) . copied ( ) ) . or_else (
17021724 || {
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+ } )
17101728 } ,
17111729 )
17121730 }
0 commit comments