File Index
Files and directories
Sign in
FILE

spanned.rs

File preview with syntax highlighting.

linux-6.19.14/rust/syn/spanned.rs RUST
  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}
~/ Read-only file preview.