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