mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Print token::Interpolated
with token stream pretty printing.
Instead of using AST pretty printing. This is a step towards removing `token::Interpolated`, which will eventually (in #124141) be replaced with a token stream within invisible delimiters. This changes (improves) the output of the `stringify!` macro in some cases. This is allowed. As the `stringify!` docs say: "Note that the expanded results of the input tokens may change in the future. You should be careful if you rely on the output." Test changes: - tests/ui/macros/stringify.rs: this used to test both token stream pretty printing and AST pretty printing via different ways of invoking of `stringify!` (i.e. `$expr` vs `$tt`). But those two different invocations now give the same result, which is a nice consistency improvement. This removes the need for all the `c2*` macros. The AST pretty printer now has more thorough testing thanks to #125236. - tests/ui/proc-macro/*: minor improvements where small differences between `INPUT (DISPLAY)` output and `DEEP-RE-COLLECTED (DISPLAY)` output disappear.
This commit is contained in:
parent
a330e49593
commit
f7d49fdf4f
@ -870,18 +870,11 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
|
fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
|
||||||
match nt {
|
// We extract the token stream from the AST fragment and pretty print
|
||||||
token::NtExpr(e) => self.expr_to_string(e),
|
// it, rather than using AST pretty printing, because `Nonterminal` is
|
||||||
token::NtMeta(e) => self.attr_item_to_string(e),
|
// slated for removal in #124141. (This method will also then be
|
||||||
token::NtTy(e) => self.ty_to_string(e),
|
// removed.)
|
||||||
token::NtPath(e) => self.path_to_string(e),
|
self.tts_to_string(&TokenStream::from_nonterminal_ast(nt))
|
||||||
token::NtItem(e) => self.item_to_string(e),
|
|
||||||
token::NtBlock(e) => self.block_to_string(e),
|
|
||||||
token::NtStmt(e) => self.stmt_to_string(e),
|
|
||||||
token::NtPat(e) => self.pat_to_string(e),
|
|
||||||
token::NtLiteral(e) => self.expr_to_string(e),
|
|
||||||
token::NtVis(e) => self.vis_to_string(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
|
/// Print the token kind precisely, without converting `$crate` into its respective crate name.
|
||||||
@ -1015,6 +1008,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||||||
Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
|
Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tts_to_string(&self, tokens: &TokenStream) -> String {
|
||||||
|
Self::to_string(|s| s.print_tts(tokens, false))
|
||||||
|
}
|
||||||
|
|
||||||
fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
||||||
let mut printer = State::new();
|
let mut printer = State::new();
|
||||||
f(&mut printer);
|
f(&mut printer);
|
||||||
@ -2060,10 +2057,6 @@ impl<'a> State<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String {
|
|
||||||
Self::to_string(|s| s.print_tts(tokens, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
|
pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
|
||||||
Self::to_string(|s| s.print_path_segment(p, false))
|
Self::to_string(|s| s.print_path_segment(p, false))
|
||||||
}
|
}
|
||||||
|
@ -37,25 +37,22 @@ macro_rules! vis { ($vis:vis) => { stringify!($vis) }; }
|
|||||||
// the same result (which is preferable.)
|
// the same result (which is preferable.)
|
||||||
macro_rules! c1 {
|
macro_rules! c1 {
|
||||||
($frag:ident, [$($tt:tt)*], $s:literal) => {
|
($frag:ident, [$($tt:tt)*], $s:literal) => {
|
||||||
|
// Prior to #125174:
|
||||||
|
// - the first of these two lines created a `TokenKind::Interpolated`
|
||||||
|
// that was printed by the AST pretty printer;
|
||||||
|
// - the second of these two lines created a token stream that was
|
||||||
|
// printed by the TokenStream pretty printer.
|
||||||
|
//
|
||||||
|
// Now they are both printed by the TokenStream pretty printer. But it
|
||||||
|
// doesn't hurt to keep both assertions to ensure this remains true.
|
||||||
|
//
|
||||||
|
// (This also explains the name `c1`. There used to be a `c2` macro for
|
||||||
|
// cases where the two pretty printers produced different output.)
|
||||||
assert_eq!($frag!($($tt)*), $s);
|
assert_eq!($frag!($($tt)*), $s);
|
||||||
assert_eq!(stringify!($($tt)*), $s);
|
assert_eq!(stringify!($($tt)*), $s);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use this when AST pretty-printing and TokenStream pretty-printing give
|
|
||||||
// different results.
|
|
||||||
//
|
|
||||||
// `c1` and `c2` could be in a single macro, but having them separate makes it
|
|
||||||
// easy to find the cases where the two pretty-printing approaches give
|
|
||||||
// different results.
|
|
||||||
macro_rules! c2 {
|
|
||||||
($frag:ident, [$($tt:tt)*], $s1:literal, $s2:literal $(,)?) => {
|
|
||||||
assert_ne!($s1, $s2, "should use `c1!` instead");
|
|
||||||
assert_eq!($frag!($($tt)*), $s1);
|
|
||||||
assert_eq!(stringify!($($tt)*), $s2);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_block() {
|
fn test_block() {
|
||||||
c1!(block, [ {} ], "{}");
|
c1!(block, [ {} ], "{}");
|
||||||
@ -76,7 +73,7 @@ fn test_expr() {
|
|||||||
// ExprKind::Array
|
// ExprKind::Array
|
||||||
c1!(expr, [ [] ], "[]");
|
c1!(expr, [ [] ], "[]");
|
||||||
c1!(expr, [ [true] ], "[true]");
|
c1!(expr, [ [true] ], "[true]");
|
||||||
c2!(expr, [ [true,] ], "[true]", "[true,]");
|
c1!(expr, [ [true,] ], "[true,]");
|
||||||
c1!(expr, [ [true, true] ], "[true, true]");
|
c1!(expr, [ [true, true] ], "[true, true]");
|
||||||
|
|
||||||
// ExprKind::ConstBlock
|
// ExprKind::ConstBlock
|
||||||
@ -85,11 +82,11 @@ fn test_expr() {
|
|||||||
// ExprKind::Call
|
// ExprKind::Call
|
||||||
c1!(expr, [ f() ], "f()");
|
c1!(expr, [ f() ], "f()");
|
||||||
c1!(expr, [ f::<u8>() ], "f::<u8>()");
|
c1!(expr, [ f::<u8>() ], "f::<u8>()");
|
||||||
c2!(expr, [ f :: < u8>( ) ], "f::<u8>()", "f :: < u8>()");
|
c1!(expr, [ f :: < u8>( ) ], "f :: < u8>()");
|
||||||
c1!(expr, [ f::<1>() ], "f::<1>()");
|
c1!(expr, [ f::<1>() ], "f::<1>()");
|
||||||
c1!(expr, [ f::<'a, u8, 1>() ], "f::<'a, u8, 1>()");
|
c1!(expr, [ f::<'a, u8, 1>() ], "f::<'a, u8, 1>()");
|
||||||
c1!(expr, [ f(true) ], "f(true)");
|
c1!(expr, [ f(true) ], "f(true)");
|
||||||
c2!(expr, [ f(true,) ], "f(true)", "f(true,)");
|
c1!(expr, [ f(true,) ], "f(true,)");
|
||||||
c1!(expr, [ ()() ], "()()");
|
c1!(expr, [ ()() ], "()()");
|
||||||
|
|
||||||
// ExprKind::MethodCall
|
// ExprKind::MethodCall
|
||||||
@ -101,7 +98,7 @@ fn test_expr() {
|
|||||||
c1!(expr, [ () ], "()");
|
c1!(expr, [ () ], "()");
|
||||||
c1!(expr, [ (true,) ], "(true,)");
|
c1!(expr, [ (true,) ], "(true,)");
|
||||||
c1!(expr, [ (true, false) ], "(true, false)");
|
c1!(expr, [ (true, false) ], "(true, false)");
|
||||||
c2!(expr, [ (true, false,) ], "(true, false)", "(true, false,)");
|
c1!(expr, [ (true, false,) ], "(true, false,)");
|
||||||
|
|
||||||
// ExprKind::Binary
|
// ExprKind::Binary
|
||||||
c1!(expr, [ true || false ], "true || false");
|
c1!(expr, [ true || false ], "true || false");
|
||||||
@ -131,16 +128,6 @@ fn test_expr() {
|
|||||||
c1!(expr, [ if let Some(a) = b { c } else { d } ], "if let Some(a) = b { c } else { d }");
|
c1!(expr, [ if let Some(a) = b { c } else { d } ], "if let Some(a) = b { c } else { d }");
|
||||||
c1!(expr, [ if let _ = true && false {} ], "if let _ = true && false {}");
|
c1!(expr, [ if let _ = true && false {} ], "if let _ = true && false {}");
|
||||||
c1!(expr, [ if let _ = (true && false) {} ], "if let _ = (true && false) {}");
|
c1!(expr, [ if let _ = (true && false) {} ], "if let _ = (true && false) {}");
|
||||||
macro_rules! c2_if_let {
|
|
||||||
($expr:expr, $expr_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2!(expr, [ if let _ = $expr {} ], $expr_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
c2_if_let!(
|
|
||||||
true && false,
|
|
||||||
"if let _ = (true && false) {}",
|
|
||||||
"if let _ = true && false {}",
|
|
||||||
);
|
|
||||||
c1!(expr,
|
c1!(expr,
|
||||||
[ match () { _ if let _ = Struct {} => {} } ],
|
[ match () { _ if let _ = Struct {} => {} } ],
|
||||||
"match () { _ if let _ = Struct {} => {} }"
|
"match () { _ if let _ = Struct {} => {} }"
|
||||||
@ -203,31 +190,6 @@ fn test_expr() {
|
|||||||
} ],
|
} ],
|
||||||
"match self { Ok => 1, Err => 0, }"
|
"match self { Ok => 1, Err => 0, }"
|
||||||
);
|
);
|
||||||
macro_rules! c2_match_arm {
|
|
||||||
([ $expr:expr ], $expr_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2!(expr, [ match () { _ => $expr } ], $expr_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
c2_match_arm!(
|
|
||||||
[ { 1 } - 1 ],
|
|
||||||
"match () { _ => ({ 1 }) - 1, }",
|
|
||||||
"match () { _ => { 1 } - 1 }",
|
|
||||||
);
|
|
||||||
c2_match_arm!(
|
|
||||||
[ m!() - 1 ],
|
|
||||||
"match () { _ => m!() - 1, }",
|
|
||||||
"match () { _ => m!() - 1 }",
|
|
||||||
);
|
|
||||||
c2_match_arm!(
|
|
||||||
[ m![] - 1 ],
|
|
||||||
"match () { _ => m![] - 1, }",
|
|
||||||
"match () { _ => m![] - 1 }",
|
|
||||||
);
|
|
||||||
c2_match_arm!(
|
|
||||||
[ m! {} - 1 ],
|
|
||||||
"match () { _ => m! {} - 1, }",
|
|
||||||
"match () { _ => m! {} - 1 }",
|
|
||||||
);
|
|
||||||
|
|
||||||
// ExprKind::Closure
|
// ExprKind::Closure
|
||||||
c1!(expr, [ || {} ], "|| {}");
|
c1!(expr, [ || {} ], "|| {}");
|
||||||
@ -242,22 +204,19 @@ fn test_expr() {
|
|||||||
c1!(expr, [ static async || self ], "static async || self");
|
c1!(expr, [ static async || self ], "static async || self");
|
||||||
c1!(expr, [ static async move || self ], "static async move || self");
|
c1!(expr, [ static async move || self ], "static async move || self");
|
||||||
c1!(expr, [ || -> u8 { self } ], "|| -> u8 { self }");
|
c1!(expr, [ || -> u8 { self } ], "|| -> u8 { self }");
|
||||||
c2!(expr, [ 1 + || {} ], "1 + (|| {})", "1 + || {}"); // AST??
|
c1!(expr, [ 1 + || {} ], "1 + || {}");
|
||||||
|
|
||||||
// ExprKind::Block
|
// ExprKind::Block
|
||||||
c1!(expr, [ {} ], "{}");
|
c1!(expr, [ {} ], "{}");
|
||||||
c1!(expr, [ unsafe {} ], "unsafe {}");
|
c1!(expr, [ unsafe {} ], "unsafe {}");
|
||||||
c1!(expr, [ 'a: {} ], "'a: {}");
|
c1!(expr, [ 'a: {} ], "'a: {}");
|
||||||
c1!(expr, [ #[attr] {} ], "#[attr] {}");
|
c1!(expr, [ #[attr] {} ], "#[attr] {}");
|
||||||
c2!(expr,
|
c1!(expr,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
#![attr]
|
#![attr]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"{\n\
|
|
||||||
\x20 #![attr]\n\
|
|
||||||
}",
|
|
||||||
"{ #![attr] }"
|
"{ #![attr] }"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -289,7 +248,7 @@ fn test_expr() {
|
|||||||
c1!(expr, [ ..hi ], "..hi");
|
c1!(expr, [ ..hi ], "..hi");
|
||||||
c1!(expr, [ lo.. ], "lo..");
|
c1!(expr, [ lo.. ], "lo..");
|
||||||
c1!(expr, [ lo..hi ], "lo..hi");
|
c1!(expr, [ lo..hi ], "lo..hi");
|
||||||
c2!(expr, [ lo .. hi ], "lo..hi", "lo .. hi");
|
c1!(expr, [ lo .. hi ], "lo .. hi");
|
||||||
c1!(expr, [ ..=hi ], "..=hi");
|
c1!(expr, [ ..=hi ], "..=hi");
|
||||||
c1!(expr, [ lo..=hi ], "lo..=hi");
|
c1!(expr, [ lo..=hi ], "lo..=hi");
|
||||||
c1!(expr, [ -2..=-1 ], "-2..=-1");
|
c1!(expr, [ -2..=-1 ], "-2..=-1");
|
||||||
@ -382,11 +341,7 @@ fn test_item() {
|
|||||||
c1!(item, [ pub extern crate self as std; ], "pub extern crate self as std;");
|
c1!(item, [ pub extern crate self as std; ], "pub extern crate self as std;");
|
||||||
|
|
||||||
// ItemKind::Use
|
// ItemKind::Use
|
||||||
c2!(item,
|
c1!(item, [ pub use crate::{a, b::c}; ], "pub use crate::{ a, b::c };"); // FIXME
|
||||||
[ pub use crate::{a, b::c}; ],
|
|
||||||
"pub use crate::{a, b::c};",
|
|
||||||
"pub use crate::{ a, b::c };" // FIXME
|
|
||||||
);
|
|
||||||
c1!(item, [ pub use A::*; ], "pub use A::*;");
|
c1!(item, [ pub use A::*; ], "pub use A::*;");
|
||||||
|
|
||||||
// ItemKind::Static
|
// ItemKind::Static
|
||||||
@ -418,24 +373,19 @@ fn test_item() {
|
|||||||
|
|
||||||
// ItemKind::ForeignMod
|
// ItemKind::ForeignMod
|
||||||
c1!(item, [ extern "C" {} ], "extern \"C\" {}");
|
c1!(item, [ extern "C" {} ], "extern \"C\" {}");
|
||||||
c2!(item,
|
c1!(item, [ pub extern "C" {} ], "pub extern \"C\" {}");
|
||||||
[ pub extern "C" {} ],
|
|
||||||
"extern \"C\" {}", // ??
|
|
||||||
"pub extern \"C\" {}"
|
|
||||||
);
|
|
||||||
c1!(item, [ unsafe extern "C++" {} ], "unsafe extern \"C++\" {}");
|
c1!(item, [ unsafe extern "C++" {} ], "unsafe extern \"C++\" {}");
|
||||||
|
|
||||||
// ItemKind::GlobalAsm: untestable because this test works pre-expansion.
|
// ItemKind::GlobalAsm: untestable because this test works pre-expansion.
|
||||||
|
|
||||||
// ItemKind::TyAlias
|
// ItemKind::TyAlias
|
||||||
c2!(item,
|
c1!(item,
|
||||||
[
|
[
|
||||||
pub default type Type<'a>: Bound
|
pub default type Type<'a>: Bound
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
= T;
|
= T;
|
||||||
],
|
],
|
||||||
"pub default type Type<'a>: Bound where Self: 'a = T;",
|
|
||||||
"pub default type Type<'a>: Bound where Self: 'a, = T;"
|
"pub default type Type<'a>: Bound where Self: 'a, = T;"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -451,7 +401,7 @@ fn test_item() {
|
|||||||
],
|
],
|
||||||
"enum Empty { Unit, Tuple(), Struct {}, }"
|
"enum Empty { Unit, Tuple(), Struct {}, }"
|
||||||
);
|
);
|
||||||
c2!(item,
|
c1!(item,
|
||||||
[
|
[
|
||||||
enum Enum<T>
|
enum Enum<T>
|
||||||
where
|
where
|
||||||
@ -462,13 +412,6 @@ fn test_item() {
|
|||||||
Struct { t: T },
|
Struct { t: T },
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"enum Enum<T> where T: 'a {\n\
|
|
||||||
\x20 Unit,\n\
|
|
||||||
\x20 Tuple(T),\n\
|
|
||||||
\x20 Struct {\n\
|
|
||||||
\x20 t: T,\n\
|
|
||||||
\x20 },\n\
|
|
||||||
}",
|
|
||||||
"enum Enum<T> where T: 'a, { Unit, Tuple(T), Struct { t: T }, }"
|
"enum Enum<T> where T: 'a, { Unit, Tuple(T), Struct { t: T }, }"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -477,7 +420,7 @@ fn test_item() {
|
|||||||
c1!(item, [ struct Tuple(); ], "struct Tuple();");
|
c1!(item, [ struct Tuple(); ], "struct Tuple();");
|
||||||
c1!(item, [ struct Tuple(T); ], "struct Tuple(T);");
|
c1!(item, [ struct Tuple(T); ], "struct Tuple(T);");
|
||||||
c1!(item, [ struct Struct {} ], "struct Struct {}");
|
c1!(item, [ struct Struct {} ], "struct Struct {}");
|
||||||
c2!(item,
|
c1!(item,
|
||||||
[
|
[
|
||||||
struct Struct<T>
|
struct Struct<T>
|
||||||
where
|
where
|
||||||
@ -486,29 +429,23 @@ fn test_item() {
|
|||||||
t: T,
|
t: T,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"struct Struct<T> where T: 'a {\n\
|
|
||||||
\x20 t: T,\n\
|
|
||||||
}",
|
|
||||||
"struct Struct<T> where T: 'a, { t: T, }"
|
"struct Struct<T> where T: 'a, { t: T, }"
|
||||||
);
|
);
|
||||||
|
|
||||||
// ItemKind::Union
|
// ItemKind::Union
|
||||||
c1!(item, [ pub union Union {} ], "pub union Union {}");
|
c1!(item, [ pub union Union {} ], "pub union Union {}");
|
||||||
c2!(item,
|
c1!(item,
|
||||||
[
|
[
|
||||||
union Union<T> where T: 'a {
|
union Union<T> where T: 'a {
|
||||||
t: T,
|
t: T,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"union Union<T> where T: 'a {\n\
|
|
||||||
\x20 t: T,\n\
|
|
||||||
}",
|
|
||||||
"union Union<T> where T: 'a { t: T, }"
|
"union Union<T> where T: 'a { t: T, }"
|
||||||
);
|
);
|
||||||
|
|
||||||
// ItemKind::Trait
|
// ItemKind::Trait
|
||||||
c1!(item, [ pub unsafe auto trait Send {} ], "pub unsafe auto trait Send {}");
|
c1!(item, [ pub unsafe auto trait Send {} ], "pub unsafe auto trait Send {}");
|
||||||
c2!(item,
|
c1!(item,
|
||||||
[
|
[
|
||||||
trait Trait<'a>: Sized
|
trait Trait<'a>: Sized
|
||||||
where
|
where
|
||||||
@ -516,7 +453,6 @@ fn test_item() {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"trait Trait<'a>: Sized where Self: 'a {}",
|
|
||||||
"trait Trait<'a>: Sized where Self: 'a, {}"
|
"trait Trait<'a>: Sized where Self: 'a, {}"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -547,11 +483,7 @@ fn test_item() {
|
|||||||
],
|
],
|
||||||
"macro_rules! stringify { () => {}; }"
|
"macro_rules! stringify { () => {}; }"
|
||||||
);
|
);
|
||||||
c2!(item,
|
c1!(item, [ pub macro stringify() {} ], "pub macro stringify() {}");
|
||||||
[ pub macro stringify() {} ],
|
|
||||||
"pub macro stringify { () => {} }", // ??
|
|
||||||
"pub macro stringify() {}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -577,7 +509,7 @@ fn test_pat() {
|
|||||||
// PatKind::Struct
|
// PatKind::Struct
|
||||||
c1!(pat, [ Struct {} ], "Struct {}");
|
c1!(pat, [ Struct {} ], "Struct {}");
|
||||||
c1!(pat, [ Struct::<u8> {} ], "Struct::<u8> {}");
|
c1!(pat, [ Struct::<u8> {} ], "Struct::<u8> {}");
|
||||||
c2!(pat, [ Struct ::< u8 > {} ], "Struct::<u8> {}", "Struct ::< u8 > {}");
|
c1!(pat, [ Struct ::< u8 > {} ], "Struct ::< u8 > {}");
|
||||||
c1!(pat, [ Struct::<'static> {} ], "Struct::<'static> {}");
|
c1!(pat, [ Struct::<'static> {} ], "Struct::<'static> {}");
|
||||||
c1!(pat, [ Struct { x } ], "Struct { x }");
|
c1!(pat, [ Struct { x } ], "Struct { x }");
|
||||||
c1!(pat, [ Struct { x: _x } ], "Struct { x: _x }");
|
c1!(pat, [ Struct { x: _x } ], "Struct { x: _x }");
|
||||||
@ -597,8 +529,8 @@ fn test_pat() {
|
|||||||
|
|
||||||
// PatKind::Or
|
// PatKind::Or
|
||||||
c1!(pat, [ true | false ], "true | false");
|
c1!(pat, [ true | false ], "true | false");
|
||||||
c2!(pat, [ | true ], "true", "| true");
|
c1!(pat, [ | true ], "| true");
|
||||||
c2!(pat, [ |true| false ], "true | false", "|true| false");
|
c1!(pat, [ |true| false ], "|true| false");
|
||||||
|
|
||||||
// PatKind::Path
|
// PatKind::Path
|
||||||
c1!(pat, [ crate::Path ], "crate::Path");
|
c1!(pat, [ crate::Path ], "crate::Path");
|
||||||
@ -631,7 +563,7 @@ fn test_pat() {
|
|||||||
// PatKind::Slice
|
// PatKind::Slice
|
||||||
c1!(pat, [ [] ], "[]");
|
c1!(pat, [ [] ], "[]");
|
||||||
c1!(pat, [ [true] ], "[true]");
|
c1!(pat, [ [true] ], "[true]");
|
||||||
c2!(pat, [ [true,] ], "[true]", "[true,]");
|
c1!(pat, [ [true,] ], "[true,]");
|
||||||
c1!(pat, [ [true, false] ], "[true, false]");
|
c1!(pat, [ [true, false] ], "[true, false]");
|
||||||
|
|
||||||
// PatKind::Rest
|
// PatKind::Rest
|
||||||
@ -658,7 +590,7 @@ fn test_path() {
|
|||||||
c1!(path, [ crate::thing ], "crate::thing");
|
c1!(path, [ crate::thing ], "crate::thing");
|
||||||
c1!(path, [ Self::thing ], "Self::thing");
|
c1!(path, [ Self::thing ], "Self::thing");
|
||||||
c1!(path, [ Self<'static> ], "Self<'static>");
|
c1!(path, [ Self<'static> ], "Self<'static>");
|
||||||
c2!(path, [ Self::<'static> ], "Self<'static>", "Self::<'static>");
|
c1!(path, [ Self::<'static> ], "Self::<'static>");
|
||||||
c1!(path, [ Self() ], "Self()");
|
c1!(path, [ Self() ], "Self()");
|
||||||
c1!(path, [ Self() -> () ], "Self() -> ()");
|
c1!(path, [ Self() -> () ], "Self() -> ()");
|
||||||
}
|
}
|
||||||
@ -666,40 +598,12 @@ fn test_path() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_stmt() {
|
fn test_stmt() {
|
||||||
// StmtKind::Local
|
// StmtKind::Local
|
||||||
c2!(stmt, [ let _ ], "let _;", "let _");
|
c1!(stmt, [ let _ ], "let _");
|
||||||
c2!(stmt, [ let x = true ], "let x = true;", "let x = true");
|
c1!(stmt, [ let x = true ], "let x = true");
|
||||||
c2!(stmt, [ let x: bool = true ], "let x: bool = true;", "let x: bool = true");
|
c1!(stmt, [ let x: bool = true ], "let x: bool = true");
|
||||||
c2!(stmt, [ let (a, b) = (1, 2) ], "let (a, b) = (1, 2);", "let (a, b) = (1, 2)");
|
c1!(stmt, [ let (a, b) = (1, 2) ], "let (a, b) = (1, 2)");
|
||||||
c2!(stmt,
|
c1!(stmt, [ let (a, b): (u32, u32) = (1, 2) ], "let (a, b): (u32, u32) = (1, 2)");
|
||||||
[ let (a, b): (u32, u32) = (1, 2) ],
|
c1!(stmt, [ let _ = f() else { return; } ], "let _ = f() else { return; }");
|
||||||
"let (a, b): (u32, u32) = (1, 2);",
|
|
||||||
"let (a, b): (u32, u32) = (1, 2)"
|
|
||||||
);
|
|
||||||
c2!(stmt,
|
|
||||||
[ let _ = f() else { return; } ],
|
|
||||||
"let _ = f() else { return; };",
|
|
||||||
"let _ = f() else { return; }",
|
|
||||||
);
|
|
||||||
macro_rules! c2_let_expr_minus_one {
|
|
||||||
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2!(stmt, [ let _ = $expr - 1 ], $stmt_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
c2_let_expr_minus_one!(
|
|
||||||
[ match void {} ],
|
|
||||||
"let _ = match void {} - 1;",
|
|
||||||
"let _ = match void {} - 1",
|
|
||||||
);
|
|
||||||
macro_rules! c2_let_expr_else_return {
|
|
||||||
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2!(stmt, [ let _ = $expr else { return; } ], $stmt_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
c2_let_expr_else_return!(
|
|
||||||
[ f() ],
|
|
||||||
"let _ = f() else { return; };",
|
|
||||||
"let _ = f() else { return; }",
|
|
||||||
);
|
|
||||||
|
|
||||||
// StmtKind::Item
|
// StmtKind::Item
|
||||||
c1!(stmt, [ struct S; ], "struct S;");
|
c1!(stmt, [ struct S; ], "struct S;");
|
||||||
@ -709,62 +613,7 @@ fn test_stmt() {
|
|||||||
c1!(stmt, [ loop {} ], "loop {}");
|
c1!(stmt, [ loop {} ], "loop {}");
|
||||||
|
|
||||||
// StmtKind::Semi
|
// StmtKind::Semi
|
||||||
c2!(stmt, [ 1 + 1 ], "1 + 1;", "1 + 1");
|
c1!(stmt, [ 1 + 1 ], "1 + 1");
|
||||||
macro_rules! c2_expr_as_stmt {
|
|
||||||
// Parse as expr, then reparse as stmt.
|
|
||||||
//
|
|
||||||
// The c2_minus_one macro below can't directly call `c2!(stmt, ...)`
|
|
||||||
// because `$expr - 1` cannot be parsed directly as a stmt. A statement
|
|
||||||
// boundary occurs after the `match void {}`, after which the `-` token
|
|
||||||
// hits "no rules expected this token in macro call".
|
|
||||||
//
|
|
||||||
// The unwanted statement boundary is exactly why the pretty-printer is
|
|
||||||
// injecting parentheses around the subexpression, which is the behavior
|
|
||||||
// we are interested in testing.
|
|
||||||
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2!(stmt, [ $expr ], $stmt_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
macro_rules! c2_minus_one {
|
|
||||||
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
|
|
||||||
c2_expr_as_stmt!([ $expr - 1 ], $stmt_expected, $tokens_expected);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
c2_minus_one!(
|
|
||||||
[ match void {} ],
|
|
||||||
"(match void {}) - 1;",
|
|
||||||
"match void {} - 1",
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ match void {}() ],
|
|
||||||
"(match void {})() - 1;",
|
|
||||||
"match void {}() - 1",
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ match void {}[0] ],
|
|
||||||
"(match void {})[0] - 1;",
|
|
||||||
"match void {}[0] - 1",
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ loop { break 1; } ],
|
|
||||||
"(loop { break 1; }) - 1;",
|
|
||||||
"loop { break 1; } - 1",
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ m!() ],
|
|
||||||
"m!() - 1;",
|
|
||||||
"m!() - 1"
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ m![] ],
|
|
||||||
"m![] - 1;",
|
|
||||||
"m![] - 1"
|
|
||||||
);
|
|
||||||
c2_minus_one!(
|
|
||||||
[ m! {} ],
|
|
||||||
"(m! {}) - 1;",
|
|
||||||
"m! {} - 1"
|
|
||||||
);
|
|
||||||
|
|
||||||
// StmtKind::Empty
|
// StmtKind::Empty
|
||||||
c1!(stmt, [ ; ], ";");
|
c1!(stmt, [ ; ], ";");
|
||||||
@ -793,14 +642,14 @@ fn test_ty() {
|
|||||||
c1!(ty, [ &'a T ], "&'a T");
|
c1!(ty, [ &'a T ], "&'a T");
|
||||||
c1!(ty, [ &'a mut [T] ], "&'a mut [T]");
|
c1!(ty, [ &'a mut [T] ], "&'a mut [T]");
|
||||||
c1!(ty, [ &A<B<C<D<E>>>> ], "&A<B<C<D<E>>>>");
|
c1!(ty, [ &A<B<C<D<E>>>> ], "&A<B<C<D<E>>>>");
|
||||||
c2!(ty, [ &A<B<C<D<E> > > > ], "&A<B<C<D<E>>>>", "&A<B<C<D<E> > > >");
|
c1!(ty, [ &A<B<C<D<E> > > > ], "&A<B<C<D<E> > > >");
|
||||||
|
|
||||||
// TyKind::BareFn
|
// TyKind::BareFn
|
||||||
c1!(ty, [ fn() ], "fn()");
|
c1!(ty, [ fn() ], "fn()");
|
||||||
c1!(ty, [ fn() -> () ], "fn() -> ()");
|
c1!(ty, [ fn() -> () ], "fn() -> ()");
|
||||||
c1!(ty, [ fn(u8) ], "fn(u8)");
|
c1!(ty, [ fn(u8) ], "fn(u8)");
|
||||||
c1!(ty, [ fn(x: u8) ], "fn(x: u8)");
|
c1!(ty, [ fn(x: u8) ], "fn(x: u8)");
|
||||||
c2!(ty, [ for<> fn() ], "fn()", "for<> fn()");
|
c1!(ty, [ for<> fn() ], "for<> fn()");
|
||||||
c1!(ty, [ for<'a> fn() ], "for<'a> fn()");
|
c1!(ty, [ for<'a> fn() ], "for<'a> fn()");
|
||||||
|
|
||||||
// TyKind::Never
|
// TyKind::Never
|
||||||
@ -819,7 +668,7 @@ fn test_ty() {
|
|||||||
c1!(ty, [ T ], "T");
|
c1!(ty, [ T ], "T");
|
||||||
c1!(ty, [ Ref<'a> ], "Ref<'a>");
|
c1!(ty, [ Ref<'a> ], "Ref<'a>");
|
||||||
c1!(ty, [ PhantomData<T> ], "PhantomData<T>");
|
c1!(ty, [ PhantomData<T> ], "PhantomData<T>");
|
||||||
c2!(ty, [ PhantomData::<T> ], "PhantomData<T>", "PhantomData::<T>");
|
c1!(ty, [ PhantomData::<T> ], "PhantomData::<T>");
|
||||||
c1!(ty, [ Fn() -> ! ], "Fn() -> !");
|
c1!(ty, [ Fn() -> ! ], "Fn() -> !");
|
||||||
c1!(ty, [ Fn(u8) -> ! ], "Fn(u8) -> !");
|
c1!(ty, [ Fn(u8) -> ! ], "Fn(u8) -> !");
|
||||||
c1!(ty, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type");
|
c1!(ty, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type");
|
||||||
@ -864,23 +713,19 @@ fn test_ty() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_vis() {
|
fn test_vis() {
|
||||||
// VisibilityKind::Public
|
// VisibilityKind::Public
|
||||||
c2!(vis, [ pub ], "pub ", "pub");
|
c1!(vis, [ pub ], "pub");
|
||||||
|
|
||||||
// VisibilityKind::Restricted
|
// VisibilityKind::Restricted
|
||||||
c2!(vis, [ pub(crate) ], "pub(crate) ", "pub(crate)");
|
c1!(vis, [ pub(crate) ], "pub(crate)");
|
||||||
c2!(vis, [ pub(self) ], "pub(self) ", "pub(self)");
|
c1!(vis, [ pub(self) ], "pub(self)");
|
||||||
c2!(vis, [ pub(super) ], "pub(super) ", "pub(super)");
|
c1!(vis, [ pub(super) ], "pub(super)");
|
||||||
c2!(vis, [ pub(in crate) ], "pub(in crate) ", "pub(in crate)");
|
c1!(vis, [ pub(in crate) ], "pub(in crate)");
|
||||||
c2!(vis, [ pub(in self) ], "pub(in self) ", "pub(in self)");
|
c1!(vis, [ pub(in self) ], "pub(in self)");
|
||||||
c2!(vis, [ pub(in super) ], "pub(in super) ", "pub(in super)");
|
c1!(vis, [ pub(in super) ], "pub(in super)");
|
||||||
c2!(vis, [ pub(in path::to) ], "pub(in path::to) ", "pub(in path::to)");
|
c1!(vis, [ pub(in path::to) ], "pub(in path::to)");
|
||||||
c2!(vis, [ pub(in ::path::to) ], "pub(in ::path::to) ", "pub(in ::path::to)");
|
c1!(vis, [ pub(in ::path::to) ], "pub(in ::path::to)");
|
||||||
c2!(vis, [ pub(in self::path::to) ], "pub(in self::path::to) ", "pub(in self::path::to)");
|
c1!(vis, [ pub(in self::path::to) ], "pub(in self::path::to)");
|
||||||
c2!(vis,
|
c1!(vis, [ pub(in super::path::to) ], "pub(in super::path::to)");
|
||||||
[ pub(in super::path::to) ],
|
|
||||||
"pub(in super::path::to) ",
|
|
||||||
"pub(in super::path::to)"
|
|
||||||
);
|
|
||||||
|
|
||||||
// VisibilityKind::Inherited
|
// VisibilityKind::Inherited
|
||||||
// This one is different because directly calling `vis!` does not work.
|
// This one is different because directly calling `vis!` does not work.
|
||||||
|
@ -46,7 +46,7 @@ macro_rules! test {
|
|||||||
(let $p:pat = $e:expr) => {test!(($p,$e))};
|
(let $p:pat = $e:expr) => {test!(($p,$e))};
|
||||||
// this should be expr
|
// this should be expr
|
||||||
// vvv
|
// vvv
|
||||||
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1 + 1`
|
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1+1`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
|
@ -50,7 +50,7 @@ LL | my_recursive_macro!();
|
|||||||
= note: expanding `my_recursive_macro! { }`
|
= note: expanding `my_recursive_macro! { }`
|
||||||
= note: to `my_recursive_macro! ();`
|
= note: to `my_recursive_macro! ();`
|
||||||
|
|
||||||
error: expected expression, found pattern `A { a: a, b: 0, c: _, .. }`
|
error: expected expression, found pattern `A { a : a, b : 0, c : _, .. }`
|
||||||
--> $DIR/trace_faulty_macros.rs:16:9
|
--> $DIR/trace_faulty_macros.rs:16:9
|
||||||
|
|
|
|
||||||
LL | $a
|
LL | $a
|
||||||
@ -69,7 +69,7 @@ LL | #[derive(Debug)]
|
|||||||
LL | fn use_derive_macro_as_attr() {}
|
LL | fn use_derive_macro_as_attr() {}
|
||||||
| -------------------------------- not a `struct`, `enum` or `union`
|
| -------------------------------- not a `struct`, `enum` or `union`
|
||||||
|
|
||||||
error: expected expression, found pattern `1 + 1`
|
error: expected expression, found pattern `1+1`
|
||||||
--> $DIR/trace_faulty_macros.rs:49:37
|
--> $DIR/trace_faulty_macros.rs:49:37
|
||||||
|
|
|
|
||||||
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
|
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
|
||||||
@ -96,7 +96,7 @@ LL | let a = pat_macro!();
|
|||||||
= note: expanding `pat_macro! { }`
|
= note: expanding `pat_macro! { }`
|
||||||
= note: to `pat_macro! (A { a : a, b : 0, c : _, .. });`
|
= note: to `pat_macro! (A { a : a, b : 0, c : _, .. });`
|
||||||
= note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }`
|
= note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }`
|
||||||
= note: to `A { a: a, b: 0, c: _, .. }`
|
= note: to `A { a : a, b : 0, c : _, .. }`
|
||||||
|
|
||||||
note: trace_macro
|
note: trace_macro
|
||||||
--> $DIR/trace_faulty_macros.rs:53:5
|
--> $DIR/trace_faulty_macros.rs:53:5
|
||||||
@ -105,9 +105,9 @@ LL | test!(let x = 1+1);
|
|||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: expanding `test! { let x = 1+1 }`
|
= note: expanding `test! { let x = 1+1 }`
|
||||||
= note: to `test! ((x, 1 + 1))`
|
= note: to `test! ((x, 1+1))`
|
||||||
= note: expanding `test! { (x, 1 + 1) }`
|
= note: expanding `test! { (x, 1+1) }`
|
||||||
= note: to `let x = 1 + 1;`
|
= note: to `let x = 1+1;`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
@ -11,9 +11,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
|
|||||||
span: $DIR/capture-macro-rules-invoke.rs:21:21: 21:26 (#3),
|
span: $DIR/capture-macro-rules-invoke.rs:21:21: 21:26 (#3),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1;, String, my_name, 'a, my_val = 30,
|
PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
|
||||||
std::option::Option, pub(in some::path) , [a b c], -30
|
|
||||||
PRINT-BANG RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
|
|
||||||
std::option::Option, pub(in some::path), [a b c], -30
|
std::option::Option, pub(in some::path), [a b c], -30
|
||||||
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
|
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
|
||||||
std :: option :: Option, pub(in some :: path), [a b c], - 30
|
std :: option :: Option, pub(in some :: path), [a b c], - 30
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0; 0 }, }
|
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0; 0 }, }
|
||||||
PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0; 0 }, }
|
|
||||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "enum",
|
ident: "enum",
|
||||||
@ -122,8 +121,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
|||||||
span: #3 bytes(308..357),
|
span: #3 bytes(308..357),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; }; 0 }, }
|
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 }; 0 }, }
|
||||||
PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 }; 0 }, }
|
|
||||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "enum",
|
ident: "enum",
|
||||||
@ -280,8 +278,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
|||||||
span: #11 bytes(432..485),
|
span: #11 bytes(432..485),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; }; 0 }, }
|
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH }; 0 }, }
|
||||||
PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH }; 0 }, }
|
|
||||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "enum",
|
ident: "enum",
|
||||||
@ -358,8 +355,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
|||||||
span: #15 bytes(432..485),
|
span: #15 bytes(432..485),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; }; 0 }, }
|
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1 }; 0 }, }
|
||||||
PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 }; 0 }, }
|
|
||||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "enum",
|
ident: "enum",
|
||||||
@ -449,8 +445,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
|||||||
span: #19 bytes(432..485),
|
span: #19 bytes(432..485),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; }; 0 }, }
|
PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1 }; 0 }, }
|
||||||
PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 }; 0 }, }
|
|
||||||
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
PRINT-DERIVE INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
ident: "enum",
|
ident: "enum",
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
PRINT-BANG INPUT (DISPLAY): foo! { #[fake_attr] mod bar {
|
PRINT-BANG INPUT (DISPLAY): foo! { #[fake_attr] mod bar { #![doc = r" Foo"] } }
|
||||||
#![doc = r" Foo"]
|
|
||||||
} }
|
|
||||||
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo! { #[fake_attr] mod bar { #! [doc = r" Foo"] } }
|
PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): foo! { #[fake_attr] mod bar { #! [doc = r" Foo"] } }
|
||||||
PRINT-BANG INPUT (DEBUG): TokenStream [
|
PRINT-BANG INPUT (DEBUG): TokenStream [
|
||||||
Ident {
|
Ident {
|
||||||
|
Loading…
Reference in New Issue
Block a user