rustc_macros/diagnostics/
diagnostic.rs1#![deny(unused_must_use)]
2
3use proc_macro2::TokenStream;
4use quote::quote;
5use synstructure::Structure;
6
7use crate::diagnostics::diagnostic_builder::each_variant;
8use crate::diagnostics::error::DiagnosticDeriveError;
9
10pub(crate) struct DiagnosticDerive<'a> {
12 structure: Structure<'a>,
13}
14
15impl<'a> DiagnosticDerive<'a> {
16 pub(crate) fn new(structure: Structure<'a>) -> Self {
17 Self { structure }
18 }
19
20 pub(crate) fn into_tokens(self) -> TokenStream {
21 let DiagnosticDerive { mut structure } = self;
22 let implementation = each_variant(&mut structure, |mut builder, variant| {
23 let preamble = builder.preamble(variant);
24 let body = builder.body(variant);
25
26 let Some(message) = builder.primary_message() else {
27 return DiagnosticDeriveError::ErrorHandled.to_compile_error();
28 };
29 let message = message.diag_message(Some(variant));
30
31 let init = quote! {
32 let mut diag = rustc_errors::Diag::new(
33 dcx,
34 level,
35 #message
36 );
37 };
38
39 let formatting_init = &builder.formatting_init;
40 quote! {
41 #init
42 #formatting_init
43 #preamble
44 #body
45 diag
46 }
47 });
48
49 structure.gen_impl(quote! {
51 gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self
52 where G: rustc_errors::EmissionGuarantee
53 {
54 #[track_caller]
55 fn into_diag(
56 self,
57 dcx: rustc_errors::DiagCtxtHandle<'_sess>,
58 level: rustc_errors::Level
59 ) -> rustc_errors::Diag<'_sess, G> {
60 #implementation
61 }
62 }
63 })
64 }
65}