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
85use proc_macro2::Span;
86use 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.*
102pub 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
107 fn span(&self) -> Span;
108}
109
110impl<T: ?Sized + ToTokens> Spanned for T {
111 fn span(&self) -> Span {
112 self.__span()
113 }
114}
115