From 2a0b51d852e3765d257284f91fc3246084c96ee5 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sun, 31 Jul 2022 15:11:00 +0000 Subject: [PATCH 1/8] Always include a position span in rustc_parse_format::Argument --- compiler/rustc_builtin_macros/src/asm.rs | 5 +- compiler/rustc_builtin_macros/src/format.rs | 14 ++-- compiler/rustc_parse_format/src/lib.rs | 40 +++++------ compiler/rustc_parse_format/src/tests.rs | 70 ++++++++++++++++--- .../src/traits/on_unimplemented.rs | 4 +- src/tools/clippy/clippy_lints/src/write.rs | 4 +- 6 files changed, 96 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index a2205c3613d92..bb64394e21eba 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -656,7 +656,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option { + parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => { if idx >= args.operands.len() || named_pos.contains_key(&idx) || args.reg_args.contains(&idx) @@ -702,11 +702,12 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option { + parse::ArgumentNamed(name) => { match args.named_args.get(&Symbol::intern(name)) { Some(&idx) => Some(idx), None => { let msg = format!("there is no argument named `{}`", name); + let span = arg.position_span; ecx.struct_span_err( template_span .from_inner(InnerSpan::new(span.start, span.end)), diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 082c78934262b..f536d0b5900bc 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -381,8 +381,8 @@ impl<'a, 'b> Context<'a, 'b> { match *p { parse::String(_) => {} parse::NextArgument(ref mut arg) => { - if let parse::ArgumentNamed(s, _) = arg.position { - arg.position = parse::ArgumentIs(lookup(s), None); + if let parse::ArgumentNamed(s) = arg.position { + arg.position = parse::ArgumentIs(lookup(s)); } if let parse::CountIsName(s, _) = arg.format.width { arg.format.width = parse::CountIsParam(lookup(s)); @@ -417,14 +417,14 @@ impl<'a, 'b> Context<'a, 'b> { // argument second, if it's an implicit positional parameter // it's written second, so it should come after width/precision. let pos = match arg.position { - parse::ArgumentIs(i, arg_end) => { + parse::ArgumentIs(i) => { self.unused_names_lint.maybe_add_positional_named_arg( i, self.args.len(), i, PositionalNamedArgType::Arg, self.curpiece, - arg_end, + Some(arg.position_span), &self.names, ); @@ -442,8 +442,9 @@ impl<'a, 'b> Context<'a, 'b> { ); Exact(i) } - parse::ArgumentNamed(s, span) => { + parse::ArgumentNamed(s) => { let symbol = Symbol::intern(s); + let span = arg.position_span; Named(symbol, InnerSpan::new(span.start, span.end)) } }; @@ -878,8 +879,9 @@ impl<'a, 'b> Context<'a, 'b> { // track the current argument ourselves. let i = self.curarg; self.curarg += 1; - parse::ArgumentIs(i, None) + parse::ArgumentIs(i) }, + position_span: arg.position_span, format: parse::FormatSpec { fill: arg.format.fill, align: parse::AlignUnknown, diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 5deb17b8651b6..a7ff9711691fb 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -70,6 +70,9 @@ pub enum Piece<'a> { pub struct Argument<'a> { /// Where to find this argument pub position: Position<'a>, + /// The span of the position indicator. Includes any whitespace in implicit + /// positions (`{ }`). + pub position_span: InnerSpan, /// How to format the argument pub format: FormatSpec<'a>, } @@ -105,9 +108,9 @@ pub enum Position<'a> { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), /// The argument is located at a specific index given in the format, - ArgumentIs(usize, Option), + ArgumentIs(usize), /// The argument has a name. - ArgumentNamed(&'a str, InnerSpan), + ArgumentNamed(&'a str), } impl Position<'_> { @@ -216,14 +219,15 @@ impl<'a> Iterator for Parser<'a> { '{' => { let curr_last_brace = self.last_opening_brace; let byte_pos = self.to_span_index(pos); - self.last_opening_brace = Some(byte_pos.to(InnerOffset(byte_pos.0 + 1))); + let lbrace_end = InnerOffset(byte_pos.0 + 1); + self.last_opening_brace = Some(byte_pos.to(lbrace_end)); self.cur.next(); if self.consume('{') { self.last_opening_brace = curr_last_brace; Some(String(self.string(pos + 1))) } else { - let arg = self.argument(); + let arg = self.argument(lbrace_end); if let Some(rbrace_byte_idx) = self.must_consume('}') { let lbrace_inner_offset = self.to_span_index(pos); let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx); @@ -477,8 +481,16 @@ impl<'a> Parser<'a> { } /// Parses an `Argument` structure, or what's contained within braces inside the format string. - fn argument(&mut self) -> Argument<'a> { + fn argument(&mut self, start: InnerOffset) -> Argument<'a> { let pos = self.position(); + + let end = self + .cur + .clone() + .find(|(_, ch)| !ch.is_whitespace()) + .map_or(start, |(end, _)| self.to_span_index(end)); + let position_span = start.to(end); + let format = match self.mode { ParseMode::Format => self.format(), ParseMode::InlineAsm => self.inline_asm(), @@ -494,7 +506,7 @@ impl<'a> Parser<'a> { } }; - Argument { position: pos, format } + Argument { position: pos, position_span, format } } /// Parses a positional argument for a format. This could either be an @@ -502,23 +514,11 @@ impl<'a> Parser<'a> { /// Returns `Some(parsed_position)` if the position is not implicitly /// consuming a macro argument, `None` if it's the case. fn position(&mut self) -> Option> { - let start_position = self.cur.peek().map(|item| item.0); if let Some(i) = self.integer() { - let inner_span = start_position.and_then(|start| { - self.cur - .peek() - .cloned() - .and_then(|item| Some(self.to_span_index(start).to(self.to_span_index(item.0)))) - }); - Some(ArgumentIs(i, inner_span)) + Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(start, c)) if rustc_lexer::is_id_start(c) => { - let word = self.word(); - let end = start + word.len(); - let span = self.to_span_index(start).to(self.to_span_index(end)); - Some(ArgumentNamed(word, span)) - } + Some(&(_, c)) if rustc_lexer::is_id_start(c) => Some(ArgumentNamed(self.word())), // This is an `ArgumentNext`. // Record the fact and do the resolution after parsing the diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index a98f816644bd6..578530696105d 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -58,14 +58,22 @@ fn invalid06() { #[test] fn format_nothing() { - same("{}", &[NextArgument(Argument { position: ArgumentImplicitlyIs(0), format: fmtdflt() })]); + same( + "{}", + &[NextArgument(Argument { + position: ArgumentImplicitlyIs(0), + position_span: InnerSpan { start: 2, end: 2 }, + format: fmtdflt(), + })], + ); } #[test] fn format_position() { same( "{3}", &[NextArgument(Argument { - position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + position: ArgumentIs(3), + position_span: InnerSpan { start: 2, end: 3 }, format: fmtdflt(), })], ); @@ -75,17 +83,30 @@ fn format_position_nothing_else() { same( "{3:}", &[NextArgument(Argument { - position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + position: ArgumentIs(3), + position_span: InnerSpan { start: 2, end: 3 }, format: fmtdflt(), })], ); } #[test] +fn format_named() { + same( + "{name}", + &[NextArgument(Argument { + position: ArgumentNamed("name"), + position_span: InnerSpan { start: 2, end: 6 }, + format: fmtdflt(), + })], + ) +} +#[test] fn format_type() { same( "{3:x}", &[NextArgument(Argument { - position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + position: ArgumentIs(3), + position_span: InnerSpan { start: 2, end: 3 }, format: FormatSpec { fill: None, align: AlignUnknown, @@ -105,7 +126,8 @@ fn format_align_fill() { same( "{3:>}", &[NextArgument(Argument { - position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + position: ArgumentIs(3), + position_span: InnerSpan { start: 2, end: 3 }, format: FormatSpec { fill: None, align: AlignRight, @@ -122,7 +144,8 @@ fn format_align_fill() { same( "{3:0<}", &[NextArgument(Argument { - position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + position: ArgumentIs(3), + position_span: InnerSpan { start: 2, end: 3 }, format: FormatSpec { fill: Some('0'), align: AlignLeft, @@ -139,7 +162,8 @@ fn format_align_fill() { same( "{3:* OnUnimplementedFormatString { match token { Piece::String(_) => (), // Normal string, no need to check it Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s, _) => { + Position::ArgumentNamed(s) => { match Symbol::intern(s) { // `{Self}` is allowed kw::SelfUpper => (), @@ -386,7 +386,7 @@ impl<'tcx> OnUnimplementedFormatString { .map(|p| match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s, _) => { + Position::ArgumentNamed(s) => { let s = Symbol::intern(s); match generic_map.get(&s) { Some(val) => val, diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 3a99d1b417fee..32718200c0b3a 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -441,7 +441,7 @@ impl SimpleFormatArgs { }; match arg.position { - ArgumentIs(n, _) | ArgumentImplicitlyIs(n) => { + ArgumentIs(n) | ArgumentImplicitlyIs(n) => { if self.unnamed.len() <= n { // Use a dummy span to mark all unseen arguments. self.unnamed.resize_with(n, || vec![DUMMY_SP]); @@ -462,7 +462,7 @@ impl SimpleFormatArgs { } } }, - ArgumentNamed(n, _) => { + ArgumentNamed(n) => { let n = Symbol::intern(n); if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) { match x.1.as_slice() { From 099a32bbe4af19568286845ab0a7c439b81fef4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 1 Aug 2022 00:00:00 +0000 Subject: [PATCH 2/8] Remove redundant `TransferWrapper` struct --- .../rustc_mir_dataflow/src/impls/liveness.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index e64136928cce8..21132eb991fd5 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -222,18 +222,6 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for MaybeTransitiveLiveLocals<'a> { } } -struct TransferWrapper<'a>(&'a mut ChunkedBitSet); - -impl<'a> GenKill for TransferWrapper<'a> { - fn gen(&mut self, l: Local) { - self.0.insert(l); - } - - fn kill(&mut self, l: Local) { - self.0.remove(l); - } -} - impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { fn apply_statement_effect( &self, @@ -271,7 +259,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { return; } } - TransferFunction(&mut TransferWrapper(trans)).visit_statement(statement, location); + TransferFunction(trans).visit_statement(statement, location); } fn apply_terminator_effect( @@ -280,7 +268,7 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> { terminator: &mir::Terminator<'tcx>, location: Location, ) { - TransferFunction(&mut TransferWrapper(trans)).visit_terminator(terminator, location); + TransferFunction(trans).visit_terminator(terminator, location); } fn apply_call_return_effect( From 96c955e66b39f23eca553644aeb2ea5f41ff355a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 2 Aug 2022 05:25:45 +0100 Subject: [PATCH 3/8] Properly reject the `may_unwind` option in `global_asm!` This was accidentally accepted even though it had no effect in `global_asm!`. The option only makes sense for `asm!` which runs within a function. --- compiler/rustc_builtin_macros/src/asm.rs | 4 ++-- src/test/ui/asm/aarch64/bad-options.stderr | 24 +++++++++++----------- src/test/ui/asm/aarch64/parse-error.stderr | 12 +++++------ src/test/ui/asm/x86_64/bad-options.stderr | 24 +++++++++++----------- src/test/ui/asm/x86_64/parse-error.stderr | 12 +++++------ 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index a2205c3613d92..fc310129b249e 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -410,12 +410,12 @@ fn parse_options<'a>( try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN); } else if !is_global_asm && p.eat_keyword(sym::nostack) { try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK); + } else if !is_global_asm && p.eat_keyword(sym::may_unwind) { + try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND); } else if p.eat_keyword(sym::att_syntax) { try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX); } else if p.eat_keyword(kw::Raw) { try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW); - } else if p.eat_keyword(sym::may_unwind) { - try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND); } else { return p.unexpected(); } diff --git a/src/test/ui/asm/aarch64/bad-options.stderr b/src/test/ui/asm/aarch64/bad-options.stderr index 867e0433eae1b..21bcc4a9c7bad 100644 --- a/src/test/ui/asm/aarch64/bad-options.stderr +++ b/src/test/ui/asm/aarch64/bad-options.stderr @@ -36,41 +36,41 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C")); | | | generic outputs -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/bad-options.rs:28:25 | LL | global_asm!("", options(nomem)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `readonly` +error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` --> $DIR/bad-options.rs:30:25 | LL | global_asm!("", options(readonly)); - | ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `noreturn` +error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` --> $DIR/bad-options.rs:32:25 | LL | global_asm!("", options(noreturn)); - | ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `pure` +error: expected one of `)`, `att_syntax`, or `raw`, found `pure` --> $DIR/bad-options.rs:34:25 | LL | global_asm!("", options(pure)); - | ^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nostack` +error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` --> $DIR/bad-options.rs:36:25 | LL | global_asm!("", options(nostack)); - | ^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `preserves_flags` +error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` --> $DIR/bad-options.rs:38:25 | LL | global_asm!("", options(preserves_flags)); - | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: invalid ABI for `clobber_abi` --> $DIR/bad-options.rs:20:18 diff --git a/src/test/ui/asm/aarch64/parse-error.stderr b/src/test/ui/asm/aarch64/parse-error.stderr index f2013046cda42..804966b06ba7d 100644 --- a/src/test/ui/asm/aarch64/parse-error.stderr +++ b/src/test/ui/asm/aarch64/parse-error.stderr @@ -260,23 +260,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO` LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `FOO` +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` --> $DIR/parse-error.rs:102:25 | LL | global_asm!("", options(FOO)); - | ^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:104:25 | LL | global_asm!("", options(nomem FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:106:25 | LL | global_asm!("", options(nomem, FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: arguments are not allowed after options --> $DIR/parse-error.rs:108:30 diff --git a/src/test/ui/asm/x86_64/bad-options.stderr b/src/test/ui/asm/x86_64/bad-options.stderr index a63c42aac2737..e2351840eef21 100644 --- a/src/test/ui/asm/x86_64/bad-options.stderr +++ b/src/test/ui/asm/x86_64/bad-options.stderr @@ -45,41 +45,41 @@ LL | asm!("{}", out(reg) foo, clobber_abi("C"), clobber_abi("C")); | | clobber_abi | generic outputs -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/bad-options.rs:31:25 | LL | global_asm!("", options(nomem)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `readonly` +error: expected one of `)`, `att_syntax`, or `raw`, found `readonly` --> $DIR/bad-options.rs:33:25 | LL | global_asm!("", options(readonly)); - | ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `noreturn` +error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn` --> $DIR/bad-options.rs:35:25 | LL | global_asm!("", options(noreturn)); - | ^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `pure` +error: expected one of `)`, `att_syntax`, or `raw`, found `pure` --> $DIR/bad-options.rs:37:25 | LL | global_asm!("", options(pure)); - | ^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nostack` +error: expected one of `)`, `att_syntax`, or `raw`, found `nostack` --> $DIR/bad-options.rs:39:25 | LL | global_asm!("", options(nostack)); - | ^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `preserves_flags` +error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags` --> $DIR/bad-options.rs:41:25 | LL | global_asm!("", options(preserves_flags)); - | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw` error: invalid ABI for `clobber_abi` --> $DIR/bad-options.rs:20:18 diff --git a/src/test/ui/asm/x86_64/parse-error.stderr b/src/test/ui/asm/x86_64/parse-error.stderr index 1fd317a96a8a6..57702c37b7ce2 100644 --- a/src/test/ui/asm/x86_64/parse-error.stderr +++ b/src/test/ui/asm/x86_64/parse-error.stderr @@ -266,23 +266,23 @@ error: expected one of `,`, `.`, `?`, or an operator, found `FOO` LL | global_asm!("{}", const(reg) FOO); | ^^^ expected one of `,`, `.`, `?`, or an operator -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `FOO` +error: expected one of `)`, `att_syntax`, or `raw`, found `FOO` --> $DIR/parse-error.rs:104:25 | LL | global_asm!("", options(FOO)); - | ^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:106:25 | LL | global_asm!("", options(nomem FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` -error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem` +error: expected one of `)`, `att_syntax`, or `raw`, found `nomem` --> $DIR/parse-error.rs:108:25 | LL | global_asm!("", options(nomem, FOO)); - | ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw` + | ^^^^^ expected one of `)`, `att_syntax`, or `raw` error: arguments are not allowed after options --> $DIR/parse-error.rs:110:30 From efa9586427a88018da59daf1217c82e873ace329 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Tue, 2 Aug 2022 10:10:11 +0200 Subject: [PATCH 4/8] RISC-V ASM test: relax label name constraint. --- src/test/assembly/asm/riscv-types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs index 0f9f61bd6d916..68dc186ea0c76 100644 --- a/src/test/assembly/asm/riscv-types.rs +++ b/src/test/assembly/asm/riscv-types.rs @@ -56,7 +56,7 @@ pub unsafe fn sym_fn() { // CHECK-LABEL: sym_static: // CHECK: #APP // CHECK: auipc t0, %pcrel_hi(extern_static) -// CHECK: lb t0, %pcrel_lo(.Lpcrel_hi0)(t0) +// CHECK: lb t0, %pcrel_lo(.Lpcrel_hi{{[0-9]+}})(t0) // CHECK: #NO_APP #[no_mangle] pub unsafe fn sym_static() { From b608ec8f4185b150d43db870cd153c3c836a15a5 Mon Sep 17 00:00:00 2001 From: tabokie Date: Mon, 1 Aug 2022 13:22:16 +0800 Subject: [PATCH 5/8] move [`assertions_on_result_states`] to restriction Signed-off-by: tabokie --- .../clippy/clippy_lints/src/assertions_on_result_states.rs | 5 ++++- src/tools/clippy/clippy_lints/src/lib.register_all.rs | 1 - .../clippy/clippy_lints/src/lib.register_restriction.rs | 1 + src/tools/clippy/clippy_lints/src/lib.register_style.rs | 1 - 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs index b6affdee52364..4caab6230909c 100644 --- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs +++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs @@ -19,6 +19,9 @@ declare_clippy_lint! { /// ### Why is this bad? /// An assertion failure cannot output an useful message of the error. /// + /// ### Known problems + /// The suggested replacement decreases the readability of code and log output. + /// /// ### Example /// ```rust,ignore /// # let r = Ok::<_, ()>(()); @@ -28,7 +31,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.64.0"] pub ASSERTIONS_ON_RESULT_STATES, - style, + restriction, "`assert!(r.is_ok())`/`assert!(r.is_err())` gives worse error message than directly calling `r.unwrap()`/`r.unwrap_err()`" } diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs index 5be1c417bf8f6..0ba9b7ae7e581 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs @@ -6,7 +6,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE), LintId::of(approx_const::APPROX_CONSTANT), LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES), LintId::of(async_yields_async::ASYNC_YIELDS_ASYNC), LintId::of(attrs::BLANKET_CLIPPY_RESTRICTION_LINTS), LintId::of(attrs::DEPRECATED_CFG_ATTR), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs index 495abd8387e85..a7339ef272174 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs @@ -7,6 +7,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve LintId::of(as_underscore::AS_UNDERSCORE), LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX), LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX), + LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES), LintId::of(attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON), LintId::of(casts::FN_TO_NUMERIC_CAST_ANY), LintId::of(create_dir::CREATE_DIR), diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs index e029a5235e720..e95bab1d0454d 100644 --- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs +++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs @@ -4,7 +4,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(assertions_on_constants::ASSERTIONS_ON_CONSTANTS), - LintId::of(assertions_on_result_states::ASSERTIONS_ON_RESULT_STATES), LintId::of(blacklisted_name::BLACKLISTED_NAME), LintId::of(blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS), LintId::of(bool_assert_comparison::BOOL_ASSERT_COMPARISON), From fa14d02d9bdd17206a26a25c02555a99bf980f1c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Aug 2022 12:42:36 +0200 Subject: [PATCH 6/8] Remove Clean trait implementation for ty::TraitRef --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 8 ++++---- src/librustdoc/clean/mod.rs | 10 ++-------- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 5fe2c9ab4e37b..4c7c9412edda7 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -120,7 +120,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { kind: Box::new(ImplItem(Box::new(Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, - trait_: Some(trait_ref.clean(self.cx)), + trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, &[])), for_: clean_middle_ty(ty, self.cx, None), items: Vec::new(), polarity, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 8aecd9b15e842..01dd95e6e4093 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -115,7 +115,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { ), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(trait_ref.0.clean(cx)), + trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, &[])), for_: clean_middle_ty(ty.0, cx, None), items: cx.tcx .associated_items(impl_def_id) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 838283e32daf4..e86c1d553a897 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -16,9 +16,9 @@ use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ - self, clean_fn_decl_from_did_and_sig, clean_middle_field, clean_middle_ty, clean_ty, - clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt, - Clean, ImplKind, ItemId, Type, Visibility, + self, clean_fn_decl_from_did_and_sig, clean_middle_field, clean_middle_ty, + clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def, + clean_visibility, utils, Attributes, AttributesExt, Clean, ImplKind, ItemId, Type, Visibility, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -450,7 +450,7 @@ pub(crate) fn build_impl( ), }; let polarity = tcx.impl_polarity(did); - let trait_ = associated_trait.map(|t| t.clean(cx)); + let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, &[])); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4067cf8441b3d..85505c699f958 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -163,7 +163,7 @@ impl<'tcx> Clean<'tcx, Option> for hir::GenericBound<'tcx> { } } -fn clean_trait_ref_with_bindings<'tcx>( +pub(crate) fn clean_trait_ref_with_bindings<'tcx>( cx: &mut DocContext<'tcx>, trait_ref: ty::TraitRef<'tcx>, bindings: &[TypeBinding], @@ -180,12 +180,6 @@ fn clean_trait_ref_with_bindings<'tcx>( path } -impl<'tcx> Clean<'tcx, Path> for ty::TraitRef<'tcx> { - fn clean(&self, cx: &mut DocContext<'tcx>) -> Path { - clean_trait_ref_with_bindings(cx, *self, &[]) - } -} - fn clean_poly_trait_ref_with_bindings<'tcx>( cx: &mut DocContext<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, @@ -432,7 +426,7 @@ fn clean_projection<'tcx>( def_id: Option, ) -> Type { let lifted = ty.lift_to_tcx(cx.tcx).unwrap(); - let trait_ = lifted.trait_ref(cx.tcx).clean(cx); + let trait_ = clean_trait_ref_with_bindings(cx, lifted.trait_ref(cx.tcx), &[]); let self_type = clean_middle_ty(ty.self_ty(), cx, None); let self_def_id = if let Some(def_id) = def_id { cx.tcx.opt_parent(def_id).or(Some(def_id)) From f84a948df1de5cd5e130f64f53d3bf1783ab5af0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Aug 2022 12:55:25 +0200 Subject: [PATCH 7/8] Remove Clean trait implementation for hir::Lifetime --- src/librustdoc/clean/mod.rs | 40 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 85505c699f958..a13665eb30602 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -130,7 +130,7 @@ impl<'tcx> Clean<'tcx, Attributes> for [ast::Attribute] { impl<'tcx> Clean<'tcx, Option> for hir::GenericBound<'tcx> { fn clean(&self, cx: &mut DocContext<'tcx>) -> Option { Some(match *self { - hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), + hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)), hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); @@ -214,21 +214,19 @@ impl<'tcx> Clean<'tcx, GenericBound> for ty::PolyTraitRef<'tcx> { } } -impl<'tcx> Clean<'tcx, Lifetime> for hir::Lifetime { - fn clean(&self, cx: &mut DocContext<'tcx>) -> Lifetime { - let def = cx.tcx.named_region(self.hir_id); - if let Some( - rl::Region::EarlyBound(_, node_id) - | rl::Region::LateBound(_, _, node_id) - | rl::Region::Free(_, node_id), - ) = def - { - if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { - return lt; - } +fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime { + let def = cx.tcx.named_region(lifetime.hir_id); + if let Some( + rl::Region::EarlyBound(_, node_id) + | rl::Region::LateBound(_, _, node_id) + | rl::Region::Free(_, node_id), + ) = def + { + if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() { + return lt; } - Lifetime(self.name.ident().name) } + Lifetime(lifetime.name.ident().name) } pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant { @@ -305,7 +303,7 @@ impl<'tcx> Clean<'tcx, Option> for hir::WherePredicate<'tcx> { } hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate { - lifetime: wrp.lifetime.clean(cx), + lifetime: clean_lifetime(wrp.lifetime, cx), bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(), }, @@ -518,7 +516,7 @@ fn clean_generic_param<'tcx>( .filter(|bp| !bp.in_where_clause) .flat_map(|bp| bp.bounds) .map(|bound| match bound { - hir::GenericBound::Outlives(lt) => lt.clean(cx), + hir::GenericBound::Outlives(lt) => clean_lifetime(*lt, cx), _ => panic!(), }) .collect() @@ -1425,7 +1423,8 @@ fn maybe_expand_private_type_alias<'tcx>( }); if let Some(lt) = lifetime.cloned() { let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id); - let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() }; + let cleaned = + if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() }; substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned)); } indices.lifetimes += 1; @@ -1497,7 +1496,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T // there's no case where it could cause the function to fail to compile. let elided = l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh)); - let lifetime = if elided { None } else { Some(l.clean(cx)) }; + let lifetime = if elided { None } else { Some(clean_lifetime(*l, cx)) }; BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), @@ -1533,7 +1532,8 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T TyKind::Path(_) => clean_qpath(ty, cx), TyKind::TraitObject(bounds, ref lifetime, _) => { let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect(); - let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; + let lifetime = + if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None }; DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(barefn.clean(cx))), @@ -1871,7 +1871,7 @@ impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> { .iter() .map(|arg| match arg { hir::GenericArg::Lifetime(lt) if !lt.is_elided() => { - GenericArg::Lifetime(lt.clean(cx)) + GenericArg::Lifetime(clean_lifetime(*lt, cx)) } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), From 04f570aad0b89d4475fbf65c6f9567e6f11cad20 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 1 Aug 2022 01:59:33 +0200 Subject: [PATCH 8/8] Remove Clean trait implementation for ast::Attribute and cleanup Attributes::from_ast function by splitting it in two --- src/librustdoc/clean/inline.rs | 6 +++--- src/librustdoc/clean/mod.rs | 8 +------- src/librustdoc/clean/types.rs | 16 +++++++++------- src/librustdoc/doctest.rs | 2 +- src/librustdoc/html/render/print_item.rs | 2 +- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 838283e32daf4..8d5e91f58c610 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -304,14 +304,14 @@ fn merge_attrs( both.extend_from_slice(old_attrs); ( if let Some(new_id) = parent_module { - Attributes::from_ast(old_attrs, Some((inner, new_id))) + Attributes::from_ast_with_additional(old_attrs, (inner, new_id)) } else { - Attributes::from_ast(&both, None) + Attributes::from_ast(&both) }, both.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } else { - (old_attrs.clean(cx), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg)) + (Attributes::from_ast(&old_attrs), old_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg)) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4067cf8441b3d..8626e8e305d12 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -121,12 +121,6 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> { } } -impl<'tcx> Clean<'tcx, Attributes> for [ast::Attribute] { - fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes { - Attributes::from_ast(self, None) - } -} - impl<'tcx> Clean<'tcx, Option> for hir::GenericBound<'tcx> { fn clean(&self, cx: &mut DocContext<'tcx>) -> Option { Some(match *self { @@ -2097,7 +2091,7 @@ fn clean_extern_crate<'tcx>( // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason vec![Item { name: Some(name), - attrs: Box::new(attrs.clean(cx)), + attrs: Box::new(Attributes::from_ast(attrs)), item_id: crate_def_id.into(), visibility: clean_visibility(ty_vis), kind: Box::new(ExternCrateItem { src: orig_name }), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d022ce9696ad0..712ec41023fa4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,10 +34,10 @@ use rustc_target::spec::abi::Abi; use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; use crate::clean::cfg::Cfg; +use crate::clean::clean_visibility; use crate::clean::external_path; use crate::clean::inline::{self, print_inlined_const}; use crate::clean::utils::{is_literal_expr, print_const_expr, print_evaluated_const}; -use crate::clean::{clean_visibility, Clean}; use crate::core::DocContext; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -477,7 +477,7 @@ impl Item { def_id, name, kind, - Box::new(ast_attrs.clean(cx)), + Box::new(Attributes::from_ast(ast_attrs)), cx, ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), ) @@ -1177,14 +1177,16 @@ impl Attributes { false } - pub(crate) fn from_ast( + pub(crate) fn from_ast(attrs: &[ast::Attribute]) -> Attributes { + Attributes::from_ast_iter(attrs.iter().map(|attr| (attr, None)), false) + } + + pub(crate) fn from_ast_with_additional( attrs: &[ast::Attribute], - additional_attrs: Option<(&[ast::Attribute], DefId)>, + (additional_attrs, def_id): (&[ast::Attribute], DefId), ) -> Attributes { // Additional documentation should be shown before the original documentation. - let attrs1 = additional_attrs - .into_iter() - .flat_map(|(attrs, def_id)| attrs.iter().map(move |attr| (attr, Some(def_id)))); + let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id))); let attrs2 = attrs.iter().map(|attr| (attr, None)); Attributes::from_ast_iter(attrs1.chain(attrs2), false) } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 213f564ce2db5..35964e3ba38e4 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1222,7 +1222,7 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us. - let attrs = Attributes::from_ast(ast_attrs, None); + let attrs = Attributes::from_ast(ast_attrs); if let Some(doc) = attrs.collapsed_doc_value() { // Use the outermost invocation, so that doctest names come from where the docs were written. let span = ast_attrs diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 547d6696a431d..99cf4291927fb 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -345,7 +345,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: clean::ImportItem(ref import) => { let (stab, stab_tags) = if let Some(import_def_id) = import.source.did { let ast_attrs = cx.tcx().get_attrs_unchecked(import_def_id); - let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs, None)); + let import_attrs = Box::new(clean::Attributes::from_ast(ast_attrs)); // Just need an item with the correct def_id and attrs let import_item = clean::Item {