]>
Commit | Line | Data |
---|---|---|
c30ab7b3 | 1 | //! A support library for macro authors when defining new macros. |
9e0c209e | 2 | //! |
c30ab7b3 | 3 | //! This library, provided by the standard distribution, provides the types |
94b46f34 | 4 | //! consumed in the interfaces of procedurally defined macro definitions such as |
b7449926 | 5 | //! function-like macros `#[proc_macro]`, macro attributes `#[proc_macro_attribute]` and |
94b46f34 | 6 | //! custom derive attributes`#[proc_macro_derive]`. |
9e0c209e | 7 | //! |
9fa01778 XL |
8 | //! See [the book] for more. |
9 | //! | |
10 | //! [the book]: ../book/ch19-06-macros.html#procedural-macros-for-generating-code-from-attributes | |
9e0c209e | 11 | |
476ff2be | 12 | #![stable(feature = "proc_macro_lib", since = "1.15.0")] |
c30ab7b3 | 13 | #![deny(missing_docs)] |
dfeec247 | 14 | #![doc( |
dfeec247 XL |
15 | html_playground_url = "https://play.rust-lang.org/", |
16 | issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", | |
17 | test(no_crate_inject, attr(deny(warnings))), | |
18 | test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) | |
19 | )] | |
fc512014 | 20 | #![feature(rustc_allow_const_fn_unstable)] |
0bf4aa26 | 21 | #![feature(nll)] |
c30ab7b3 | 22 | #![feature(staged_api)] |
17df50a5 | 23 | #![feature(const_fn_trait_bound)] |
29967ef6 | 24 | #![feature(const_fn_fn_ptr_basics)] |
e1599b0c | 25 | #![feature(allow_internal_unstable)] |
e1599b0c | 26 | #![feature(decl_macro)] |
a1dfa0c6 | 27 | #![feature(extern_types)] |
f9f354fc | 28 | #![feature(negative_impls)] |
5869c6ff | 29 | #![feature(auto_traits)] |
3dfed10e | 30 | #![feature(restricted_std)] |
e1599b0c | 31 | #![feature(rustc_attrs)] |
f9f354fc | 32 | #![feature(min_specialization)] |
5099ac24 | 33 | #![feature(panic_update_hook)] |
dfeec247 | 34 | #![recursion_limit = "256"] |
94b46f34 | 35 | |
8faf50e0 XL |
36 | #[unstable(feature = "proc_macro_internals", issue = "27812")] |
37 | #[doc(hidden)] | |
a1dfa0c6 | 38 | pub mod bridge; |
8faf50e0 | 39 | |
ea8adc8c XL |
40 | mod diagnostic; |
41 | ||
b7449926 | 42 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
0bf4aa26 | 43 | pub use diagnostic::{Diagnostic, Level, MultiSpan}; |
9e0c209e | 44 | |
f9f354fc | 45 | use std::cmp::Ordering; |
17df50a5 | 46 | use std::ops::RangeBounds; |
8faf50e0 | 47 | use std::path::PathBuf; |
c30ab7b3 | 48 | use std::str::FromStr; |
ba9703b0 | 49 | use std::{error, fmt, iter, mem}; |
c30ab7b3 | 50 | |
f9f354fc XL |
51 | /// Determines whether proc_macro has been made accessible to the currently |
52 | /// running program. | |
53 | /// | |
54 | /// The proc_macro crate is only intended for use inside the implementation of | |
55 | /// procedural macros. All the functions in this crate panic if invoked from | |
56 | /// outside of a procedural macro, such as from a build script or unit test or | |
57 | /// ordinary Rust binary. | |
58 | /// | |
59 | /// With consideration for Rust libraries that are designed to support both | |
60 | /// macro and non-macro use cases, `proc_macro::is_available()` provides a | |
61 | /// non-panicking way to detect whether the infrastructure required to use the | |
62 | /// API of proc_macro is presently available. Returns true if invoked from | |
63 | /// inside of a procedural macro, false if invoked from any other binary. | |
c295e0f8 | 64 | #[stable(feature = "proc_macro_is_available", since = "1.57.0")] |
f9f354fc XL |
65 | pub fn is_available() -> bool { |
66 | bridge::Bridge::is_available() | |
67 | } | |
68 | ||
c30ab7b3 | 69 | /// The main type provided by this crate, representing an abstract stream of |
94b46f34 XL |
70 | /// tokens, or, more specifically, a sequence of token trees. |
71 | /// The type provide interfaces for iterating over those token trees and, conversely, | |
72 | /// collecting a number of token trees into one stream. | |
c30ab7b3 | 73 | /// |
94b46f34 XL |
74 | /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` |
75 | /// and `#[proc_macro_derive]` definitions. | |
476ff2be | 76 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 77 | #[derive(Clone)] |
a1dfa0c6 | 78 | pub struct TokenStream(bridge::client::TokenStream); |
c30ab7b3 | 79 | |
94b46f34 | 80 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 81 | impl !Send for TokenStream {} |
94b46f34 | 82 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d XL |
83 | impl !Sync for TokenStream {} |
84 | ||
c30ab7b3 | 85 | /// Error returned from `TokenStream::from_str`. |
476ff2be | 86 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
136023e0 | 87 | #[non_exhaustive] |
041b39d2 | 88 | #[derive(Debug)] |
136023e0 | 89 | pub struct LexError; |
c30ab7b3 | 90 | |
ba9703b0 XL |
91 | #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")] |
92 | impl fmt::Display for LexError { | |
93 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
94 | f.write_str("cannot parse string into token stream") | |
95 | } | |
96 | } | |
97 | ||
98 | #[stable(feature = "proc_macro_lexerror_impls", since = "1.44.0")] | |
99 | impl error::Error for LexError {} | |
100 | ||
94b46f34 | 101 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d | 102 | impl !Send for LexError {} |
94b46f34 | 103 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
83c7162d XL |
104 | impl !Sync for LexError {} |
105 | ||
3c0e092e XL |
106 | /// Error returned from `TokenStream::expand_expr`. |
107 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
108 | #[non_exhaustive] | |
109 | #[derive(Debug)] | |
110 | pub struct ExpandError; | |
111 | ||
112 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
113 | impl fmt::Display for ExpandError { | |
114 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
115 | f.write_str("macro expansion failed") | |
116 | } | |
117 | } | |
118 | ||
119 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
120 | impl error::Error for ExpandError {} | |
121 | ||
122 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
123 | impl !Send for ExpandError {} | |
124 | ||
125 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
126 | impl !Sync for ExpandError {} | |
127 | ||
83c7162d | 128 | impl TokenStream { |
94b46f34 | 129 | /// Returns an empty `TokenStream` containing no token trees. |
8faf50e0 | 130 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 131 | pub fn new() -> TokenStream { |
a1dfa0c6 | 132 | TokenStream(bridge::client::TokenStream::new()) |
83c7162d XL |
133 | } |
134 | ||
135 | /// Checks if this `TokenStream` is empty. | |
8faf50e0 | 136 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
137 | pub fn is_empty(&self) -> bool { |
138 | self.0.is_empty() | |
139 | } | |
3c0e092e XL |
140 | |
141 | /// Parses this `TokenStream` as an expression and attempts to expand any | |
142 | /// macros within it. Returns the expanded `TokenStream`. | |
143 | /// | |
144 | /// Currently only expressions expanding to literals will succeed, although | |
145 | /// this may be relaxed in the future. | |
146 | /// | |
147 | /// NOTE: In error conditions, `expand_expr` may leave macros unexpanded, | |
148 | /// report an error, failing compilation, and/or return an `Err(..)`. The | |
149 | /// specific behavior for any error condition, and what conditions are | |
150 | /// considered errors, is unspecified and may change in the future. | |
151 | #[unstable(feature = "proc_macro_expand", issue = "90765")] | |
152 | pub fn expand_expr(&self) -> Result<TokenStream, ExpandError> { | |
153 | match bridge::client::TokenStream::expand_expr(&self.0) { | |
154 | Ok(stream) => Ok(TokenStream(stream)), | |
155 | Err(_) => Err(ExpandError), | |
156 | } | |
157 | } | |
83c7162d XL |
158 | } |
159 | ||
94b46f34 XL |
160 | /// Attempts to break the string into tokens and parse those tokens into a token stream. |
161 | /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters | |
162 | /// or characters not existing in the language. | |
8faf50e0 | 163 | /// All tokens in the parsed stream get `Span::call_site()` spans. |
94b46f34 | 164 | /// |
9fa01778 | 165 | /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to |
94b46f34 | 166 | /// change these errors into `LexError`s later. |
041b39d2 XL |
167 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
168 | impl FromStr for TokenStream { | |
169 | type Err = LexError; | |
170 | ||
171 | fn from_str(src: &str) -> Result<TokenStream, LexError> { | |
a1dfa0c6 XL |
172 | Ok(TokenStream(bridge::client::TokenStream::from_str(src))) |
173 | } | |
174 | } | |
175 | ||
0731742a | 176 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
177 | // based on it (the reverse of the usual relationship between the two). |
178 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
179 | impl ToString for TokenStream { | |
180 | fn to_string(&self) -> String { | |
181 | self.0.to_string() | |
041b39d2 XL |
182 | } |
183 | } | |
184 | ||
94b46f34 XL |
185 | /// Prints the token stream as a string that is supposed to be losslessly convertible back |
186 | /// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s | |
187 | /// with `Delimiter::None` delimiters and negative numeric literals. | |
041b39d2 XL |
188 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
189 | impl fmt::Display for TokenStream { | |
9fa01778 | 190 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 191 | f.write_str(&self.to_string()) |
041b39d2 XL |
192 | } |
193 | } | |
194 | ||
94b46f34 | 195 | /// Prints token in a form convenient for debugging. |
83c7162d XL |
196 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] |
197 | impl fmt::Debug for TokenStream { | |
9fa01778 | 198 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
83c7162d XL |
199 | f.write_str("TokenStream ")?; |
200 | f.debug_list().entries(self.clone()).finish() | |
201 | } | |
202 | } | |
041b39d2 | 203 | |
f9f354fc XL |
204 | #[stable(feature = "proc_macro_token_stream_default", since = "1.45.0")] |
205 | impl Default for TokenStream { | |
206 | fn default() -> Self { | |
207 | TokenStream::new() | |
208 | } | |
209 | } | |
210 | ||
0bf4aa26 | 211 | #[unstable(feature = "proc_macro_quote", issue = "54722")] |
8faf50e0 XL |
212 | pub use quote::{quote, quote_span}; |
213 | ||
94b46f34 | 214 | /// Creates a token stream containing a single token tree. |
dfeec247 | 215 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
216 | impl From<TokenTree> for TokenStream { |
217 | fn from(tree: TokenTree) -> TokenStream { | |
a1dfa0c6 XL |
218 | TokenStream(bridge::client::TokenStream::from_token_tree(match tree { |
219 | TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0), | |
220 | TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0), | |
221 | TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0), | |
dfeec247 | 222 | TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0), |
a1dfa0c6 | 223 | })) |
041b39d2 XL |
224 | } |
225 | } | |
226 | ||
94b46f34 | 227 | /// Collects a number of token trees into a single stream. |
dfeec247 | 228 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
229 | impl iter::FromIterator<TokenTree> for TokenStream { |
230 | fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { | |
231 | trees.into_iter().map(TokenStream::from).collect() | |
041b39d2 XL |
232 | } |
233 | } | |
234 | ||
94b46f34 XL |
235 | /// A "flattening" operation on token streams, collects token trees |
236 | /// from multiple token streams into a single stream. | |
237 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
83c7162d XL |
238 | impl iter::FromIterator<TokenStream> for TokenStream { |
239 | fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { | |
a1dfa0c6 | 240 | let mut builder = bridge::client::TokenStreamBuilder::new(); |
532ac7d7 | 241 | streams.into_iter().for_each(|stream| builder.push(stream.0)); |
041b39d2 XL |
242 | TokenStream(builder.build()) |
243 | } | |
244 | } | |
245 | ||
b7449926 XL |
246 | #[stable(feature = "token_stream_extend", since = "1.30.0")] |
247 | impl Extend<TokenTree> for TokenStream { | |
248 | fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) { | |
249 | self.extend(trees.into_iter().map(TokenStream::from)); | |
250 | } | |
251 | } | |
252 | ||
253 | #[stable(feature = "token_stream_extend", since = "1.30.0")] | |
254 | impl Extend<TokenStream> for TokenStream { | |
255 | fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { | |
a1dfa0c6 XL |
256 | // FIXME(eddyb) Use an optimized implementation if/when possible. |
257 | *self = iter::once(mem::replace(self, Self::new())).chain(streams).collect(); | |
b7449926 XL |
258 | } |
259 | } | |
260 | ||
94b46f34 | 261 | /// Public implementation details for the `TokenStream` type, such as iterators. |
8faf50e0 | 262 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 263 | pub mod token_stream { |
dfeec247 | 264 | use crate::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree}; |
041b39d2 | 265 | |
94b46f34 | 266 | /// An iterator over `TokenStream`'s `TokenTree`s. |
0731742a | 267 | /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, |
94b46f34 | 268 | /// and returns whole groups as token trees. |
83c7162d | 269 | #[derive(Clone)] |
8faf50e0 | 270 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
a1dfa0c6 | 271 | pub struct IntoIter(bridge::client::TokenStreamIter); |
041b39d2 | 272 | |
8faf50e0 | 273 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
274 | impl Iterator for IntoIter { |
275 | type Item = TokenTree; | |
276 | ||
277 | fn next(&mut self) -> Option<TokenTree> { | |
a1dfa0c6 XL |
278 | self.0.next().map(|tree| match tree { |
279 | bridge::TokenTree::Group(tt) => TokenTree::Group(Group(tt)), | |
280 | bridge::TokenTree::Punct(tt) => TokenTree::Punct(Punct(tt)), | |
281 | bridge::TokenTree::Ident(tt) => TokenTree::Ident(Ident(tt)), | |
282 | bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)), | |
283 | }) | |
83c7162d | 284 | } |
041b39d2 XL |
285 | } |
286 | ||
8faf50e0 | 287 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
288 | impl IntoIterator for TokenStream { |
289 | type Item = TokenTree; | |
290 | type IntoIter = IntoIter; | |
291 | ||
292 | fn into_iter(self) -> IntoIter { | |
a1dfa0c6 | 293 | IntoIter(self.0.into_iter()) |
83c7162d | 294 | } |
041b39d2 XL |
295 | } |
296 | } | |
297 | ||
83c7162d | 298 | /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input. |
94222f64 | 299 | /// For example, `quote!(a + b)` will produce an expression, that, when evaluated, constructs |
94b46f34 | 300 | /// the `TokenStream` `[Ident("a"), Punct('+', Alone), Ident("b")]`. |
83c7162d XL |
301 | /// |
302 | /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term. | |
303 | /// To quote `$` itself, use `$$`. | |
0bf4aa26 | 304 | #[unstable(feature = "proc_macro_quote", issue = "54722")] |
17df50a5 | 305 | #[allow_internal_unstable(proc_macro_def_site, proc_macro_internals)] |
e74abb32 | 306 | #[rustc_builtin_macro] |
dfeec247 XL |
307 | pub macro quote($($t:tt)*) { |
308 | /* compiler built-in */ | |
309 | } | |
041b39d2 | 310 | |
83c7162d XL |
311 | #[unstable(feature = "proc_macro_internals", issue = "27812")] |
312 | #[doc(hidden)] | |
313 | mod quote; | |
041b39d2 | 314 | |
83c7162d | 315 | /// A region of source code, along with macro expansion information. |
8faf50e0 | 316 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 317 | #[derive(Copy, Clone)] |
a1dfa0c6 | 318 | pub struct Span(bridge::client::Span); |
83c7162d | 319 | |
8faf50e0 | 320 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 321 | impl !Send for Span {} |
8faf50e0 | 322 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
323 | impl !Sync for Span {} |
324 | ||
ea8adc8c | 325 | macro_rules! diagnostic_method { |
f9f354fc | 326 | ($name:ident, $level:expr) => { |
9fa01778 | 327 | /// Creates a new `Diagnostic` with the given `message` at the span |
ea8adc8c | 328 | /// `self`. |
b7449926 | 329 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] |
ea8adc8c XL |
330 | pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic { |
331 | Diagnostic::spanned(self, $level, message) | |
332 | } | |
f9f354fc | 333 | }; |
ea8adc8c XL |
334 | } |
335 | ||
041b39d2 | 336 | impl Span { |
83c7162d | 337 | /// A span that resolves at the macro definition site. |
0bf4aa26 | 338 | #[unstable(feature = "proc_macro_def_site", issue = "54724")] |
83c7162d | 339 | pub fn def_site() -> Span { |
a1dfa0c6 | 340 | Span(bridge::client::Span::def_site()) |
83c7162d XL |
341 | } |
342 | ||
041b39d2 | 343 | /// The span of the invocation of the current procedural macro. |
94b46f34 XL |
344 | /// Identifiers created with this span will be resolved as if they were written |
345 | /// directly at the macro call location (call-site hygiene) and other code | |
346 | /// at the macro call site will be able to refer to them as well. | |
8faf50e0 | 347 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 348 | pub fn call_site() -> Span { |
a1dfa0c6 | 349 | Span(bridge::client::Span::call_site()) |
041b39d2 | 350 | } |
ea8adc8c | 351 | |
e74abb32 XL |
352 | /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro |
353 | /// definition site (local variables, labels, `$crate`) and sometimes at the macro | |
354 | /// call site (everything else). | |
355 | /// The span location is taken from the call-site. | |
f9f354fc | 356 | #[stable(feature = "proc_macro_mixed_site", since = "1.45.0")] |
e74abb32 XL |
357 | pub fn mixed_site() -> Span { |
358 | Span(bridge::client::Span::mixed_site()) | |
359 | } | |
360 | ||
ea8adc8c | 361 | /// The original source file into which this span points. |
0bf4aa26 | 362 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 363 | pub fn source_file(&self) -> SourceFile { |
a1dfa0c6 | 364 | SourceFile(self.0.source_file()) |
ea8adc8c XL |
365 | } |
366 | ||
2c00a5a8 XL |
367 | /// The `Span` for the tokens in the previous macro expansion from which |
368 | /// `self` was generated from, if any. | |
0bf4aa26 | 369 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 | 370 | pub fn parent(&self) -> Option<Span> { |
83c7162d | 371 | self.0.parent().map(Span) |
2c00a5a8 XL |
372 | } |
373 | ||
374 | /// The span for the origin source code that `self` was generated from. If | |
375 | /// this `Span` wasn't generated from other macro expansions then the return | |
376 | /// value is the same as `*self`. | |
0bf4aa26 | 377 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
2c00a5a8 | 378 | pub fn source(&self) -> Span { |
a1dfa0c6 | 379 | Span(self.0.source()) |
2c00a5a8 XL |
380 | } |
381 | ||
9fa01778 | 382 | /// Gets the starting line/column in the source file for this span. |
0bf4aa26 | 383 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 384 | pub fn start(&self) -> LineColumn { |
94222f64 | 385 | self.0.start().add_1_to_column() |
ea8adc8c XL |
386 | } |
387 | ||
9fa01778 | 388 | /// Gets the ending line/column in the source file for this span. |
0bf4aa26 | 389 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 390 | pub fn end(&self) -> LineColumn { |
94222f64 | 391 | self.0.end().add_1_to_column() |
ea8adc8c XL |
392 | } |
393 | ||
c295e0f8 XL |
394 | /// Creates an empty span pointing to directly before this span. |
395 | #[unstable(feature = "proc_macro_span_shrink", issue = "87552")] | |
396 | pub fn before(&self) -> Span { | |
397 | Span(self.0.before()) | |
398 | } | |
399 | ||
400 | /// Creates an empty span pointing to directly after this span. | |
401 | #[unstable(feature = "proc_macro_span_shrink", issue = "87552")] | |
402 | pub fn after(&self) -> Span { | |
403 | Span(self.0.after()) | |
404 | } | |
405 | ||
9fa01778 | 406 | /// Creates a new span encompassing `self` and `other`. |
ea8adc8c XL |
407 | /// |
408 | /// Returns `None` if `self` and `other` are from different files. | |
0bf4aa26 | 409 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 410 | pub fn join(&self, other: Span) -> Option<Span> { |
a1dfa0c6 | 411 | self.0.join(other.0).map(Span) |
ea8adc8c XL |
412 | } |
413 | ||
2c00a5a8 XL |
414 | /// Creates a new span with the same line/column information as `self` but |
415 | /// that resolves symbols as though it were at `other`. | |
f9f354fc | 416 | #[stable(feature = "proc_macro_span_resolved_at", since = "1.45.0")] |
2c00a5a8 | 417 | pub fn resolved_at(&self, other: Span) -> Span { |
a1dfa0c6 | 418 | Span(self.0.resolved_at(other.0)) |
2c00a5a8 XL |
419 | } |
420 | ||
421 | /// Creates a new span with the same name resolution behavior as `self` but | |
422 | /// with the line/column information of `other`. | |
f9f354fc | 423 | #[stable(feature = "proc_macro_span_located_at", since = "1.45.0")] |
2c00a5a8 XL |
424 | pub fn located_at(&self, other: Span) -> Span { |
425 | other.resolved_at(*self) | |
426 | } | |
427 | ||
83c7162d | 428 | /// Compares to spans to see if they're equal. |
0bf4aa26 | 429 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d XL |
430 | pub fn eq(&self, other: &Span) -> bool { |
431 | self.0 == other.0 | |
432 | } | |
433 | ||
532ac7d7 XL |
434 | /// Returns the source text behind a span. This preserves the original source |
435 | /// code, including spaces and comments. It only returns a result if the span | |
436 | /// corresponds to real source code. | |
437 | /// | |
438 | /// Note: The observable result of a macro should only rely on the tokens and | |
439 | /// not on this source text. The result of this function is a best effort to | |
440 | /// be used for diagnostics only. | |
441 | #[unstable(feature = "proc_macro_span", issue = "54725")] | |
442 | pub fn source_text(&self) -> Option<String> { | |
443 | self.0.source_text() | |
444 | } | |
445 | ||
17df50a5 XL |
446 | // Used by the implementation of `Span::quote` |
447 | #[doc(hidden)] | |
448 | #[unstable(feature = "proc_macro_internals", issue = "27812")] | |
449 | pub fn save_span(&self) -> usize { | |
450 | self.0.save_span() | |
451 | } | |
452 | ||
453 | // Used by the implementation of `Span::quote` | |
454 | #[doc(hidden)] | |
455 | #[unstable(feature = "proc_macro_internals", issue = "27812")] | |
456 | pub fn recover_proc_macro_span(id: usize) -> Span { | |
457 | Span(bridge::client::Span::recover_proc_macro_span(id)) | |
458 | } | |
459 | ||
ea8adc8c XL |
460 | diagnostic_method!(error, Level::Error); |
461 | diagnostic_method!(warning, Level::Warning); | |
462 | diagnostic_method!(note, Level::Note); | |
463 | diagnostic_method!(help, Level::Help); | |
464 | } | |
465 | ||
94b46f34 | 466 | /// Prints a span in a form convenient for debugging. |
8faf50e0 | 467 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 468 | impl fmt::Debug for Span { |
9fa01778 | 469 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 470 | self.0.fmt(f) |
83c7162d XL |
471 | } |
472 | } | |
473 | ||
ea8adc8c | 474 | /// A line-column pair representing the start or end of a `Span`. |
0bf4aa26 | 475 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
476 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
477 | pub struct LineColumn { | |
478 | /// The 1-indexed line in the source file on which the span starts or ends (inclusive). | |
0bf4aa26 | 479 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ff7c6d11 | 480 | pub line: usize, |
94222f64 XL |
481 | /// The 1-indexed column (number of bytes in UTF-8 encoding) in the source |
482 | /// file on which the span starts or ends (inclusive). | |
0bf4aa26 | 483 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
dfeec247 | 484 | pub column: usize, |
ea8adc8c XL |
485 | } |
486 | ||
94222f64 XL |
487 | impl LineColumn { |
488 | fn add_1_to_column(self) -> Self { | |
489 | LineColumn { line: self.line, column: self.column + 1 } | |
490 | } | |
491 | } | |
492 | ||
0bf4aa26 | 493 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d | 494 | impl !Send for LineColumn {} |
0bf4aa26 | 495 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
83c7162d XL |
496 | impl !Sync for LineColumn {} |
497 | ||
f9f354fc XL |
498 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
499 | impl Ord for LineColumn { | |
500 | fn cmp(&self, other: &Self) -> Ordering { | |
501 | self.line.cmp(&other.line).then(self.column.cmp(&other.column)) | |
502 | } | |
503 | } | |
504 | ||
505 | #[unstable(feature = "proc_macro_span", issue = "54725")] | |
506 | impl PartialOrd for LineColumn { | |
507 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | |
508 | Some(self.cmp(other)) | |
509 | } | |
510 | } | |
511 | ||
ea8adc8c | 512 | /// The source file of a given `Span`. |
0bf4aa26 | 513 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 514 | #[derive(Clone)] |
a1dfa0c6 | 515 | pub struct SourceFile(bridge::client::SourceFile); |
0531ce1d | 516 | |
ea8adc8c | 517 | impl SourceFile { |
9fa01778 | 518 | /// Gets the path to this source file. |
ea8adc8c XL |
519 | /// |
520 | /// ### Note | |
521 | /// If the code span associated with this `SourceFile` was generated by an external macro, this | |
94222f64 | 522 | /// macro, this might not be an actual path on the filesystem. Use [`is_real`] to check. |
ea8adc8c | 523 | /// |
0531ce1d | 524 | /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on |
94222f64 | 525 | /// the command line, the path as given might not actually be valid. |
ea8adc8c | 526 | /// |
3dfed10e | 527 | /// [`is_real`]: Self::is_real |
0bf4aa26 | 528 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
8faf50e0 | 529 | pub fn path(&self) -> PathBuf { |
a1dfa0c6 | 530 | PathBuf::from(self.0.path()) |
ea8adc8c XL |
531 | } |
532 | ||
533 | /// Returns `true` if this source file is a real source file, and not generated by an external | |
534 | /// macro's expansion. | |
0bf4aa26 | 535 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
536 | pub fn is_real(&self) -> bool { |
537 | // This is a hack until intercrate spans are implemented and we can have real source files | |
538 | // for spans generated in external macros. | |
539 | // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368 | |
a1dfa0c6 | 540 | self.0.is_real() |
ea8adc8c XL |
541 | } |
542 | } | |
543 | ||
0bf4aa26 | 544 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c | 545 | impl fmt::Debug for SourceFile { |
9fa01778 | 546 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
ea8adc8c | 547 | f.debug_struct("SourceFile") |
8faf50e0 | 548 | .field("path", &self.path()) |
ea8adc8c XL |
549 | .field("is_real", &self.is_real()) |
550 | .finish() | |
551 | } | |
552 | } | |
553 | ||
0bf4aa26 | 554 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
555 | impl PartialEq for SourceFile { |
556 | fn eq(&self, other: &Self) -> bool { | |
a1dfa0c6 | 557 | self.0.eq(&other.0) |
ea8adc8c XL |
558 | } |
559 | } | |
560 | ||
0bf4aa26 | 561 | #[unstable(feature = "proc_macro_span", issue = "54725")] |
ea8adc8c XL |
562 | impl Eq for SourceFile {} |
563 | ||
0731742a | 564 | /// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`). |
8faf50e0 | 565 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
566 | #[derive(Clone)] |
567 | pub enum TokenTree { | |
94b46f34 | 568 | /// A token stream surrounded by bracket delimiters. |
8faf50e0 | 569 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 570 | Group(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Group), |
94b46f34 | 571 | /// An identifier. |
8faf50e0 | 572 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 573 | Ident(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Ident), |
94b46f34 | 574 | /// A single punctuation character (`+`, `,`, `$`, etc.). |
8faf50e0 | 575 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 576 | Punct(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Punct), |
83c7162d | 577 | /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. |
8faf50e0 | 578 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
dfeec247 | 579 | Literal(#[stable(feature = "proc_macro_lib2", since = "1.29.0")] Literal), |
041b39d2 XL |
580 | } |
581 | ||
8faf50e0 | 582 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 583 | impl !Send for TokenTree {} |
8faf50e0 | 584 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
585 | impl !Sync for TokenTree {} |
586 | ||
587 | impl TokenTree { | |
94b46f34 XL |
588 | /// Returns the span of this tree, delegating to the `span` method of |
589 | /// the contained token or a delimited stream. | |
8faf50e0 | 590 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
591 | pub fn span(&self) -> Span { |
592 | match *self { | |
593 | TokenTree::Group(ref t) => t.span(), | |
94b46f34 XL |
594 | TokenTree::Ident(ref t) => t.span(), |
595 | TokenTree::Punct(ref t) => t.span(), | |
83c7162d XL |
596 | TokenTree::Literal(ref t) => t.span(), |
597 | } | |
598 | } | |
599 | ||
600 | /// Configures the span for *only this token*. | |
601 | /// | |
602 | /// Note that if this token is a `Group` then this method will not configure | |
603 | /// the span of each of the internal tokens, this will simply delegate to | |
604 | /// the `set_span` method of each variant. | |
8faf50e0 | 605 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
606 | pub fn set_span(&mut self, span: Span) { |
607 | match *self { | |
608 | TokenTree::Group(ref mut t) => t.set_span(span), | |
94b46f34 XL |
609 | TokenTree::Ident(ref mut t) => t.set_span(span), |
610 | TokenTree::Punct(ref mut t) => t.set_span(span), | |
83c7162d XL |
611 | TokenTree::Literal(ref mut t) => t.set_span(span), |
612 | } | |
613 | } | |
614 | } | |
615 | ||
a1dfa0c6 | 616 | /// Prints token tree in a form convenient for debugging. |
8faf50e0 | 617 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 618 | impl fmt::Debug for TokenTree { |
9fa01778 | 619 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
83c7162d XL |
620 | // Each of these has the name in the struct type in the derived debug, |
621 | // so don't bother with an extra layer of indirection | |
622 | match *self { | |
623 | TokenTree::Group(ref tt) => tt.fmt(f), | |
94b46f34 XL |
624 | TokenTree::Ident(ref tt) => tt.fmt(f), |
625 | TokenTree::Punct(ref tt) => tt.fmt(f), | |
83c7162d XL |
626 | TokenTree::Literal(ref tt) => tt.fmt(f), |
627 | } | |
628 | } | |
629 | } | |
630 | ||
8faf50e0 | 631 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
632 | impl From<Group> for TokenTree { |
633 | fn from(g: Group) -> TokenTree { | |
634 | TokenTree::Group(g) | |
635 | } | |
636 | } | |
637 | ||
8faf50e0 | 638 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 XL |
639 | impl From<Ident> for TokenTree { |
640 | fn from(g: Ident) -> TokenTree { | |
641 | TokenTree::Ident(g) | |
83c7162d XL |
642 | } |
643 | } | |
644 | ||
8faf50e0 | 645 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 XL |
646 | impl From<Punct> for TokenTree { |
647 | fn from(g: Punct) -> TokenTree { | |
648 | TokenTree::Punct(g) | |
83c7162d XL |
649 | } |
650 | } | |
651 | ||
8faf50e0 | 652 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
653 | impl From<Literal> for TokenTree { |
654 | fn from(g: Literal) -> TokenTree { | |
655 | TokenTree::Literal(g) | |
041b39d2 XL |
656 | } |
657 | } | |
658 | ||
0731742a | 659 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
660 | // based on it (the reverse of the usual relationship between the two). |
661 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
662 | impl ToString for TokenTree { | |
663 | fn to_string(&self) -> String { | |
664 | match *self { | |
665 | TokenTree::Group(ref t) => t.to_string(), | |
666 | TokenTree::Ident(ref t) => t.to_string(), | |
667 | TokenTree::Punct(ref t) => t.to_string(), | |
668 | TokenTree::Literal(ref t) => t.to_string(), | |
669 | } | |
670 | } | |
671 | } | |
672 | ||
94b46f34 XL |
673 | /// Prints the token tree as a string that is supposed to be losslessly convertible back |
674 | /// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s | |
675 | /// with `Delimiter::None` delimiters and negative numeric literals. | |
8faf50e0 | 676 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 677 | impl fmt::Display for TokenTree { |
9fa01778 | 678 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 679 | f.write_str(&self.to_string()) |
041b39d2 XL |
680 | } |
681 | } | |
682 | ||
94b46f34 | 683 | /// A delimited token stream. |
83c7162d | 684 | /// |
94b46f34 | 685 | /// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s. |
8faf50e0 XL |
686 | #[derive(Clone)] |
687 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
a1dfa0c6 | 688 | pub struct Group(bridge::client::Group); |
041b39d2 | 689 | |
8faf50e0 | 690 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 691 | impl !Send for Group {} |
8faf50e0 | 692 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
693 | impl !Sync for Group {} |
694 | ||
041b39d2 | 695 | /// Describes how a sequence of token trees is delimited. |
3b2f2976 | 696 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
8faf50e0 | 697 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
698 | pub enum Delimiter { |
699 | /// `( ... )` | |
8faf50e0 | 700 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 701 | Parenthesis, |
041b39d2 | 702 | /// `{ ... }` |
8faf50e0 | 703 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
3b2f2976 XL |
704 | Brace, |
705 | /// `[ ... ]` | |
8faf50e0 | 706 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 707 | Bracket, |
94b46f34 XL |
708 | /// `Ø ... Ø` |
709 | /// An implicit delimiter, that may, for example, appear around tokens coming from a | |
710 | /// "macro variable" `$var`. It is important to preserve operator priorities in cases like | |
711 | /// `$var * 3` where `$var` is `1 + 2`. | |
94222f64 | 712 | /// Implicit delimiters might not survive roundtrip of a token stream through a string. |
8faf50e0 | 713 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
714 | None, |
715 | } | |
716 | ||
83c7162d | 717 | impl Group { |
94b46f34 | 718 | /// Creates a new `Group` with the given delimiter and token stream. |
83c7162d XL |
719 | /// |
720 | /// This constructor will set the span for this group to | |
721 | /// `Span::call_site()`. To change the span you can use the `set_span` | |
722 | /// method below. | |
8faf50e0 | 723 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 724 | pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { |
a1dfa0c6 | 725 | Group(bridge::client::Group::new(delimiter, stream.0)) |
83c7162d | 726 | } |
041b39d2 | 727 | |
83c7162d | 728 | /// Returns the delimiter of this `Group` |
8faf50e0 | 729 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 730 | pub fn delimiter(&self) -> Delimiter { |
a1dfa0c6 | 731 | self.0.delimiter() |
041b39d2 XL |
732 | } |
733 | ||
83c7162d XL |
734 | /// Returns the `TokenStream` of tokens that are delimited in this `Group`. |
735 | /// | |
736 | /// Note that the returned token stream does not include the delimiter | |
737 | /// returned above. | |
8faf50e0 | 738 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 739 | pub fn stream(&self) -> TokenStream { |
a1dfa0c6 | 740 | TokenStream(self.0.stream()) |
83c7162d XL |
741 | } |
742 | ||
743 | /// Returns the span for the delimiters of this token stream, spanning the | |
744 | /// entire `Group`. | |
b7449926 XL |
745 | /// |
746 | /// ```text | |
747 | /// pub fn span(&self) -> Span { | |
748 | /// ^^^^^^^ | |
749 | /// ``` | |
8faf50e0 | 750 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 751 | pub fn span(&self) -> Span { |
a1dfa0c6 | 752 | Span(self.0.span()) |
b7449926 XL |
753 | } |
754 | ||
755 | /// Returns the span pointing to the opening delimiter of this group. | |
756 | /// | |
757 | /// ```text | |
758 | /// pub fn span_open(&self) -> Span { | |
759 | /// ^ | |
760 | /// ``` | |
136023e0 | 761 | #[stable(feature = "proc_macro_group_span", since = "1.55.0")] |
b7449926 | 762 | pub fn span_open(&self) -> Span { |
a1dfa0c6 | 763 | Span(self.0.span_open()) |
b7449926 XL |
764 | } |
765 | ||
766 | /// Returns the span pointing to the closing delimiter of this group. | |
767 | /// | |
768 | /// ```text | |
769 | /// pub fn span_close(&self) -> Span { | |
770 | /// ^ | |
771 | /// ``` | |
136023e0 | 772 | #[stable(feature = "proc_macro_group_span", since = "1.55.0")] |
b7449926 | 773 | pub fn span_close(&self) -> Span { |
a1dfa0c6 | 774 | Span(self.0.span_close()) |
83c7162d XL |
775 | } |
776 | ||
777 | /// Configures the span for this `Group`'s delimiters, but not its internal | |
778 | /// tokens. | |
779 | /// | |
780 | /// This method will **not** set the span of all the internal tokens spanned | |
781 | /// by this group, but rather it will only set the span of the delimiter | |
782 | /// tokens at the level of the `Group`. | |
8faf50e0 | 783 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 784 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
785 | self.0.set_span(span.0); |
786 | } | |
787 | } | |
788 | ||
0731742a | 789 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
790 | // based on it (the reverse of the usual relationship between the two). |
791 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
792 | impl ToString for Group { | |
793 | fn to_string(&self) -> String { | |
794 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
795 | } |
796 | } | |
797 | ||
94b46f34 XL |
798 | /// Prints the group as a string that should be losslessly convertible back |
799 | /// into the same group (modulo spans), except for possibly `TokenTree::Group`s | |
800 | /// with `Delimiter::None` delimiters. | |
8faf50e0 | 801 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 802 | impl fmt::Display for Group { |
9fa01778 | 803 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 804 | f.write_str(&self.to_string()) |
041b39d2 XL |
805 | } |
806 | } | |
807 | ||
8faf50e0 XL |
808 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
809 | impl fmt::Debug for Group { | |
9fa01778 | 810 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
811 | f.debug_struct("Group") |
812 | .field("delimiter", &self.delimiter()) | |
813 | .field("stream", &self.stream()) | |
814 | .field("span", &self.span()) | |
815 | .finish() | |
816 | } | |
817 | } | |
818 | ||
136023e0 | 819 | /// A `Punct` is a single punctuation character such as `+`, `-` or `#`. |
83c7162d | 820 | /// |
a1dfa0c6 | 821 | /// Multi-character operators like `+=` are represented as two instances of `Punct` with different |
83c7162d | 822 | /// forms of `Spacing` returned. |
8faf50e0 XL |
823 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
824 | #[derive(Clone)] | |
a1dfa0c6 | 825 | pub struct Punct(bridge::client::Punct); |
83c7162d | 826 | |
8faf50e0 | 827 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 828 | impl !Send for Punct {} |
8faf50e0 | 829 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 830 | impl !Sync for Punct {} |
83c7162d | 831 | |
136023e0 XL |
832 | /// Describes whether a `Punct` is followed immediately by another `Punct` ([`Spacing::Joint`]) or |
833 | /// by a different token or whitespace ([`Spacing::Alone`]). | |
3b2f2976 | 834 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
8faf50e0 | 835 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 836 | pub enum Spacing { |
136023e0 XL |
837 | /// A `Punct` is not immediately followed by another `Punct`. |
838 | /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`. | |
8faf50e0 | 839 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 840 | Alone, |
136023e0 XL |
841 | /// A `Punct` is immediately followed by another `Punct`. |
842 | /// E.g. `+` is `Joint` in `+=` and `++`. | |
843 | /// | |
844 | /// Additionally, single quote `'` can join with identifiers to form lifetimes: `'ident`. | |
8faf50e0 | 845 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 XL |
846 | Joint, |
847 | } | |
848 | ||
94b46f34 XL |
849 | impl Punct { |
850 | /// Creates a new `Punct` from the given character and spacing. | |
851 | /// The `ch` argument must be a valid punctuation character permitted by the language, | |
852 | /// otherwise the function will panic. | |
83c7162d | 853 | /// |
94b46f34 | 854 | /// The returned `Punct` will have the default span of `Span::call_site()` |
83c7162d | 855 | /// which can be further configured with the `set_span` method below. |
8faf50e0 | 856 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 857 | pub fn new(ch: char, spacing: Spacing) -> Punct { |
a1dfa0c6 | 858 | Punct(bridge::client::Punct::new(ch, spacing)) |
83c7162d XL |
859 | } |
860 | ||
94b46f34 | 861 | /// Returns the value of this punctuation character as `char`. |
8faf50e0 | 862 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 863 | pub fn as_char(&self) -> char { |
a1dfa0c6 | 864 | self.0.as_char() |
83c7162d XL |
865 | } |
866 | ||
94b46f34 XL |
867 | /// Returns the spacing of this punctuation character, indicating whether it's immediately |
868 | /// followed by another `Punct` in the token stream, so they can potentially be combined into | |
a1dfa0c6 | 869 | /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace |
94b46f34 | 870 | /// (`Alone`) so the operator has certainly ended. |
8faf50e0 | 871 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 872 | pub fn spacing(&self) -> Spacing { |
a1dfa0c6 | 873 | self.0.spacing() |
83c7162d XL |
874 | } |
875 | ||
94b46f34 | 876 | /// Returns the span for this punctuation character. |
8faf50e0 | 877 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 878 | pub fn span(&self) -> Span { |
a1dfa0c6 | 879 | Span(self.0.span()) |
83c7162d XL |
880 | } |
881 | ||
94b46f34 | 882 | /// Configure the span for this punctuation character. |
8faf50e0 | 883 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 884 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
885 | self.0 = self.0.with_span(span.0); |
886 | } | |
887 | } | |
888 | ||
0731742a | 889 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
890 | // based on it (the reverse of the usual relationship between the two). |
891 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
892 | impl ToString for Punct { | |
893 | fn to_string(&self) -> String { | |
894 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
895 | } |
896 | } | |
897 | ||
94b46f34 XL |
898 | /// Prints the punctuation character as a string that should be losslessly convertible |
899 | /// back into the same character. | |
8faf50e0 | 900 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 901 | impl fmt::Display for Punct { |
9fa01778 | 902 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 903 | f.write_str(&self.to_string()) |
83c7162d XL |
904 | } |
905 | } | |
041b39d2 | 906 | |
8faf50e0 XL |
907 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
908 | impl fmt::Debug for Punct { | |
9fa01778 | 909 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
910 | f.debug_struct("Punct") |
911 | .field("ch", &self.as_char()) | |
912 | .field("spacing", &self.spacing()) | |
913 | .field("span", &self.span()) | |
914 | .finish() | |
915 | } | |
916 | } | |
917 | ||
6a06907d | 918 | #[stable(feature = "proc_macro_punct_eq", since = "1.50.0")] |
fc512014 XL |
919 | impl PartialEq<char> for Punct { |
920 | fn eq(&self, rhs: &char) -> bool { | |
921 | self.as_char() == *rhs | |
922 | } | |
923 | } | |
924 | ||
6a06907d XL |
925 | #[stable(feature = "proc_macro_punct_eq_flipped", since = "1.52.0")] |
926 | impl PartialEq<Punct> for char { | |
927 | fn eq(&self, rhs: &Punct) -> bool { | |
928 | *self == rhs.as_char() | |
929 | } | |
930 | } | |
931 | ||
94b46f34 | 932 | /// An identifier (`ident`). |
8faf50e0 XL |
933 | #[derive(Clone)] |
934 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
a1dfa0c6 | 935 | pub struct Ident(bridge::client::Ident); |
83c7162d | 936 | |
94b46f34 XL |
937 | impl Ident { |
938 | /// Creates a new `Ident` with the given `string` as well as the specified | |
83c7162d | 939 | /// `span`. |
94b46f34 | 940 | /// The `string` argument must be a valid identifier permitted by the |
3dfed10e | 941 | /// language (including keywords, e.g. `self` or `fn`). Otherwise, the function will panic. |
83c7162d XL |
942 | /// |
943 | /// Note that `span`, currently in rustc, configures the hygiene information | |
94b46f34 XL |
944 | /// for this identifier. |
945 | /// | |
946 | /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene | |
947 | /// meaning that identifiers created with this span will be resolved as if they were written | |
948 | /// directly at the location of the macro call, and other code at the macro call site will be | |
949 | /// able to refer to them as well. | |
950 | /// | |
951 | /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene | |
952 | /// meaning that identifiers created with this span will be resolved at the location of the | |
953 | /// macro definition and other code at the macro call site will not be able to refer to them. | |
83c7162d XL |
954 | /// |
955 | /// Due to the current importance of hygiene this constructor, unlike other | |
956 | /// tokens, requires a `Span` to be specified at construction. | |
8faf50e0 | 957 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 958 | pub fn new(string: &str, span: Span) -> Ident { |
a1dfa0c6 | 959 | Ident(bridge::client::Ident::new(string, span.0, false)) |
83c7162d XL |
960 | } |
961 | ||
94b46f34 | 962 | /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). |
3dfed10e XL |
963 | /// The `string` argument be a valid identifier permitted by the language |
964 | /// (including keywords, e.g. `fn`). Keywords which are usable in path segments | |
965 | /// (e.g. `self`, `super`) are not supported, and will cause a panic. | |
966 | #[stable(feature = "proc_macro_raw_ident", since = "1.47.0")] | |
94b46f34 | 967 | pub fn new_raw(string: &str, span: Span) -> Ident { |
a1dfa0c6 | 968 | Ident(bridge::client::Ident::new(string, span.0, true)) |
83c7162d XL |
969 | } |
970 | ||
94b46f34 | 971 | /// Returns the span of this `Ident`, encompassing the entire string returned |
29967ef6 | 972 | /// by [`to_string`](Self::to_string). |
8faf50e0 | 973 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 974 | pub fn span(&self) -> Span { |
a1dfa0c6 | 975 | Span(self.0.span()) |
83c7162d XL |
976 | } |
977 | ||
94b46f34 | 978 | /// Configures the span of this `Ident`, possibly changing its hygiene context. |
8faf50e0 | 979 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 980 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
981 | self.0 = self.0.with_span(span.0); |
982 | } | |
983 | } | |
984 | ||
0731742a | 985 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
986 | // based on it (the reverse of the usual relationship between the two). |
987 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
988 | impl ToString for Ident { | |
989 | fn to_string(&self) -> String { | |
990 | TokenStream::from(TokenTree::from(self.clone())).to_string() | |
83c7162d XL |
991 | } |
992 | } | |
993 | ||
94b46f34 XL |
994 | /// Prints the identifier as a string that should be losslessly convertible |
995 | /// back into the same identifier. | |
8faf50e0 | 996 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
94b46f34 | 997 | impl fmt::Display for Ident { |
9fa01778 | 998 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 999 | f.write_str(&self.to_string()) |
8faf50e0 XL |
1000 | } |
1001 | } | |
1002 | ||
1003 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] | |
1004 | impl fmt::Debug for Ident { | |
9fa01778 | 1005 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
8faf50e0 XL |
1006 | f.debug_struct("Ident") |
1007 | .field("ident", &self.to_string()) | |
1008 | .field("span", &self.span()) | |
1009 | .finish() | |
041b39d2 XL |
1010 | } |
1011 | } | |
1012 | ||
94b46f34 XL |
1013 | /// A literal string (`"hello"`), byte string (`b"hello"`), |
1014 | /// character (`'a'`), byte character (`b'a'`), an integer or floating point number | |
1015 | /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`). | |
1016 | /// Boolean literals like `true` and `false` do not belong here, they are `Ident`s. | |
a1dfa0c6 | 1017 | #[derive(Clone)] |
8faf50e0 | 1018 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
a1dfa0c6 | 1019 | pub struct Literal(bridge::client::Literal); |
83c7162d XL |
1020 | |
1021 | macro_rules! suffixed_int_literals { | |
1022 | ($($name:ident => $kind:ident,)*) => ($( | |
1023 | /// Creates a new suffixed integer literal with the specified value. | |
1024 | /// | |
1025 | /// This function will create an integer like `1u32` where the integer | |
1026 | /// value specified is the first part of the token and the integral is | |
1027 | /// also suffixed at the end. | |
94222f64 | 1028 | /// Literals created from negative numbers might not survive round-trips through |
94b46f34 | 1029 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1030 | /// |
1031 | /// Literals created through this method have the `Span::call_site()` | |
1032 | /// span by default, which can be configured with the `set_span` method | |
1033 | /// below. | |
8faf50e0 | 1034 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1035 | pub fn $name(n: $kind) -> Literal { |
a1dfa0c6 | 1036 | Literal(bridge::client::Literal::typed_integer(&n.to_string(), stringify!($kind))) |
041b39d2 | 1037 | } |
83c7162d XL |
1038 | )*) |
1039 | } | |
1040 | ||
1041 | macro_rules! unsuffixed_int_literals { | |
1042 | ($($name:ident => $kind:ident,)*) => ($( | |
1043 | /// Creates a new unsuffixed integer literal with the specified value. | |
1044 | /// | |
1045 | /// This function will create an integer like `1` where the integer | |
1046 | /// value specified is the first part of the token. No suffix is | |
1047 | /// specified on this token, meaning that invocations like | |
1048 | /// `Literal::i8_unsuffixed(1)` are equivalent to | |
1049 | /// `Literal::u32_unsuffixed(1)`. | |
94222f64 | 1050 | /// Literals created from negative numbers might not survive rountrips through |
94b46f34 | 1051 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1052 | /// |
1053 | /// Literals created through this method have the `Span::call_site()` | |
1054 | /// span by default, which can be configured with the `set_span` method | |
1055 | /// below. | |
8faf50e0 | 1056 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1057 | pub fn $name(n: $kind) -> Literal { |
a1dfa0c6 | 1058 | Literal(bridge::client::Literal::integer(&n.to_string())) |
83c7162d XL |
1059 | } |
1060 | )*) | |
041b39d2 XL |
1061 | } |
1062 | ||
1063 | impl Literal { | |
83c7162d XL |
1064 | suffixed_int_literals! { |
1065 | u8_suffixed => u8, | |
1066 | u16_suffixed => u16, | |
1067 | u32_suffixed => u32, | |
1068 | u64_suffixed => u64, | |
1069 | u128_suffixed => u128, | |
1070 | usize_suffixed => usize, | |
1071 | i8_suffixed => i8, | |
1072 | i16_suffixed => i16, | |
1073 | i32_suffixed => i32, | |
1074 | i64_suffixed => i64, | |
1075 | i128_suffixed => i128, | |
1076 | isize_suffixed => isize, | |
1077 | } | |
1078 | ||
1079 | unsuffixed_int_literals! { | |
1080 | u8_unsuffixed => u8, | |
1081 | u16_unsuffixed => u16, | |
1082 | u32_unsuffixed => u32, | |
1083 | u64_unsuffixed => u64, | |
1084 | u128_unsuffixed => u128, | |
1085 | usize_unsuffixed => usize, | |
1086 | i8_unsuffixed => i8, | |
1087 | i16_unsuffixed => i16, | |
1088 | i32_unsuffixed => i32, | |
1089 | i64_unsuffixed => i64, | |
1090 | i128_unsuffixed => i128, | |
1091 | isize_unsuffixed => isize, | |
041b39d2 XL |
1092 | } |
1093 | ||
83c7162d XL |
1094 | /// Creates a new unsuffixed floating-point literal. |
1095 | /// | |
1096 | /// This constructor is similar to those like `Literal::i8_unsuffixed` where | |
1097 | /// the float's value is emitted directly into the token but no suffix is | |
1098 | /// used, so it may be inferred to be a `f64` later in the compiler. | |
94222f64 | 1099 | /// Literals created from negative numbers might not survive rountrips through |
94b46f34 | 1100 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1101 | /// |
1102 | /// # Panics | |
1103 | /// | |
1104 | /// This function requires that the specified float is finite, for | |
1105 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1106 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d XL |
1107 | pub fn f32_unsuffixed(n: f32) -> Literal { |
1108 | if !n.is_finite() { | |
1109 | panic!("Invalid float literal {}", n); | |
1110 | } | |
3c0e092e XL |
1111 | let mut repr = n.to_string(); |
1112 | if !repr.contains('.') { | |
1113 | repr.push_str(".0"); | |
1114 | } | |
1115 | Literal(bridge::client::Literal::float(&repr)) | |
041b39d2 XL |
1116 | } |
1117 | ||
83c7162d XL |
1118 | /// Creates a new suffixed floating-point literal. |
1119 | /// | |
a1dfa0c6 | 1120 | /// This constructor will create a literal like `1.0f32` where the value |
83c7162d XL |
1121 | /// specified is the preceding part of the token and `f32` is the suffix of |
1122 | /// the token. This token will always be inferred to be an `f32` in the | |
1123 | /// compiler. | |
94222f64 | 1124 | /// Literals created from negative numbers might not survive rountrips through |
94b46f34 | 1125 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1126 | /// |
1127 | /// # Panics | |
1128 | /// | |
1129 | /// This function requires that the specified float is finite, for | |
1130 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1131 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1132 | pub fn f32_suffixed(n: f32) -> Literal { |
041b39d2 XL |
1133 | if !n.is_finite() { |
1134 | panic!("Invalid float literal {}", n); | |
1135 | } | |
a1dfa0c6 | 1136 | Literal(bridge::client::Literal::f32(&n.to_string())) |
041b39d2 XL |
1137 | } |
1138 | ||
83c7162d XL |
1139 | /// Creates a new unsuffixed floating-point literal. |
1140 | /// | |
1141 | /// This constructor is similar to those like `Literal::i8_unsuffixed` where | |
1142 | /// the float's value is emitted directly into the token but no suffix is | |
1143 | /// used, so it may be inferred to be a `f64` later in the compiler. | |
94222f64 | 1144 | /// Literals created from negative numbers might not survive rountrips through |
94b46f34 | 1145 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1146 | /// |
1147 | /// # Panics | |
1148 | /// | |
1149 | /// This function requires that the specified float is finite, for | |
1150 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1151 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1152 | pub fn f64_unsuffixed(n: f64) -> Literal { |
041b39d2 | 1153 | if !n.is_finite() { |
83c7162d XL |
1154 | panic!("Invalid float literal {}", n); |
1155 | } | |
3c0e092e XL |
1156 | let mut repr = n.to_string(); |
1157 | if !repr.contains('.') { | |
1158 | repr.push_str(".0"); | |
1159 | } | |
1160 | Literal(bridge::client::Literal::float(&repr)) | |
041b39d2 XL |
1161 | } |
1162 | ||
83c7162d XL |
1163 | /// Creates a new suffixed floating-point literal. |
1164 | /// | |
a1dfa0c6 | 1165 | /// This constructor will create a literal like `1.0f64` where the value |
83c7162d XL |
1166 | /// specified is the preceding part of the token and `f64` is the suffix of |
1167 | /// the token. This token will always be inferred to be an `f64` in the | |
1168 | /// compiler. | |
94222f64 | 1169 | /// Literals created from negative numbers might not survive rountrips through |
94b46f34 | 1170 | /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). |
83c7162d XL |
1171 | /// |
1172 | /// # Panics | |
1173 | /// | |
1174 | /// This function requires that the specified float is finite, for | |
1175 | /// example if it is infinity or NaN this function will panic. | |
8faf50e0 | 1176 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1177 | pub fn f64_suffixed(n: f64) -> Literal { |
041b39d2 | 1178 | if !n.is_finite() { |
83c7162d XL |
1179 | panic!("Invalid float literal {}", n); |
1180 | } | |
a1dfa0c6 | 1181 | Literal(bridge::client::Literal::f64(&n.to_string())) |
041b39d2 XL |
1182 | } |
1183 | ||
1184 | /// String literal. | |
8faf50e0 | 1185 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1186 | pub fn string(string: &str) -> Literal { |
a1dfa0c6 | 1187 | Literal(bridge::client::Literal::string(string)) |
041b39d2 XL |
1188 | } |
1189 | ||
1190 | /// Character literal. | |
8faf50e0 | 1191 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1192 | pub fn character(ch: char) -> Literal { |
a1dfa0c6 | 1193 | Literal(bridge::client::Literal::character(ch)) |
041b39d2 XL |
1194 | } |
1195 | ||
1196 | /// Byte string literal. | |
8faf50e0 | 1197 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
041b39d2 | 1198 | pub fn byte_string(bytes: &[u8]) -> Literal { |
a1dfa0c6 | 1199 | Literal(bridge::client::Literal::byte_string(bytes)) |
041b39d2 | 1200 | } |
041b39d2 | 1201 | |
83c7162d | 1202 | /// Returns the span encompassing this literal. |
8faf50e0 | 1203 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1204 | pub fn span(&self) -> Span { |
a1dfa0c6 | 1205 | Span(self.0.span()) |
83c7162d XL |
1206 | } |
1207 | ||
1208 | /// Configures the span associated for this literal. | |
8faf50e0 | 1209 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1210 | pub fn set_span(&mut self, span: Span) { |
a1dfa0c6 XL |
1211 | self.0.set_span(span.0); |
1212 | } | |
1213 | ||
1214 | /// Returns a `Span` that is a subset of `self.span()` containing only the | |
1215 | /// source bytes in range `range`. Returns `None` if the would-be trimmed | |
1216 | /// span is outside the bounds of `self`. | |
1217 | // FIXME(SergioBenitez): check that the byte range starts and ends at a | |
1218 | // UTF-8 boundary of the source. otherwise, it's likely that a panic will | |
1219 | // occur elsewhere when the source text is printed. | |
1220 | // FIXME(SergioBenitez): there is no way for the user to know what | |
1221 | // `self.span()` actually maps to, so this method can currently only be | |
1222 | // called blindly. For example, `to_string()` for the character 'c' returns | |
1223 | // "'\u{63}'"; there is no way for the user to know whether the source text | |
1224 | // was 'c' or whether it was '\u{63}'. | |
1225 | #[unstable(feature = "proc_macro_span", issue = "54725")] | |
1226 | pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { | |
17df50a5 XL |
1227 | self.0.subspan(range.start_bound().cloned(), range.end_bound().cloned()).map(Span) |
1228 | } | |
1229 | } | |
1230 | ||
1231 | /// Parse a single literal from its stringified representation. | |
1232 | /// | |
1233 | /// In order to parse successfully, the input string must not contain anything | |
1234 | /// but the literal token. Specifically, it must not contain whitespace or | |
1235 | /// comments in addition to the literal. | |
1236 | /// | |
1237 | /// The resulting literal token will have a `Span::call_site()` span. | |
1238 | /// | |
1239 | /// NOTE: some errors may cause panics instead of returning `LexError`. We | |
1240 | /// reserve the right to change these errors into `LexError`s later. | |
1241 | #[stable(feature = "proc_macro_literal_parse", since = "1.54.0")] | |
1242 | impl FromStr for Literal { | |
1243 | type Err = LexError; | |
a1dfa0c6 | 1244 | |
17df50a5 XL |
1245 | fn from_str(src: &str) -> Result<Self, LexError> { |
1246 | match bridge::client::Literal::from_str(src) { | |
1247 | Ok(literal) => Ok(Literal(literal)), | |
3c0e092e | 1248 | Err(()) => Err(LexError), |
17df50a5 | 1249 | } |
a1dfa0c6 XL |
1250 | } |
1251 | } | |
1252 | ||
0731742a | 1253 | // N.B., the bridge only provides `to_string`, implement `fmt::Display` |
a1dfa0c6 XL |
1254 | // based on it (the reverse of the usual relationship between the two). |
1255 | #[stable(feature = "proc_macro_lib", since = "1.15.0")] | |
1256 | impl ToString for Literal { | |
1257 | fn to_string(&self) -> String { | |
94222f64 | 1258 | self.0.to_string() |
83c7162d | 1259 | } |
041b39d2 XL |
1260 | } |
1261 | ||
94b46f34 XL |
1262 | /// Prints the literal as a string that should be losslessly convertible |
1263 | /// back into the same literal (except for possible rounding for floating point literals). | |
8faf50e0 | 1264 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
83c7162d | 1265 | impl fmt::Display for Literal { |
9fa01778 | 1266 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 1267 | f.write_str(&self.to_string()) |
041b39d2 XL |
1268 | } |
1269 | } | |
1270 | ||
a1dfa0c6 XL |
1271 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")] |
1272 | impl fmt::Debug for Literal { | |
9fa01778 | 1273 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
a1dfa0c6 | 1274 | self.0.fmt(f) |
c30ab7b3 SL |
1275 | } |
1276 | } | |
3dfed10e XL |
1277 | |
1278 | /// Tracked access to environment variables. | |
1279 | #[unstable(feature = "proc_macro_tracked_env", issue = "74690")] | |
1280 | pub mod tracked_env { | |
1281 | use std::env::{self, VarError}; | |
1282 | use std::ffi::OsStr; | |
1283 | ||
1284 | /// Retrieve an environment variable and add it to build dependency info. | |
1285 | /// Build system executing the compiler will know that the variable was accessed during | |
1286 | /// compilation, and will be able to rerun the build when the value of that variable changes. | |
1287 | /// Besides the dependency tracking this function should be equivalent to `env::var` from the | |
1288 | /// standard library, except that the argument must be UTF-8. | |
1289 | #[unstable(feature = "proc_macro_tracked_env", issue = "74690")] | |
1290 | pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> { | |
1291 | let key: &str = key.as_ref(); | |
1292 | let value = env::var(key); | |
1293 | crate::bridge::client::FreeFunctions::track_env_var(key, value.as_deref().ok()); | |
1294 | value | |
1295 | } | |
1296 | } | |
136023e0 XL |
1297 | |
1298 | /// Tracked access to additional files. | |
1299 | #[unstable(feature = "track_path", issue = "73921")] | |
1300 | pub mod tracked_path { | |
1301 | ||
1302 | /// Track a file explicitly. | |
1303 | /// | |
1304 | /// Commonly used for tracking asset preprocessing. | |
1305 | #[unstable(feature = "track_path", issue = "73921")] | |
1306 | pub fn path<P: AsRef<str>>(path: P) { | |
1307 | let path: &str = path.as_ref(); | |
1308 | crate::bridge::client::FreeFunctions::track_path(path); | |
1309 | } | |
1310 | } |