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