提交 c825bc43 编写于 作者: B bors

Auto merge of #83312 - petrochenkov:noinner, r=Aaron1011

parser: Remove support for inner attributes on non-block expressions

Remove support for attributes like
```rust
fn attrs() {
    (#![print_target_and_args(fifth)] 1, 2);

    [#![print_target_and_args(sixth)] 1 , 2];
    [#![print_target_and_args(seventh)] true ; 5];

    match 0 {
        #![print_target_and_args(eighth)]
        _ => {}
    }

    MyStruct { #![print_target_and_args(ninth)] field: true };
}
```
They are
- useless
- unstable (modulo holes like https://github.com/rust-lang/rust/issues/65860)
- pessimize compiler performance, namely token collection for macros (cc https://github.com/rust-lang/rust/pull/82608)

I still want to run crater on this to check whether the stability holes are exploited in practice, and whether such attributes are used at all.
......@@ -366,10 +366,6 @@ fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
}
fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
}
fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) {
self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
}
......@@ -1675,32 +1671,24 @@ fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
}
}
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>], attrs: &[ast::Attribute]) {
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
self.ibox(INDENT_UNIT);
self.s.word("[");
self.print_inner_attributes_inline(attrs);
self.commasep_exprs(Inconsistent, exprs);
self.s.word("]");
self.end();
}
fn print_expr_anon_const(&mut self, expr: &ast::AnonConst, attrs: &[ast::Attribute]) {
fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) {
self.ibox(INDENT_UNIT);
self.s.word("const");
self.print_inner_attributes_inline(attrs);
self.print_expr(&expr.value);
self.end();
}
fn print_expr_repeat(
&mut self,
element: &ast::Expr,
count: &ast::AnonConst,
attrs: &[ast::Attribute],
) {
fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) {
self.ibox(INDENT_UNIT);
self.s.word("[");
self.print_inner_attributes_inline(attrs);
self.print_expr(element);
self.word_space(";");
self.print_expr(&count.value);
......@@ -1713,11 +1701,9 @@ fn print_expr_struct(
path: &ast::Path,
fields: &[ast::ExprField],
rest: &ast::StructRest,
attrs: &[ast::Attribute],
) {
self.print_path(path, true, 0);
self.s.word("{");
self.print_inner_attributes_inline(attrs);
self.commasep_cmnt(
Consistent,
fields,
......@@ -1752,9 +1738,8 @@ fn print_expr_struct(
self.s.word("}");
}
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>], attrs: &[ast::Attribute]) {
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) {
self.popen();
self.print_inner_attributes_inline(attrs);
self.commasep_exprs(Inconsistent, exprs);
if exprs.len() == 1 {
self.s.word(",");
......@@ -1865,19 +1850,19 @@ fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
}
ast::ExprKind::Array(ref exprs) => {
self.print_expr_vec(&exprs[..], attrs);
self.print_expr_vec(exprs);
}
ast::ExprKind::ConstBlock(ref anon_const) => {
self.print_expr_anon_const(anon_const, attrs);
self.print_expr_anon_const(anon_const);
}
ast::ExprKind::Repeat(ref element, ref count) => {
self.print_expr_repeat(element, count, attrs);
self.print_expr_repeat(element, count);
}
ast::ExprKind::Struct(ref se) => {
self.print_expr_struct(&se.path, &se.fields, &se.rest, attrs);
self.print_expr_struct(&se.path, &se.fields, &se.rest);
}
ast::ExprKind::Tup(ref exprs) => {
self.print_expr_tup(&exprs[..], attrs);
self.print_expr_tup(exprs);
}
ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args[..]);
......@@ -1955,7 +1940,6 @@ fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
self.print_expr_as_cond(expr);
self.s.space();
self.bopen();
self.print_inner_attributes_no_trailing_hardbreak(attrs);
for arm in arms {
self.print_arm(arm);
}
......@@ -2253,7 +2237,6 @@ enum AsmArg<'a> {
ast::ExprKind::MacCall(ref m) => self.print_mac(m),
ast::ExprKind::Paren(ref e) => {
self.popen();
self.print_inner_attributes_inline(attrs);
self.print_expr(e);
self.pclose();
}
......
......@@ -1216,10 +1216,9 @@ fn parse_lit_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
}
}
fn parse_tuple_parens_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
fn parse_tuple_parens_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.expect(&token::OpenDelim(token::Paren))?;
attrs.extend(self.parse_inner_attributes()?); // `(#![foo] a, b, ...)` is OK.
let (es, trailing_comma) = match self.parse_seq_to_end(
&token::CloseDelim(token::Paren),
SeqSep::trailing_allowed(token::Comma),
......@@ -1239,12 +1238,10 @@ fn parse_tuple_parens_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>
self.maybe_recover_from_bad_qpath(expr, true)
}
fn parse_array_or_repeat_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
fn parse_array_or_repeat_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
self.bump(); // `[`
attrs.extend(self.parse_inner_attributes()?);
let close = &token::CloseDelim(token::Bracket);
let kind = if self.eat(close) {
// Empty vector
......@@ -1950,7 +1947,7 @@ fn eat_label(&mut self) -> Option<Label> {
}
/// Parses a `match ... { ... }` expression (`match` token already eaten).
fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
fn parse_match_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let match_span = self.prev_token.span;
let lo = self.prev_token.span;
let scrutinee = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
......@@ -1965,7 +1962,6 @@ fn parse_match_expr(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
}
return Err(e);
}
attrs.extend(self.parse_inner_attributes()?);
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(token::Brace) {
......@@ -2293,15 +2289,13 @@ fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) {
pub(super) fn parse_struct_expr(
&mut self,
pth: ast::Path,
mut attrs: AttrVec,
attrs: AttrVec,
recover: bool,
) -> PResult<'a, P<Expr>> {
let mut fields = Vec::new();
let mut base = ast::StructRest::None;
let mut recover_async = false;
attrs.extend(self.parse_inner_attributes()?);
let mut async_block_err = |e: &mut DiagnosticBuilder<'_>, span: Span| {
recover_async = true;
e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
......
......@@ -5,15 +5,15 @@ fn main() { }
#[cfg(FALSE)]
fn syntax() {
let _ = #[attr] box 0;
let _ = #[attr] [#![attr] ];
let _ = #[attr] [#![attr] 0];
let _ = #[attr] [#![attr] 0; 0];
let _ = #[attr] [#![attr] 0, 0, 0];
let _ = #[attr] [];
let _ = #[attr] [0];
let _ = #[attr] [0; 0];
let _ = #[attr] [0, 0, 0];
let _ = #[attr] foo();
let _ = #[attr] x.foo();
let _ = #[attr] (#![attr] );
let _ = #[attr] (#![attr] #[attr] 0,);
let _ = #[attr] (#![attr] #[attr] 0, 0);
let _ = #[attr] ();
let _ = #[attr] (#[attr] 0,);
let _ = #[attr] (#[attr] 0, 0);
let _ = #[attr] 0 + #[attr] 0;
let _ = #[attr] 0 / #[attr] 0;
let _ = #[attr] 0 & #[attr] 0;
......@@ -43,10 +43,10 @@ fn syntax() {
#![attr]
};
let _ =
#[attr] match true {
#![attr]
#[attr]
_ => false,
#[attr] match true
{
#[attr]
_ => false,
};
let _ = #[attr] || #[attr] foo;
let _ = #[attr] move || #[attr] foo;
......@@ -119,10 +119,10 @@ fn syntax() {
let _ = #[attr] foo![# ! [attr]];
let _ = #[attr] foo! { };
let _ = #[attr] foo! { # ! [attr] };
let _ = #[attr] Foo{#![attr] bar: baz,};
let _ = #[attr] Foo{#![attr] ..foo};
let _ = #[attr] Foo{#![attr] bar: baz, ..foo};
let _ = #[attr] (#![attr] 0);
let _ = #[attr] Foo{bar: baz,};
let _ = #[attr] Foo{..foo};
let _ = #[attr] Foo{bar: baz, ..foo};
let _ = #[attr] (0);
{
#[attr]
......
......@@ -41,16 +41,9 @@ fn _3() {
fn _4() {
#[rustc_dummy]
match () {
#![rustc_dummy]
_ => (),
}
match () { _ => (), }
let _ =
#[rustc_dummy] match () {
#![rustc_dummy]
() => (),
};
let _ = #[rustc_dummy] match () { () => (), };
}
fn _5() {
......@@ -71,14 +64,14 @@ fn _5() {
fn _6() {
#[rustc_dummy]
[#![rustc_dummy] 1, 2, 3];
[1, 2, 3];
let _ = #[rustc_dummy] [#![rustc_dummy] 1, 2, 3];
let _ = #[rustc_dummy] [1, 2, 3];
#[rustc_dummy]
[#![rustc_dummy] 1; 4];
[1; 4];
let _ = #[rustc_dummy] [#![rustc_dummy] 1; 4];
let _ = #[rustc_dummy] [1; 4];
}
struct Foo {
......@@ -90,24 +83,24 @@ struct Foo {
fn _7() {
#[rustc_dummy]
Foo{#![rustc_dummy] data: (),};
Foo{data: (),};
let _ = #[rustc_dummy] Foo{#![rustc_dummy] data: (),};
let _ = #[rustc_dummy] Foo{data: (),};
}
fn _8() {
#[rustc_dummy]
(#![rustc_dummy] );
();
#[rustc_dummy]
(#![rustc_dummy] 0);
(0);
#[rustc_dummy]
(#![rustc_dummy] 0,);
(0,);
#[rustc_dummy]
(#![rustc_dummy] 0, 1);
(0, 1);
}
fn _9() {
......@@ -138,15 +131,15 @@ fn _10() {
fn _11() {
let _ = #[rustc_dummy] box 0;
let _: [(); 0] = #[rustc_dummy] [#![rustc_dummy] ];
let _ = #[rustc_dummy] [#![rustc_dummy] 0, 0];
let _ = #[rustc_dummy] [#![rustc_dummy] 0; 0];
let _: [(); 0] = #[rustc_dummy] [];
let _ = #[rustc_dummy] [0, 0];
let _ = #[rustc_dummy] [0; 0];
let _ = #[rustc_dummy] foo();
let _ = #[rustc_dummy] 1i32.clone();
let _ = #[rustc_dummy] (#![rustc_dummy] );
let _ = #[rustc_dummy] (#![rustc_dummy] 0);
let _ = #[rustc_dummy] (#![rustc_dummy] 0,);
let _ = #[rustc_dummy] (#![rustc_dummy] 0, 0);
let _ = #[rustc_dummy] ();
let _ = #[rustc_dummy] (0);
let _ = #[rustc_dummy] (0,);
let _ = #[rustc_dummy] (0, 0);
let _ = #[rustc_dummy] 0 + #[rustc_dummy] 0;
let _ = #[rustc_dummy] !0;
let _ = #[rustc_dummy] -0i32;
......@@ -171,11 +164,7 @@ fn _11() {
#[rustc_dummy] loop {
#![rustc_dummy]
};
let _ =
#[rustc_dummy] match false {
#![rustc_dummy]
_ => (),
};
let _ = #[rustc_dummy] match false { _ => (), };
let _ = #[rustc_dummy] || #[rustc_dummy] ();
let _ = #[rustc_dummy] move || #[rustc_dummy] ();
let _ =
......@@ -237,10 +226,10 @@ fn _11() {
let _ = #[rustc_dummy] expr_mac!();
let _ = #[rustc_dummy] expr_mac![];
let _ = #[rustc_dummy] expr_mac! { };
let _ = #[rustc_dummy] Foo{#![rustc_dummy] data: (),};
let _ = #[rustc_dummy] Foo{#![rustc_dummy] ..s};
let _ = #[rustc_dummy] Foo{#![rustc_dummy] data: (), ..s};
let _ = #[rustc_dummy] (#![rustc_dummy] 0);
let _ = #[rustc_dummy] Foo{data: (),};
let _ = #[rustc_dummy] Foo{..s};
let _ = #[rustc_dummy] Foo{data: (), ..s};
let _ = #[rustc_dummy] (0);
}
fn _12() {
......
......@@ -5,16 +5,14 @@ fn main() {
// Test that attributes on parens get concatenated
// in the expected order in the hir folder.
#[deny(non_snake_case)] (
#![allow(non_snake_case)]
#[deny(non_snake_case)] #[allow(non_snake_case)] (
{
let X = 0;
let _ = X;
}
);
#[allow(non_snake_case)] (
#![deny(non_snake_case)]
#[allow(non_snake_case)] #[deny(non_snake_case)] (
{
let X = 0; //~ ERROR snake case name
let _ = X;
......
error: variable `X` should have a snake case name
--> $DIR/expr_attr_paren_order.rs:19:17
--> $DIR/expr_attr_paren_order.rs:17:17
|
LL | let X = 0;
| ^ help: convert the identifier to snake case (notice the capitalization): `x`
|
note: the lint level is defined here
--> $DIR/expr_attr_paren_order.rs:17:17
--> $DIR/expr_attr_paren_order.rs:15:37
|
LL | #![deny(non_snake_case)]
| ^^^^^^^^^^^^^^
LL | #[allow(non_snake_case)] #[deny(non_snake_case)] (
| ^^^^^^^^^^^^^^
error: aborting due to previous error
......@@ -8,15 +8,31 @@ fn main() {
//~^ ERROR an inner attribute is not permitted in this context
let b = (#![allow(warnings)] 1, 2);
//~^ ERROR an inner attribute is not permitted in this context
let c = {
#![allow(warnings)]
(#![allow(warnings)] 1, 2)
//~^ ERROR an inner attribute is not permitted in this context
};
let d = {
#![allow(warnings)]
let e = (#![allow(warnings)] 1, 2);
//~^ ERROR an inner attribute is not permitted in this context
e
};
let e = [#![allow(warnings)] 1, 2];
//~^ ERROR an inner attribute is not permitted in this context
let f = [#![allow(warnings)] 1; 0];
//~^ ERROR an inner attribute is not permitted in this context
let g = match true { #![allow(warnings)] _ => {} };
//~^ ERROR an inner attribute is not permitted in this context
struct MyStruct { field: u8 }
let h = MyStruct { #![allow(warnings)] field: 0 };
//~^ ERROR an inner attribute is not permitted in this context
}
......@@ -6,5 +6,61 @@ LL | let a = #![allow(warnings)] (1, 2);
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: aborting due to previous error
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:10:14
|
LL | let b = (#![allow(warnings)] 1, 2);
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:15:10
|
LL | (#![allow(warnings)] 1, 2)
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:21:18
|
LL | let e = (#![allow(warnings)] 1, 2);
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:26:14
|
LL | let e = [#![allow(warnings)] 1, 2];
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:29:14
|
LL | let f = [#![allow(warnings)] 1; 0];
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:32:26
|
LL | let g = match true { #![allow(warnings)] _ => {} };
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: an inner attribute is not permitted in this context
--> $DIR/stmt_expr_attrs_placement.rs:36:24
|
LL | let h = MyStruct { #![allow(warnings)] field: 0 };
| ^^^^^^^^^^^^^^^^^^^
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
error: aborting due to 8 previous errors
// compile-flags: -Z span-debug --error-format human
// aux-build:test-macros.rs
// edition:2018
#![feature(custom_inner_attributes)]
#![feature(proc_macro_hygiene)]
#![feature(stmt_expr_attributes)]
......@@ -34,8 +35,6 @@ struct MyStruct {
struct MyDerivePrint {
field: [u8; {
match true {
#![cfg_attr(not(FALSE), rustc_dummy(first))]
#![cfg_attr(not(FALSE), rustc_dummy(second))]
_ => {
#![cfg_attr(not(FALSE), rustc_dummy(third))]
true
......@@ -46,49 +45,20 @@ struct MyDerivePrint {
}
fn bar() {
(#![print_target_and_args(fifth)] 1, 2);
//~^ ERROR expected non-macro inner attribute, found attribute macro
#[print_target_and_args(tuple_attrs)] (
#![cfg_attr(FALSE, rustc_dummy)]
3, 4, {
#![cfg_attr(not(FALSE), rustc_dummy(innermost))]
5
}
);
#[print_target_and_args(array_attrs)] [
#![rustc_dummy(inner)]
true; 0
];
#[print_target_and_args(tuple_attrs)] (
#![cfg_attr(FALSE, rustc_dummy)]
3, 4, {
#![cfg_attr(not(FALSE), rustc_dummy(innermost))]
5
}
);
#[print_target_and_args(array_attrs)] [
#![rustc_dummy(inner)]
true; 0
];
[#![print_target_and_args(sixth)] 1 , 2];
//~^ ERROR expected non-macro inner attribute, found attribute macro
[#![print_target_and_args(seventh)] true ; 5];
//~^ ERROR expected non-macro inner attribute, found attribute macro
match 0 {
#![print_target_and_args(eighth)]
//~^ ERROR expected non-macro inner attribute, found attribute macro
_ => {}
}
MyStruct { #![print_target_and_args(ninth)] field: true };
//~^ ERROR expected non-macro inner attribute, found attribute macro
for _ in &[true] {
#![print_attr] //~ ERROR expected non-macro inner attribute
}
......
error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
--> $DIR/inner-attrs.rs:49:9
|
LL | (#![print_target_and_args(fifth)] 1, 2);
| ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
--> $DIR/inner-attrs.rs:78:9
|
LL | [#![print_target_and_args(sixth)] 1 , 2];
| ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
--> $DIR/inner-attrs.rs:80:9
|
LL | [#![print_target_and_args(seventh)] true ; 5];
| ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
--> $DIR/inner-attrs.rs:84:12
|
LL | #![print_target_and_args(eighth)]
| ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_target_and_args`
--> $DIR/inner-attrs.rs:89:19
|
LL | MyStruct { #![print_target_and_args(ninth)] field: true };
| ^^^^^^^^^^^^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
--> $DIR/inner-attrs.rs:93:12
--> $DIR/inner-attrs.rs:63:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
--> $DIR/inner-attrs.rs:97:12
--> $DIR/inner-attrs.rs:67:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
--> $DIR/inner-attrs.rs:101:12
--> $DIR/inner-attrs.rs:71:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
error: expected non-macro inner attribute, found attribute macro `print_attr`
--> $DIR/inner-attrs.rs:105:12
--> $DIR/inner-attrs.rs:75:12
|
LL | #![print_attr]
| ^^^^^^^^^^ not a non-macro inner attribute
error: aborting due to 9 previous errors
error: aborting due to 4 previous errors
// check-pass
// compile-flags: -Z span-debug --error-format human
// aux-build:test-macros.rs
// edition:2018
#![feature(proc_macro_hygiene)]
#![no_std] // Don't load unnecessary hygiene information from std
extern crate std;
#[macro_use]
extern crate test_macros;
fn main() {
#[print_target_and_args(my_arg)] (
#![cfg_attr(not(FALSE), allow(unused))]
1, 2, 3
);
}
PRINT-ATTR_ARGS INPUT (DISPLAY): my_arg
PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
Ident {
ident: "my_arg",
span: $DIR/simple-tuple.rs:15:29: 15:35 (#0),
},
]
PRINT-ATTR INPUT (DISPLAY): (# ! [allow(unused)] 1, 2, 3) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Group {
delimiter: Parenthesis,
stream: TokenStream [
Punct {
ch: '#',
spacing: Alone,
span: $DIR/simple-tuple.rs:16:9: 16:10 (#0),
},
Punct {
ch: '!',
spacing: Alone,
span: $DIR/simple-tuple.rs:16:10: 16:11 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "allow",
span: $DIR/simple-tuple.rs:16:33: 16:38 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "unused",
span: $DIR/simple-tuple.rs:16:39: 16:45 (#0),
},
],
span: $DIR/simple-tuple.rs:16:38: 16:46 (#0),
},
],
span: $DIR/simple-tuple.rs:16:9: 16:10 (#0),
},
Literal {
kind: Integer,
symbol: "1",
suffix: None,
span: $DIR/simple-tuple.rs:17:9: 17:10 (#0),
},
Punct {
ch: ',',
spacing: Alone,
span: $DIR/simple-tuple.rs:17:10: 17:11 (#0),
},
Literal {
kind: Integer,
symbol: "2",
suffix: None,
span: $DIR/simple-tuple.rs:17:12: 17:13 (#0),
},
Punct {
ch: ',',
spacing: Alone,
span: $DIR/simple-tuple.rs:17:13: 17:14 (#0),
},
Literal {
kind: Integer,
symbol: "3",
suffix: None,
span: $DIR/simple-tuple.rs:17:15: 17:16 (#0),
},
],
span: $DIR/simple-tuple.rs:15:38: 18:6 (#0),
},
Punct {
ch: ';',
spacing: Alone,
span: $DIR/simple-tuple.rs:18:6: 18:7 (#0),
},
]
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册