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
82use proc_macro2::Span;
83use 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
96pub 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
101 fn span(&self) -> Span;
102}
103
104impl<T: ?Sized + ToTokens> Spanned for T {
105 fn span(&self) -> Span {
106 self.__span()
107 }
108}
109
110mod private {
111 use super::*;
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