1 //! lib-proc-macro main module 2 //! 3 //! Copy from <https://github.com/rust-lang/rust/blob/6050e523bae6de61de4e060facc43dc512adaccd/src/libproc_macro/lib.rs> 4 //! augmented with removing unstable features 5 6 // NOTE(@edwin0cheng): 7 // Because we just copy the bridge module from rustc for ABI compatible 8 // There are some unused stuffs inside it. 9 // We suppress these warning here. 10 #[doc(hidden)] 11 #[allow(unused_macros)] 12 #[allow(unused_variables)] 13 pub mod bridge; 14 15 mod diagnostic; 16 17 pub use diagnostic::{Diagnostic, Level, MultiSpan}; 18 19 use std::ops::{Bound, RangeBounds}; 20 use std::path::PathBuf; 21 use std::str::FromStr; 22 use std::{fmt, iter, mem}; 23 24 /// The main type provided by this crate, representing an abstract stream of 25 /// tokens, or, more specifically, a sequence of token trees. 26 /// The type provide interfaces for iterating over those token trees and, conversely, 27 /// collecting a number of token trees into one stream. 28 /// 29 /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` 30 /// and `#[proc_macro_derive]` definitions. 31 #[derive(Clone)] 32 pub struct TokenStream(bridge::client::TokenStream); 33 34 /// Error returned from `TokenStream::from_str` 35 #[derive(Debug)] 36 pub struct LexError { 37 _inner: (), 38 } 39 impl LexError { new() -> Self40 fn new() -> Self { 41 LexError { _inner: () } 42 } 43 } 44 45 impl TokenStream { 46 /// Returns an empty `TokenStream` containing no token trees. new() -> TokenStream47 pub fn new() -> TokenStream { 48 TokenStream(bridge::client::TokenStream::new()) 49 } 50 51 /// Checks if this `TokenStream` is empty. is_empty(&self) -> bool52 pub fn is_empty(&self) -> bool { 53 self.0.is_empty() 54 } 55 } 56 57 /// Attempts to break the string into tokens and parse those tokens into a token stream. 58 /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters 59 /// or characters not existing in the language. 60 /// All tokens in the parsed stream get `Span::call_site()` spans. 61 /// 62 /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to 63 /// change these errors into `LexError`s later. 64 impl FromStr for TokenStream { 65 type Err = LexError; 66 from_str(src: &str) -> Result<TokenStream, LexError>67 fn from_str(src: &str) -> Result<TokenStream, LexError> { 68 Ok(TokenStream(bridge::client::TokenStream::from_str(src))) 69 } 70 } 71 72 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 73 // based on it (the reverse of the usual relationship between the two). 74 // impl ToString for TokenStream { 75 // fn to_string(&self) -> String { 76 // self.0.to_string() 77 // } 78 // } 79 80 /// Prints the token stream as a string that is supposed to be losslessly convertible back 81 /// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s 82 /// with `Delimiter::None` delimiters and negative numeric literals. 83 impl fmt::Display for TokenStream { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 85 f.write_str(&self.to_string()) 86 } 87 } 88 89 /// Prints token in a form convenient for debugging. 90 impl fmt::Debug for TokenStream { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 92 f.write_str("TokenStream ")?; 93 f.debug_list().entries(self.clone()).finish() 94 } 95 } 96 97 /// Creates a token stream containing a single token tree. 98 impl From<TokenTree> for TokenStream { from(tree: TokenTree) -> TokenStream99 fn from(tree: TokenTree) -> TokenStream { 100 TokenStream(bridge::client::TokenStream::from_token_tree(match tree { 101 TokenTree::Group(tt) => bridge::TokenTree::Group(tt.0), 102 TokenTree::Punct(tt) => bridge::TokenTree::Punct(tt.0), 103 TokenTree::Ident(tt) => bridge::TokenTree::Ident(tt.0), 104 TokenTree::Literal(tt) => bridge::TokenTree::Literal(tt.0), 105 })) 106 } 107 } 108 109 /// Collects a number of token trees into a single stream. 110 impl iter::FromIterator<TokenTree> for TokenStream { from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self111 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { 112 trees.into_iter().map(TokenStream::from).collect() 113 } 114 } 115 116 /// A "flattening" operation on token streams, collects token trees 117 /// from multiple token streams into a single stream. 118 impl iter::FromIterator<TokenStream> for TokenStream { from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self119 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { 120 let mut builder = bridge::client::TokenStreamBuilder::new(); 121 streams.into_iter().for_each(|stream| builder.push(stream.0)); 122 TokenStream(builder.build()) 123 } 124 } 125 126 impl Extend<TokenTree> for TokenStream { extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I)127 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) { 128 self.extend(trees.into_iter().map(TokenStream::from)); 129 } 130 } 131 132 impl Extend<TokenStream> for TokenStream { extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)133 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { 134 // FIXME(eddyb) Use an optimized implementation if/when possible. 135 *self = iter::once(mem::replace(self, Self::new())).chain(streams).collect(); 136 } 137 } 138 139 /// Public implementation details for the `TokenStream` type, such as iterators. 140 pub mod token_stream { 141 use super::{bridge, Group, Ident, Literal, Punct, TokenStream, TokenTree}; 142 143 /// An iterator over `TokenStream`'s `TokenTree`s. 144 /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, 145 /// and returns whole groups as token trees. 146 #[derive(Clone)] 147 pub struct IntoIter(bridge::client::TokenStreamIter); 148 149 impl Iterator for IntoIter { 150 type Item = TokenTree; 151 next(&mut self) -> Option<TokenTree>152 fn next(&mut self) -> Option<TokenTree> { 153 self.0.next().map(|tree| match tree { 154 bridge::TokenTree::Group(tt) => TokenTree::Group(Group(tt)), 155 bridge::TokenTree::Punct(tt) => TokenTree::Punct(Punct(tt)), 156 bridge::TokenTree::Ident(tt) => TokenTree::Ident(Ident(tt)), 157 bridge::TokenTree::Literal(tt) => TokenTree::Literal(Literal(tt)), 158 }) 159 } 160 } 161 162 impl IntoIterator for TokenStream { 163 type Item = TokenTree; 164 type IntoIter = IntoIter; 165 into_iter(self) -> IntoIter166 fn into_iter(self) -> IntoIter { 167 IntoIter(self.0.into_iter()) 168 } 169 } 170 } 171 172 /// A region of source code, along with macro expansion information. 173 #[derive(Copy, Clone)] 174 pub struct Span(bridge::client::Span); 175 176 macro_rules! diagnostic_method { 177 ($name:ident, $level:expr) => { 178 /// Creates a new `Diagnostic` with the given `message` at the span 179 /// `self`. 180 pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic { 181 Diagnostic::spanned(self, $level, message) 182 } 183 }; 184 } 185 186 impl Span { 187 /// A span that resolves at the macro definition site. def_site() -> Span188 pub fn def_site() -> Span { 189 Span(bridge::client::Span::def_site()) 190 } 191 192 /// The span of the invocation of the current procedural macro. 193 /// Identifiers created with this span will be resolved as if they were written 194 /// directly at the macro call location (call-site hygiene) and other code 195 /// at the macro call site will be able to refer to them as well. call_site() -> Span196 pub fn call_site() -> Span { 197 Span(bridge::client::Span::call_site()) 198 } 199 200 /// A span that represents `macro_rules` hygiene, and sometimes resolves at the macro 201 /// definition site (local variables, labels, `$crate`) and sometimes at the macro 202 /// call site (everything else). 203 /// The span location is taken from the call-site. mixed_site() -> Span204 pub fn mixed_site() -> Span { 205 Span(bridge::client::Span::mixed_site()) 206 } 207 208 /// The original source file into which this span points. source_file(&self) -> SourceFile209 pub fn source_file(&self) -> SourceFile { 210 SourceFile(self.0.source_file()) 211 } 212 213 /// The `Span` for the tokens in the previous macro expansion from which 214 /// `self` was generated from, if any. parent(&self) -> Option<Span>215 pub fn parent(&self) -> Option<Span> { 216 self.0.parent().map(Span) 217 } 218 219 /// The span for the origin source code that `self` was generated from. If 220 /// this `Span` wasn't generated from other macro expansions then the return 221 /// value is the same as `*self`. source(&self) -> Span222 pub fn source(&self) -> Span { 223 Span(self.0.source()) 224 } 225 226 /// Gets the starting line/column in the source file for this span. start(&self) -> LineColumn227 pub fn start(&self) -> LineColumn { 228 self.0.start() 229 } 230 231 /// Gets the ending line/column in the source file for this span. end(&self) -> LineColumn232 pub fn end(&self) -> LineColumn { 233 self.0.end() 234 } 235 236 /// Creates a new span encompassing `self` and `other`. 237 /// 238 /// Returns `None` if `self` and `other` are from different files. join(&self, other: Span) -> Option<Span>239 pub fn join(&self, other: Span) -> Option<Span> { 240 self.0.join(other.0).map(Span) 241 } 242 243 /// Creates a new span with the same line/column information as `self` but 244 /// that resolves symbols as though it were at `other`. resolved_at(&self, other: Span) -> Span245 pub fn resolved_at(&self, other: Span) -> Span { 246 Span(self.0.resolved_at(other.0)) 247 } 248 249 /// Creates a new span with the same name resolution behavior as `self` but 250 /// with the line/column information of `other`. located_at(&self, other: Span) -> Span251 pub fn located_at(&self, other: Span) -> Span { 252 other.resolved_at(*self) 253 } 254 255 /// Compares to spans to see if they're equal. eq(&self, other: &Span) -> bool256 pub fn eq(&self, other: &Span) -> bool { 257 self.0 == other.0 258 } 259 260 /// Returns the source text behind a span. This preserves the original source 261 /// code, including spaces and comments. It only returns a result if the span 262 /// corresponds to real source code. 263 /// 264 /// Note: The observable result of a macro should only rely on the tokens and 265 /// not on this source text. The result of this function is a best effort to 266 /// be used for diagnostics only. source_text(&self) -> Option<String>267 pub fn source_text(&self) -> Option<String> { 268 self.0.source_text() 269 } 270 271 diagnostic_method!(error, Level::Error); 272 diagnostic_method!(warning, Level::Warning); 273 diagnostic_method!(note, Level::Note); 274 diagnostic_method!(help, Level::Help); 275 } 276 277 /// Prints a span in a form convenient for debugging. 278 impl fmt::Debug for Span { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 280 self.0.fmt(f) 281 } 282 } 283 284 /// A line-column pair representing the start or end of a `Span`. 285 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 286 pub struct LineColumn { 287 /// The 1-indexed line in the source file on which the span starts or ends (inclusive). 288 pub line: usize, 289 /// The 0-indexed column (in UTF-8 characters) in the source file on which 290 /// the span starts or ends (inclusive). 291 pub column: usize, 292 } 293 294 /// The source file of a given `Span`. 295 #[derive(Clone)] 296 pub struct SourceFile(bridge::client::SourceFile); 297 298 impl SourceFile { 299 /// Gets the path to this source file. 300 /// 301 /// ### Note 302 /// If the code span associated with this `SourceFile` was generated by an external macro, this 303 /// macro, this may not be an actual path on the filesystem. Use [`is_real`] to check. 304 /// 305 /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on 306 /// the command line, the path as given may not actually be valid. 307 /// 308 /// [`is_real`]: #method.is_real path(&self) -> PathBuf309 pub fn path(&self) -> PathBuf { 310 PathBuf::from(self.0.path()) 311 } 312 313 /// Returns `true` if this source file is a real source file, and not generated by an external 314 /// macro's expansion. is_real(&self) -> bool315 pub fn is_real(&self) -> bool { 316 // This is a hack until intercrate spans are implemented and we can have real source files 317 // for spans generated in external macros. 318 // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368 319 self.0.is_real() 320 } 321 } 322 323 impl fmt::Debug for SourceFile { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 325 f.debug_struct("SourceFile") 326 .field("path", &self.path()) 327 .field("is_real", &self.is_real()) 328 .finish() 329 } 330 } 331 332 impl PartialEq for SourceFile { eq(&self, other: &Self) -> bool333 fn eq(&self, other: &Self) -> bool { 334 self.0.eq(&other.0) 335 } 336 } 337 338 impl Eq for SourceFile {} 339 340 /// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`). 341 #[derive(Clone)] 342 pub enum TokenTree { 343 /// A token stream surrounded by bracket delimiters. 344 Group(Group), 345 /// An identifier. 346 Ident(Ident), 347 /// A single punctuation character (`+`, `,`, `$`, etc.). 348 Punct(Punct), 349 /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. 350 Literal(Literal), 351 } 352 353 impl TokenTree { 354 /// Returns the span of this tree, delegating to the `span` method of 355 /// the contained token or a delimited stream. span(&self) -> Span356 pub fn span(&self) -> Span { 357 match *self { 358 TokenTree::Group(ref t) => t.span(), 359 TokenTree::Ident(ref t) => t.span(), 360 TokenTree::Punct(ref t) => t.span(), 361 TokenTree::Literal(ref t) => t.span(), 362 } 363 } 364 365 /// Configures the span for *only this token*. 366 /// 367 /// Note that if this token is a `Group` then this method will not configure 368 /// the span of each of the internal tokens, this will simply delegate to 369 /// the `set_span` method of each variant. set_span(&mut self, span: Span)370 pub fn set_span(&mut self, span: Span) { 371 match *self { 372 TokenTree::Group(ref mut t) => t.set_span(span), 373 TokenTree::Ident(ref mut t) => t.set_span(span), 374 TokenTree::Punct(ref mut t) => t.set_span(span), 375 TokenTree::Literal(ref mut t) => t.set_span(span), 376 } 377 } 378 } 379 380 /// Prints token tree in a form convenient for debugging. 381 impl fmt::Debug for TokenTree { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 383 // Each of these has the name in the struct type in the derived debug, 384 // so don't bother with an extra layer of indirection 385 match *self { 386 TokenTree::Group(ref tt) => tt.fmt(f), 387 TokenTree::Ident(ref tt) => tt.fmt(f), 388 TokenTree::Punct(ref tt) => tt.fmt(f), 389 TokenTree::Literal(ref tt) => tt.fmt(f), 390 } 391 } 392 } 393 394 impl From<Group> for TokenTree { from(g: Group) -> TokenTree395 fn from(g: Group) -> TokenTree { 396 TokenTree::Group(g) 397 } 398 } 399 400 impl From<Ident> for TokenTree { from(g: Ident) -> TokenTree401 fn from(g: Ident) -> TokenTree { 402 TokenTree::Ident(g) 403 } 404 } 405 406 impl From<Punct> for TokenTree { from(g: Punct) -> TokenTree407 fn from(g: Punct) -> TokenTree { 408 TokenTree::Punct(g) 409 } 410 } 411 412 impl From<Literal> for TokenTree { from(g: Literal) -> TokenTree413 fn from(g: Literal) -> TokenTree { 414 TokenTree::Literal(g) 415 } 416 } 417 418 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 419 // based on it (the reverse of the usual relationship between the two). 420 // impl ToString for TokenTree { 421 // fn to_string(&self) -> String { 422 // match *self { 423 // TokenTree::Group(ref t) => t.to_string(), 424 // TokenTree::Ident(ref t) => t.to_string(), 425 // TokenTree::Punct(ref t) => t.to_string(), 426 // TokenTree::Literal(ref t) => t.to_string(), 427 // } 428 // } 429 // } 430 431 /// Prints the token tree as a string that is supposed to be losslessly convertible back 432 /// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s 433 /// with `Delimiter::None` delimiters and negative numeric literals. 434 impl fmt::Display for TokenTree { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 436 f.write_str(&self.to_string()) 437 } 438 } 439 440 /// A delimited token stream. 441 /// 442 /// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s. 443 #[derive(Clone)] 444 pub struct Group(bridge::client::Group); 445 446 /// Describes how a sequence of token trees is delimited. 447 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 448 pub enum Delimiter { 449 /// `( ... )` 450 Parenthesis, 451 /// `{ ... }` 452 Brace, 453 /// `[ ... ]` 454 Bracket, 455 /// `Ø ... Ø` 456 /// An implicit delimiter, that may, for example, appear around tokens coming from a 457 /// "macro variable" `$var`. It is important to preserve operator priorities in cases like 458 /// `$var * 3` where `$var` is `1 + 2`. 459 /// Implicit delimiters may not survive roundtrip of a token stream through a string. 460 None, 461 } 462 463 impl Group { 464 /// Creates a new `Group` with the given delimiter and token stream. 465 /// 466 /// This constructor will set the span for this group to 467 /// `Span::call_site()`. To change the span you can use the `set_span` 468 /// method below. new(delimiter: Delimiter, stream: TokenStream) -> Group469 pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { 470 Group(bridge::client::Group::new(delimiter, stream.0)) 471 } 472 473 /// Returns the delimiter of this `Group` delimiter(&self) -> Delimiter474 pub fn delimiter(&self) -> Delimiter { 475 self.0.delimiter() 476 } 477 478 /// Returns the `TokenStream` of tokens that are delimited in this `Group`. 479 /// 480 /// Note that the returned token stream does not include the delimiter 481 /// returned above. stream(&self) -> TokenStream482 pub fn stream(&self) -> TokenStream { 483 TokenStream(self.0.stream()) 484 } 485 486 /// Returns the span for the delimiters of this token stream, spanning the 487 /// entire `Group`. 488 /// 489 /// ```text 490 /// pub fn span(&self) -> Span { 491 /// ^^^^^^^ 492 /// ``` span(&self) -> Span493 pub fn span(&self) -> Span { 494 Span(self.0.span()) 495 } 496 497 /// Returns the span pointing to the opening delimiter of this group. 498 /// 499 /// ```text 500 /// pub fn span_open(&self) -> Span { 501 /// ^ 502 /// ``` span_open(&self) -> Span503 pub fn span_open(&self) -> Span { 504 Span(self.0.span_open()) 505 } 506 507 /// Returns the span pointing to the closing delimiter of this group. 508 /// 509 /// ```text 510 /// pub fn span_close(&self) -> Span { 511 /// ^ 512 /// ``` span_close(&self) -> Span513 pub fn span_close(&self) -> Span { 514 Span(self.0.span_close()) 515 } 516 517 /// Configures the span for this `Group`'s delimiters, but not its internal 518 /// tokens. 519 /// 520 /// This method will **not** set the span of all the internal tokens spanned 521 /// by this group, but rather it will only set the span of the delimiter 522 /// tokens at the level of the `Group`. set_span(&mut self, span: Span)523 pub fn set_span(&mut self, span: Span) { 524 self.0.set_span(span.0); 525 } 526 } 527 528 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 529 // based on it (the reverse of the usual relationship between the two). 530 // impl ToString for Group { 531 // fn to_string(&self) -> String { 532 // TokenStream::from(TokenTree::from(self.clone())).to_string() 533 // } 534 // } 535 536 /// Prints the group as a string that should be losslessly convertible back 537 /// into the same group (modulo spans), except for possibly `TokenTree::Group`s 538 /// with `Delimiter::None` delimiters. 539 impl fmt::Display for Group { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 541 f.write_str(&self.to_string()) 542 } 543 } 544 545 impl fmt::Debug for Group { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result546 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 547 f.debug_struct("Group") 548 .field("delimiter", &self.delimiter()) 549 .field("stream", &self.stream()) 550 .field("span", &self.span()) 551 .finish() 552 } 553 } 554 555 /// An `Punct` is an single punctuation character like `+`, `-` or `#`. 556 /// 557 /// Multi-character operators like `+=` are represented as two instances of `Punct` with different 558 /// forms of `Spacing` returned. 559 #[derive(Clone)] 560 pub struct Punct(bridge::client::Punct); 561 562 /// Whether an `Punct` is followed immediately by another `Punct` or 563 /// followed by another token or whitespace. 564 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 565 pub enum Spacing { 566 /// e.g., `+` is `Alone` in `+ =`, `+ident` or `+()`. 567 Alone, 568 /// e.g., `+` is `Joint` in `+=` or `'#`. 569 /// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`. 570 Joint, 571 } 572 573 impl Punct { 574 /// Creates a new `Punct` from the given character and spacing. 575 /// The `ch` argument must be a valid punctuation character permitted by the language, 576 /// otherwise the function will panic. 577 /// 578 /// The returned `Punct` will have the default span of `Span::call_site()` 579 /// which can be further configured with the `set_span` method below. new(ch: char, spacing: Spacing) -> Punct580 pub fn new(ch: char, spacing: Spacing) -> Punct { 581 Punct(bridge::client::Punct::new(ch, spacing)) 582 } 583 584 /// Returns the value of this punctuation character as `char`. as_char(&self) -> char585 pub fn as_char(&self) -> char { 586 self.0.as_char() 587 } 588 589 /// Returns the spacing of this punctuation character, indicating whether it's immediately 590 /// followed by another `Punct` in the token stream, so they can potentially be combined into 591 /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace 592 /// (`Alone`) so the operator has certainly ended. spacing(&self) -> Spacing593 pub fn spacing(&self) -> Spacing { 594 self.0.spacing() 595 } 596 597 /// Returns the span for this punctuation character. span(&self) -> Span598 pub fn span(&self) -> Span { 599 Span(self.0.span()) 600 } 601 602 /// Configure the span for this punctuation character. set_span(&mut self, span: Span)603 pub fn set_span(&mut self, span: Span) { 604 self.0 = self.0.with_span(span.0); 605 } 606 } 607 608 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 609 // based on it (the reverse of the usual relationship between the two). 610 // impl ToString for Punct { 611 // fn to_string(&self) -> String { 612 // TokenStream::from(TokenTree::from(self.clone())).to_string() 613 // } 614 // } 615 616 /// Prints the punctuation character as a string that should be losslessly convertible 617 /// back into the same character. 618 impl fmt::Display for Punct { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result619 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 620 f.write_str(&self.to_string()) 621 } 622 } 623 624 impl fmt::Debug for Punct { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result625 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 626 f.debug_struct("Punct") 627 .field("ch", &self.as_char()) 628 .field("spacing", &self.spacing()) 629 .field("span", &self.span()) 630 .finish() 631 } 632 } 633 634 /// An identifier (`ident`). 635 #[derive(Clone, PartialEq, Eq, Hash)] 636 pub struct Ident(bridge::client::Ident); 637 638 impl Ident { 639 /// Creates a new `Ident` with the given `string` as well as the specified 640 /// `span`. 641 /// The `string` argument must be a valid identifier permitted by the 642 /// language, otherwise the function will panic. 643 /// 644 /// Note that `span`, currently in rustc, configures the hygiene information 645 /// for this identifier. 646 /// 647 /// As of this time `Span::call_site()` explicitly opts-in to "call-site" hygiene 648 /// meaning that identifiers created with this span will be resolved as if they were written 649 /// directly at the location of the macro call, and other code at the macro call site will be 650 /// able to refer to them as well. 651 /// 652 /// Later spans like `Span::def_site()` will allow to opt-in to "definition-site" hygiene 653 /// meaning that identifiers created with this span will be resolved at the location of the 654 /// macro definition and other code at the macro call site will not be able to refer to them. 655 /// 656 /// Due to the current importance of hygiene this constructor, unlike other 657 /// tokens, requires a `Span` to be specified at construction. new(string: &str, span: Span) -> Ident658 pub fn new(string: &str, span: Span) -> Ident { 659 Ident(bridge::client::Ident::new(string, span.0, false)) 660 } 661 662 /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). new_raw(string: &str, span: Span) -> Ident663 pub fn new_raw(string: &str, span: Span) -> Ident { 664 Ident(bridge::client::Ident::new(string, span.0, true)) 665 } 666 667 /// Returns the span of this `Ident`, encompassing the entire string returned 668 /// by `as_str`. span(&self) -> Span669 pub fn span(&self) -> Span { 670 Span(self.0.span()) 671 } 672 673 /// Configures the span of this `Ident`, possibly changing its hygiene context. set_span(&mut self, span: Span)674 pub fn set_span(&mut self, span: Span) { 675 self.0 = self.0.with_span(span.0); 676 } 677 } 678 679 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 680 // based on it (the reverse of the usual relationship between the two). 681 // impl ToString for Ident { 682 // fn to_string(&self) -> String { 683 // TokenStream::from(TokenTree::from(self.clone())).to_string() 684 // } 685 // } 686 687 /// Prints the identifier as a string that should be losslessly convertible 688 /// back into the same identifier. 689 impl fmt::Display for Ident { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result690 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 691 f.write_str(&self.to_string()) 692 } 693 } 694 695 impl fmt::Debug for Ident { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result696 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 697 f.debug_struct("Ident") 698 .field("ident", &self.to_string()) 699 .field("span", &self.span()) 700 .finish() 701 } 702 } 703 704 /// A literal string (`"hello"`), byte string (`b"hello"`), 705 /// character (`'a'`), byte character (`b'a'`), an integer or floating point number 706 /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`). 707 /// Boolean literals like `true` and `false` do not belong here, they are `Ident`s. 708 #[derive(Clone)] 709 pub struct Literal(bridge::client::Literal); 710 711 macro_rules! suffixed_int_literals { 712 ($($name:ident => $kind:ident,)*) => ($( 713 /// Creates a new suffixed integer literal with the specified value. 714 /// 715 /// This function will create an integer like `1u32` where the integer 716 /// value specified is the first part of the token and the integral is 717 /// also suffixed at the end. 718 /// Literals created from negative numbers may not survive round-trips through 719 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 720 /// 721 /// Literals created through this method have the `Span::call_site()` 722 /// span by default, which can be configured with the `set_span` method 723 /// below. 724 pub fn $name(n: $kind) -> Literal { 725 Literal(bridge::client::Literal::typed_integer(&n.to_string(), stringify!($kind))) 726 } 727 )*) 728 } 729 730 macro_rules! unsuffixed_int_literals { 731 ($($name:ident => $kind:ident,)*) => ($( 732 /// Creates a new unsuffixed integer literal with the specified value. 733 /// 734 /// This function will create an integer like `1` where the integer 735 /// value specified is the first part of the token. No suffix is 736 /// specified on this token, meaning that invocations like 737 /// `Literal::i8_unsuffixed(1)` are equivalent to 738 /// `Literal::u32_unsuffixed(1)`. 739 /// Literals created from negative numbers may not survive rountrips through 740 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 741 /// 742 /// Literals created through this method have the `Span::call_site()` 743 /// span by default, which can be configured with the `set_span` method 744 /// below. 745 pub fn $name(n: $kind) -> Literal { 746 Literal(bridge::client::Literal::integer(&n.to_string())) 747 } 748 )*) 749 } 750 751 impl Literal { 752 suffixed_int_literals! { 753 u8_suffixed => u8, 754 u16_suffixed => u16, 755 u32_suffixed => u32, 756 u64_suffixed => u64, 757 u128_suffixed => u128, 758 usize_suffixed => usize, 759 i8_suffixed => i8, 760 i16_suffixed => i16, 761 i32_suffixed => i32, 762 i64_suffixed => i64, 763 i128_suffixed => i128, 764 isize_suffixed => isize, 765 } 766 767 unsuffixed_int_literals! { 768 u8_unsuffixed => u8, 769 u16_unsuffixed => u16, 770 u32_unsuffixed => u32, 771 u64_unsuffixed => u64, 772 u128_unsuffixed => u128, 773 usize_unsuffixed => usize, 774 i8_unsuffixed => i8, 775 i16_unsuffixed => i16, 776 i32_unsuffixed => i32, 777 i64_unsuffixed => i64, 778 i128_unsuffixed => i128, 779 isize_unsuffixed => isize, 780 } 781 782 /// Creates a new unsuffixed floating-point literal. 783 /// 784 /// This constructor is similar to those like `Literal::i8_unsuffixed` where 785 /// the float's value is emitted directly into the token but no suffix is 786 /// used, so it may be inferred to be a `f64` later in the compiler. 787 /// Literals created from negative numbers may not survive rountrips through 788 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 789 /// 790 /// # Panics 791 /// 792 /// This function requires that the specified float is finite, for 793 /// example if it is infinity or NaN this function will panic. f32_unsuffixed(n: f32) -> Literal794 pub fn f32_unsuffixed(n: f32) -> Literal { 795 if !n.is_finite() { 796 panic!("Invalid float literal {}", n); 797 } 798 Literal(bridge::client::Literal::float(&n.to_string())) 799 } 800 801 /// Creates a new suffixed floating-point literal. 802 /// 803 /// This constructor will create a literal like `1.0f32` where the value 804 /// specified is the preceding part of the token and `f32` is the suffix of 805 /// the token. This token will always be inferred to be an `f32` in the 806 /// compiler. 807 /// Literals created from negative numbers may not survive rountrips through 808 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 809 /// 810 /// # Panics 811 /// 812 /// This function requires that the specified float is finite, for 813 /// example if it is infinity or NaN this function will panic. f32_suffixed(n: f32) -> Literal814 pub fn f32_suffixed(n: f32) -> Literal { 815 if !n.is_finite() { 816 panic!("Invalid float literal {}", n); 817 } 818 Literal(bridge::client::Literal::f32(&n.to_string())) 819 } 820 821 /// Creates a new unsuffixed floating-point literal. 822 /// 823 /// This constructor is similar to those like `Literal::i8_unsuffixed` where 824 /// the float's value is emitted directly into the token but no suffix is 825 /// used, so it may be inferred to be a `f64` later in the compiler. 826 /// Literals created from negative numbers may not survive rountrips through 827 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 828 /// 829 /// # Panics 830 /// 831 /// This function requires that the specified float is finite, for 832 /// example if it is infinity or NaN this function will panic. f64_unsuffixed(n: f64) -> Literal833 pub fn f64_unsuffixed(n: f64) -> Literal { 834 if !n.is_finite() { 835 panic!("Invalid float literal {}", n); 836 } 837 Literal(bridge::client::Literal::float(&n.to_string())) 838 } 839 840 /// Creates a new suffixed floating-point literal. 841 /// 842 /// This constructor will create a literal like `1.0f64` where the value 843 /// specified is the preceding part of the token and `f64` is the suffix of 844 /// the token. This token will always be inferred to be an `f64` in the 845 /// compiler. 846 /// Literals created from negative numbers may not survive rountrips through 847 /// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal). 848 /// 849 /// # Panics 850 /// 851 /// This function requires that the specified float is finite, for 852 /// example if it is infinity or NaN this function will panic. f64_suffixed(n: f64) -> Literal853 pub fn f64_suffixed(n: f64) -> Literal { 854 if !n.is_finite() { 855 panic!("Invalid float literal {}", n); 856 } 857 Literal(bridge::client::Literal::f64(&n.to_string())) 858 } 859 860 /// String literal. string(string: &str) -> Literal861 pub fn string(string: &str) -> Literal { 862 Literal(bridge::client::Literal::string(string)) 863 } 864 865 /// Character literal. character(ch: char) -> Literal866 pub fn character(ch: char) -> Literal { 867 Literal(bridge::client::Literal::character(ch)) 868 } 869 870 /// Byte string literal. byte_string(bytes: &[u8]) -> Literal871 pub fn byte_string(bytes: &[u8]) -> Literal { 872 Literal(bridge::client::Literal::byte_string(bytes)) 873 } 874 875 /// Returns the span encompassing this literal. span(&self) -> Span876 pub fn span(&self) -> Span { 877 Span(self.0.span()) 878 } 879 880 /// Configures the span associated for this literal. set_span(&mut self, span: Span)881 pub fn set_span(&mut self, span: Span) { 882 self.0.set_span(span.0); 883 } 884 885 /// Returns a `Span` that is a subset of `self.span()` containing only the 886 /// source bytes in range `range`. Returns `None` if the would-be trimmed 887 /// span is outside the bounds of `self`. 888 // FIXME(SergioBenitez): check that the byte range starts and ends at a 889 // UTF-8 boundary of the source. otherwise, it's likely that a panic will 890 // occur elsewhere when the source text is printed. 891 // FIXME(SergioBenitez): there is no way for the user to know what 892 // `self.span()` actually maps to, so this method can currently only be 893 // called blindly. For example, `to_string()` for the character 'c' returns 894 // "'\u{63}'"; there is no way for the user to know whether the source text 895 // was 'c' or whether it was '\u{63}'. subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span>896 pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { 897 // HACK(eddyb) something akin to `Option::cloned`, but for `Bound<&T>`. 898 fn cloned_bound<T: Clone>(bound: Bound<&T>) -> Bound<T> { 899 match bound { 900 Bound::Included(x) => Bound::Included(x.clone()), 901 Bound::Excluded(x) => Bound::Excluded(x.clone()), 902 Bound::Unbounded => Bound::Unbounded, 903 } 904 } 905 906 self.0.subspan(cloned_bound(range.start_bound()), cloned_bound(range.end_bound())).map(Span) 907 } 908 } 909 910 // N.B., the bridge only provides `to_string`, implement `fmt::Display` 911 // based on it (the reverse of the usual relationship between the two). 912 // impl ToString for Literal { 913 // fn to_string(&self) -> String { 914 // TokenStream::from(TokenTree::from(self.clone())).to_string() 915 // } 916 // } 917 918 /// Prints the literal as a string that should be losslessly convertible 919 /// back into the same literal (except for possible rounding for floating point literals). 920 impl fmt::Display for Literal { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result921 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 922 f.write_str(&self.to_string()) 923 } 924 } 925 926 impl fmt::Debug for Literal { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result927 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 928 // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. 929 self.0.fmt(f) 930 } 931 } 932 933 impl FromStr for Literal { 934 type Err = LexError; 935 from_str(src: &str) -> Result<Self, LexError>936 fn from_str(src: &str) -> Result<Self, LexError> { 937 match bridge::client::Literal::from_str(src) { 938 Ok(literal) => Ok(Literal(literal)), 939 Err(()) => Err(LexError::new()), 940 } 941 } 942 } 943 944 pub mod tracked_env { 945 use std::env::{self, VarError}; 946 use std::ffi::OsStr; 947 948 /// Retrieve an environment variable and add it to build dependency info. 949 /// Build system executing the compiler will know that the variable was accessed during 950 /// compilation, and will be able to rerun the build when the value of that variable changes. 951 /// Besides the dependency tracking this function should be equivalent to `env::var` from the 952 /// standard library, except that the argument must be UTF-8. var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError>953 pub fn var<K: AsRef<OsStr> + AsRef<str>>(key: K) -> Result<String, VarError> { 954 use std::ops::Deref; 955 956 let key: &str = key.as_ref(); 957 let value = env::var(key); 958 super::bridge::client::FreeFunctions::track_env_var( 959 key, 960 value.as_ref().map(|t| t.deref()).ok(), 961 ); 962 value 963 } 964 } 965