1 //! A trait that can provide the `Span` of the complete contents of a syntax 2 //! tree node. 3 //! 4 //! <br> 5 //! 6 //! # Example 7 //! 8 //! Suppose in a procedural macro we have a [`Type`] that we want to assert 9 //! implements the [`Sync`] trait. Maybe this is the type of one of the fields 10 //! of a struct for which we are deriving a trait implementation, and we need to 11 //! be able to pass a reference to one of those fields across threads. 12 //! 13 //! [`Type`]: crate::Type 14 //! [`Sync`]: std::marker::Sync 15 //! 16 //! If the field type does *not* implement `Sync` as required, we want the 17 //! compiler to report an error pointing out exactly which type it was. 18 //! 19 //! The following macro code takes a variable `ty` of type `Type` and produces a 20 //! static assertion that `Sync` is implemented for that type. 21 //! 22 //! ``` 23 //! # extern crate proc_macro; 24 //! # 25 //! use proc_macro::TokenStream; 26 //! use proc_macro2::Span; 27 //! use quote::quote_spanned; 28 //! use syn::Type; 29 //! use syn::spanned::Spanned; 30 //! 31 //! # const IGNORE_TOKENS: &str = stringify! { 32 //! #[proc_macro_derive(MyMacro)] 33 //! # }; 34 //! pub fn my_macro(input: TokenStream) -> TokenStream { 35 //! # let ty = get_a_type(); 36 //! /* ... */ 37 //! 38 //! let assert_sync = quote_spanned! {ty.span()=> 39 //! struct _AssertSync where #ty: Sync; 40 //! }; 41 //! 42 //! /* ... */ 43 //! # input 44 //! } 45 //! # 46 //! # fn get_a_type() -> Type { 47 //! # unimplemented!() 48 //! # } 49 //! ``` 50 //! 51 //! By inserting this `assert_sync` fragment into the output code generated by 52 //! our macro, the user's code will fail to compile if `ty` does not implement 53 //! `Sync`. The errors they would see look like the following. 54 //! 55 //! ```text 56 //! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied 57 //! --> src/main.rs:10:21 58 //! | 59 //! 10 | bad_field: *const i32, 60 //! | ^^^^^^^^^^ `*const i32` cannot be shared between threads safely 61 //! ``` 62 //! 63 //! In this technique, using the `Type`'s span for the error message makes the 64 //! error appear in the correct place underlining the right type. 65 //! 66 //! <br> 67 //! 68 //! # Limitations 69 //! 70 //! The underlying [`proc_macro::Span::join`] method is nightly-only. When 71 //! called from within a procedural macro in a nightly compiler, `Spanned` will 72 //! use `join` to produce the intended span. When not using a nightly compiler, 73 //! only the span of the *first token* of the syntax tree node is returned. 74 //! 75 //! In the common case of wanting to use the joined span as the span of a 76 //! `syn::Error`, consider instead using [`syn::Error::new_spanned`] which is 77 //! able to span the error correctly under the complete syntax tree node without 78 //! needing the unstable `join`. 79 //! 80 //! [`syn::Error::new_spanned`]: crate::Error::new_spanned 81 82 use proc_macro2::Span; 83 use quote::spanned::Spanned as ToTokens; 84 85 /// A trait that can provide the `Span` of the complete contents of a syntax 86 /// tree node. 87 /// 88 /// This trait is automatically implemented for all types that implement 89 /// [`ToTokens`] from the `quote` crate, as well as for `Span` itself. 90 /// 91 /// [`ToTokens`]: quote::ToTokens 92 /// 93 /// See the [module documentation] for an example. 94 /// 95 /// [module documentation]: self 96 pub trait Spanned: private::Sealed { 97 /// Returns a `Span` covering the complete contents of this syntax tree 98 /// node, or [`Span::call_site()`] if this node is empty. 99 /// 100 /// [`Span::call_site()`]: proc_macro2::Span::call_site span(&self) -> Span101 fn span(&self) -> Span; 102 } 103 104 impl<T: ?Sized + ToTokens> Spanned for T { span(&self) -> Span105 fn span(&self) -> Span { 106 self.__span() 107 } 108 } 109 110 mod private { 111 use crate::spanned::ToTokens; 112 113 pub trait Sealed {} 114 impl<T: ?Sized + ToTokens> Sealed for T {} 115 116 #[cfg(any(feature = "full", feature = "derive"))] 117 impl Sealed for crate::QSelf {} 118 } 119