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`]: crate::Type
17 //! [`Sync`]: std::marker::Sync
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