From e2ba9d1e0daaf7c0f8b1d2564ab7977dfaf3e582 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 23 Nov 2021 16:08:18 -0800 Subject: [PATCH 1/2] Add test for using $:literal to index a tuple Currently fails to build: error: unexpected token: `0` --> src/test/ui/macros/macro-interpolation.rs:19:16 | LL | $var . $field | ^^^^^^ ... LL | let _ = field!(tuple.0); | --------------- in this macro invocation | = note: this error originates in the macro `field` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro expansion ignores token `0` and any following --> src/test/ui/macros/macro-interpolation.rs:19:16 | LL | $var . $field | ^^^^^^ ... LL | let _ = field!(tuple.0); | --------------- caused by the macro expansion here | = note: the usage of `field!` is likely invalid in expression context error: aborting due to 2 previous errors --- src/test/ui/macros/macro-interpolation.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/ui/macros/macro-interpolation.rs b/src/test/ui/macros/macro-interpolation.rs index 35003a79ad703..d6cc682797647 100644 --- a/src/test/ui/macros/macro-interpolation.rs +++ b/src/test/ui/macros/macro-interpolation.rs @@ -24,10 +24,19 @@ macro_rules! qpath { }; } +macro_rules! field { + ($var:ident . $field:literal) => { + $var . $field + }; +} + pub fn main() { let _: qpath!(path, ::Owned); let _: qpath!(ty, ::Owned); + let tuple = ('x',); + let _ = field!(tuple.0); + assert!(overly_complicated!(f, x, Option, { return Some(x); }, Some(8), Some(y), y) == 8) } From aadf994c80c5abe963816ddea1bcca51edcaf803 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 23 Nov 2021 16:12:31 -0800 Subject: [PATCH 2/2] Uninterpolate literal to use as field index --- compiler/rustc_ast/src/token.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index db066d7c6a519..1ca7281619edc 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -452,8 +452,9 @@ impl Token { } // A convenience function for matching on identifiers during parsing. - // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token - // into the regular identifier or lifetime token it refers to, + // Turns interpolated identifier ($i:ident), lifetime ($l:lifetime), and + // integer literal ($l:literal) into the regular identifier or lifetime or + // literal token it refers to, // otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match &self.kind { @@ -462,6 +463,11 @@ impl Token { Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) } NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), + NtLiteral(ref literal) + if let ast::ExprKind::Lit(ast::Lit { token, kind: ast::LitKind::Int(..), .. }) = literal.kind => + { + Cow::Owned(Token::new(Literal(token), literal.span)) + } _ => Cow::Borrowed(self), }, _ => Cow::Borrowed(self),