1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use std::fmt::Display; 4 5 use proc_macro2::TokenStream; 6 use quote::quote_spanned; 7 use syn::{spanned::Spanned, Error}; 8 9 pub(crate) struct DiagCtxt(TokenStream); 10 pub(crate) struct ErrorGuaranteed(()); 11 12 impl DiagCtxt { 13 pub(crate) fn error(&mut self, span: impl Spanned, msg: impl Display) -> ErrorGuaranteed { 14 let error = Error::new(span.span(), msg); 15 self.0.extend(error.into_compile_error()); 16 ErrorGuaranteed(()) 17 } 18 19 pub(crate) fn warn(&mut self, span: impl Spanned, msg: impl Display) { 20 // Have the message start on a new line for visual clarity. 21 let msg = format!("\n{}", msg); 22 self.0.extend(quote_spanned!(span.span() => 23 // Approximate using deprecated warning while `proc_macro_diagnostic` is unstable. 24 const _: () = { 25 #[deprecated = #msg] 26 const fn warn() {} 27 warn(); 28 }; 29 )); 30 } 31 32 pub(crate) fn with( 33 fun: impl FnOnce(&mut DiagCtxt) -> Result<TokenStream, ErrorGuaranteed>, 34 ) -> TokenStream { 35 let mut dcx = Self(TokenStream::new()); 36 match fun(&mut dcx) { 37 Ok(mut stream) => { 38 stream.extend(dcx.0); 39 stream 40 } 41 Err(ErrorGuaranteed(())) => dcx.0, 42 } 43 } 44 } 45