spanned.rs 3.7 KB

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