1
1
use crate :: diagnostic:: IntoDiagnosticArg ;
2
2
use crate :: {
3
3
Diagnostic , DiagnosticId , DiagnosticMessage , DiagnosticStyledString , ErrorGuaranteed ,
4
- SubdiagnosticMessage ,
4
+ ExplicitBug , SubdiagnosticMessage ,
5
5
} ;
6
6
use crate :: { Handler , Level , MultiSpan , StashKey } ;
7
7
use rustc_lint_defs:: Applicability ;
@@ -12,6 +12,7 @@ use std::borrow::Cow;
12
12
use std:: fmt:: { self , Debug } ;
13
13
use std:: marker:: PhantomData ;
14
14
use std:: ops:: { Deref , DerefMut } ;
15
+ use std:: panic;
15
16
use std:: thread:: panicking;
16
17
17
18
/// Trait implemented by error types. This should not be implemented manually. Instead, use
@@ -308,6 +309,58 @@ impl EmissionGuarantee for Noted {
308
309
}
309
310
}
310
311
312
+ /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for
313
+ /// bug struct diagnostics.
314
+ #[ derive( Copy , Clone ) ]
315
+ pub struct Bug ;
316
+
317
+ impl < ' a > DiagnosticBuilder < ' a , Bug > {
318
+ /// Convenience function for internal use, clients should use one of the
319
+ /// `struct_*` methods on [`Handler`].
320
+ #[ track_caller]
321
+ pub ( crate ) fn new_bug ( handler : & ' a Handler , message : impl Into < DiagnosticMessage > ) -> Self {
322
+ let diagnostic = Diagnostic :: new_with_code ( Level :: Bug , None , message) ;
323
+ Self :: new_diagnostic_bug ( handler, diagnostic)
324
+ }
325
+
326
+ /// Creates a new `DiagnosticBuilder` with an already constructed
327
+ /// diagnostic.
328
+ pub ( crate ) fn new_diagnostic_bug ( handler : & ' a Handler , diagnostic : Diagnostic ) -> Self {
329
+ debug ! ( "Created new diagnostic bug" ) ;
330
+ Self {
331
+ inner : DiagnosticBuilderInner {
332
+ state : DiagnosticBuilderState :: Emittable ( handler) ,
333
+ diagnostic : Box :: new ( diagnostic) ,
334
+ } ,
335
+ _marker : PhantomData ,
336
+ }
337
+ }
338
+ }
339
+
340
+ impl EmissionGuarantee for Bug {
341
+ fn diagnostic_builder_emit_producing_guarantee ( db : & mut DiagnosticBuilder < ' _ , Self > ) -> Self {
342
+ match db. inner . state {
343
+ // First `.emit()` call, the `&Handler` is still available.
344
+ DiagnosticBuilderState :: Emittable ( handler) => {
345
+ db. inner . state = DiagnosticBuilderState :: AlreadyEmittedOrDuringCancellation ;
346
+
347
+ handler. emit_diagnostic ( & mut db. inner . diagnostic ) ;
348
+ }
349
+ // `.emit()` was previously called, disallowed from repeating it.
350
+ DiagnosticBuilderState :: AlreadyEmittedOrDuringCancellation => { }
351
+ }
352
+ // Then panic. No need to return the marker type.
353
+ panic:: panic_any ( ExplicitBug ) ;
354
+ }
355
+
356
+ fn make_diagnostic_builder (
357
+ handler : & Handler ,
358
+ msg : impl Into < DiagnosticMessage > ,
359
+ ) -> DiagnosticBuilder < ' _ , Self > {
360
+ DiagnosticBuilder :: new_bug ( handler, msg)
361
+ }
362
+ }
363
+
311
364
impl < ' a > DiagnosticBuilder < ' a , !> {
312
365
/// Convenience function for internal use, clients should use one of the
313
366
/// `struct_*` methods on [`Handler`].
0 commit comments