@@ -1532,26 +1532,46 @@ impl DiagCtxtInner {
15321532 self . emit_diagnostic ( Diagnostic :: new ( Note , note2) ) ;
15331533 }
15341534
1535- let mut bug =
1536- if backtrace || self . ice_file . is_none ( ) { bug. decorate ( self ) } else { bug. inner } ;
1537-
1538- // "Undelay" the delayed bugs (into plain `Bug`s).
1539- if bug. level != DelayedBug {
1540- // NOTE(eddyb) not panicking here because we're already producing
1541- // an ICE, and the more information the merrier.
1542- let subdiag = InvalidFlushedDelayedDiagnosticLevel {
1543- span : bug. span . primary_span ( ) . unwrap ( ) ,
1544- level : bug. level ,
1545- } ;
1546- // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
1547- // just uses `DiagCtxtInner` functions.
1548- subdiag. add_to_diagnostic_with ( & mut bug, |diag, msg| {
1549- let args = diag. args ( ) ;
1550- let msg = diag. subdiagnostic_message_to_diagnostic_message ( msg) ;
1551- self . eagerly_translate ( msg, args)
1552- } ) ;
1553- }
1554- bug. level = Bug ;
1535+ // This is a bit gnarly, but the `AddToDiagnostic` type uses a `DiagCtxt` to trigger
1536+ // translation. It could take an emitter or a `DiagCtxtInner` but it would make
1537+ // every other use of `AddToDiagnostic` more complex. This function is only invoked
1538+ // during the `Drop` of `DiagCtxtInner`, so we temporarily get a `T` from the `&mut T`
1539+ // here so we can put this back into a lock and back into a `DiagCtxt` to call the
1540+ // functions from `AddToDiagnostic`.
1541+ //
1542+ // FIXME(davidtwco): `AddToDiagnostic` should eventually be merged with
1543+ // `IntoDiagnostic`, and then the context determined by an associated type, depending
1544+ // on the needs of the specific diagnostic - once this is done, we can make these
1545+ // specific diagnostics take an emitter directly.
1546+ let bug = unsafe {
1547+ let old_dcx = std:: ptr:: read ( self ) ;
1548+ let ( new_dcx, bug) = std:: panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
1549+ let dcx = DiagCtxt { inner : Lock :: new ( old_dcx) } ;
1550+
1551+ let mut bug = if backtrace || self . ice_file . is_none ( ) {
1552+ bug. decorate ( & dcx)
1553+ } else {
1554+ bug. inner
1555+ } ;
1556+
1557+ // "Undelay" the delayed bugs (into plain `Bug`s).
1558+ if bug. level != DelayedBug {
1559+ // NOTE(eddyb) not panicking here because we're already producing
1560+ // an ICE, and the more information the merrier.
1561+ let subdiag = InvalidFlushedDelayedDiagnosticLevel {
1562+ span : bug. span . primary_span ( ) . unwrap ( ) ,
1563+ level : bug. level ,
1564+ } ;
1565+ subdiag. add_to_diagnostic ( & dcx, & mut bug) ;
1566+ }
1567+ bug. level = Bug ;
1568+
1569+ ( dcx. inner . into_inner ( ) , bug)
1570+ } ) )
1571+ . unwrap_or_else ( |_| std:: process:: abort ( ) ) ;
1572+ std:: ptr:: write ( self , new_dcx) ;
1573+ bug
1574+ } ;
15551575
15561576 self . emit_diagnostic ( bug) ;
15571577 }
@@ -1583,15 +1603,7 @@ impl DelayedDiagnostic {
15831603 DelayedDiagnostic { inner : diagnostic, note : backtrace }
15841604 }
15851605
1586- fn decorate ( mut self , dcx : & DiagCtxtInner ) -> Diagnostic {
1587- // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
1588- // just uses `DiagCtxtInner` functions.
1589- let subdiag_with = |diag : & mut Diagnostic , msg| {
1590- let args = diag. args ( ) ;
1591- let msg = diag. subdiagnostic_message_to_diagnostic_message ( msg) ;
1592- dcx. eagerly_translate ( msg, args)
1593- } ;
1594-
1606+ fn decorate ( mut self , dcx : & DiagCtxt ) -> Diagnostic {
15951607 match self . note . status ( ) {
15961608 BacktraceStatus :: Captured => {
15971609 let inner = & self . inner ;
@@ -1600,7 +1612,7 @@ impl DelayedDiagnostic {
16001612 emitted_at : inner. emitted_at . clone ( ) ,
16011613 note : self . note ,
16021614 } ;
1603- subdiag. add_to_diagnostic_with ( & mut self . inner , subdiag_with ) ;
1615+ subdiag. add_to_diagnostic ( dcx , & mut self . inner ) ;
16041616 }
16051617 // Avoid the needless newline when no backtrace has been captured,
16061618 // the display impl should just be a single line.
@@ -1611,7 +1623,7 @@ impl DelayedDiagnostic {
16111623 emitted_at : inner. emitted_at . clone ( ) ,
16121624 note : self . note ,
16131625 } ;
1614- subdiag. add_to_diagnostic_with ( & mut self . inner , subdiag_with ) ;
1626+ subdiag. add_to_diagnostic ( dcx , & mut self . inner ) ;
16151627 }
16161628 }
16171629
0 commit comments