mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Auto merge of #81405 - bugadani:ast, r=cjgillot
Box the biggest ast::ItemKind variants This PR is a different approach on https://github.com/rust-lang/rust/pull/81400, aiming to save memory in humongous ASTs. The three affected item kind enums are: - `ast::ItemKind` (208 -> 112 bytes) - `ast::AssocItemKind` (176 -> 72 bytes) - `ast::ForeignItemKind` (176 -> 72 bytes)
This commit is contained in:
commit
448a97bf52
@ -1,7 +1,7 @@
|
|||||||
use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint};
|
use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_ast::ast::{Async, AttrKind, Attribute, FnRetTy, ItemKind};
|
use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
|
||||||
use rustc_ast::token::CommentKind;
|
use rustc_ast::token::CommentKind;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
@ -492,7 +492,9 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
|
|||||||
| ItemKind::ExternCrate(..)
|
| ItemKind::ExternCrate(..)
|
||||||
| ItemKind::ForeignMod(..) => return false,
|
| ItemKind::ForeignMod(..) => return false,
|
||||||
// We found a main function ...
|
// We found a main function ...
|
||||||
ItemKind::Fn(_, sig, _, Some(block)) if item.ident.name == sym::main => {
|
ItemKind::Fn(box FnKind(_, sig, _, Some(block)))
|
||||||
|
if item.ident.name == sym::main =>
|
||||||
|
{
|
||||||
let is_async = matches!(sig.header.asyncness, Async::Yes { .. });
|
let is_async = matches!(sig.header.asyncness, Async::Yes { .. });
|
||||||
let returns_nothing = match &sig.decl.output {
|
let returns_nothing = match &sig.decl.output {
|
||||||
FnRetTy::Default(..) => true,
|
FnRetTy::Default(..) => true,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help};
|
use crate::utils::{attr_by_name, in_macro, match_path_ast, span_lint_and_help};
|
||||||
use rustc_ast::ast::{AssocItemKind, Extern, FnSig, Item, ItemKind, Ty, TyKind};
|
use rustc_ast::ast::{
|
||||||
|
AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind,
|
||||||
|
};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
@ -158,18 +160,16 @@ impl EarlyLintPass for ExcessiveBools {
|
|||||||
"consider using a state machine or refactoring bools into two-variant enums",
|
"consider using a state machine or refactoring bools into two-variant enums",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
ItemKind::Impl {
|
|
||||||
of_trait: None, items, ..
|
|
||||||
}
|
}
|
||||||
| ItemKind::Trait(_, _, _, _, items) => {
|
ItemKind::Impl(box ImplKind { of_trait: None, items, .. })
|
||||||
|
| ItemKind::Trait(box TraitKind(.., items)) => {
|
||||||
for item in items {
|
for item in items {
|
||||||
if let AssocItemKind::Fn(_, fn_sig, _, _) = &item.kind {
|
if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
|
||||||
self.check_fn_sig(cx, fn_sig, item.span);
|
self.check_fn_sig(cx, fn_sig, item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
ItemKind::Fn(_, fn_sig, _, _) => self.check_fn_sig(cx, fn_sig, item.span),
|
ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use crate::utils::{span_lint, span_lint_and_then};
|
use crate::utils::{span_lint, span_lint_and_then};
|
||||||
use rustc_ast::ast::{Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind};
|
use rustc_ast::ast::{
|
||||||
|
Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat,
|
||||||
|
PatKind,
|
||||||
|
};
|
||||||
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
|
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
@ -364,7 +367,7 @@ impl EarlyLintPass for NonExpressiveNames {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind {
|
if let ItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
|
||||||
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,7 +377,7 @@ impl EarlyLintPass for NonExpressiveNames {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let AssocItemKind::Fn(_, ref sig, _, Some(ref blk)) = item.kind {
|
if let AssocItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
|
||||||
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
do_check(self, cx, &item.attrs, &sig.decl, blk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,17 +229,26 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
match (l, r) {
|
match (l, r) {
|
||||||
(ExternCrate(l), ExternCrate(r)) => l == r,
|
(ExternCrate(l), ExternCrate(r)) => l == r,
|
||||||
(Use(l), Use(r)) => eq_use_tree(l, r),
|
(Use(l), Use(r)) => eq_use_tree(l, r),
|
||||||
(Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
(Static(lt, lm, le), Static(rt, rm, re)) => {
|
||||||
(Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re)
|
||||||
(Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => {
|
}
|
||||||
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
|
(Const(ld, lt, le), Const(rd, rt, re)) => {
|
||||||
},
|
eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re)
|
||||||
(Mod(l), Mod(r)) => l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind)),
|
}
|
||||||
|
(Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
|
||||||
|
eq_defaultness(*ld, *rd)
|
||||||
|
&& eq_fn_sig(lf, rf)
|
||||||
|
&& eq_generics(lg, rg)
|
||||||
|
&& both(lb, rb, |l, r| eq_block(l, r))
|
||||||
|
}
|
||||||
|
(Mod(l), Mod(r)) => {
|
||||||
|
l.inline == r.inline && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_item_kind))
|
||||||
|
}
|
||||||
(ForeignMod(l), ForeignMod(r)) => {
|
(ForeignMod(l), ForeignMod(r)) => {
|
||||||
both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r))
|
both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r))
|
||||||
&& over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
|
&& over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
|
||||||
},
|
}
|
||||||
(TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => {
|
(TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
|
||||||
eq_defaultness(*ld, *rd)
|
eq_defaultness(*ld, *rd)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
||||||
@ -250,8 +259,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
},
|
},
|
||||||
(Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
|
(Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
|
||||||
eq_variant_data(lv, rv) && eq_generics(lg, rg)
|
eq_variant_data(lv, rv) && eq_generics(lg, rg)
|
||||||
},
|
}
|
||||||
(Trait(la, lu, lg, lb, li), Trait(ra, ru, rg, rb, ri)) => {
|
(Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => {
|
||||||
la == ra
|
la == ra
|
||||||
&& matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
|
&& matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
@ -260,7 +269,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
},
|
},
|
||||||
(TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, |l, r| eq_generic_bound(l, r)),
|
(TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, |l, r| eq_generic_bound(l, r)),
|
||||||
(
|
(
|
||||||
Impl {
|
Impl(box ImplKind {
|
||||||
unsafety: lu,
|
unsafety: lu,
|
||||||
polarity: lp,
|
polarity: lp,
|
||||||
defaultness: ld,
|
defaultness: ld,
|
||||||
@ -269,8 +278,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
of_trait: lot,
|
of_trait: lot,
|
||||||
self_ty: lst,
|
self_ty: lst,
|
||||||
items: li,
|
items: li,
|
||||||
},
|
}),
|
||||||
Impl {
|
Impl(box ImplKind {
|
||||||
unsafety: ru,
|
unsafety: ru,
|
||||||
polarity: rp,
|
polarity: rp,
|
||||||
defaultness: rd,
|
defaultness: rd,
|
||||||
@ -279,7 +288,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
of_trait: rot,
|
of_trait: rot,
|
||||||
self_ty: rst,
|
self_ty: rst,
|
||||||
items: ri,
|
items: ri,
|
||||||
},
|
}),
|
||||||
) => {
|
) => {
|
||||||
matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
|
matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
|
||||||
&& matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive)
|
&& matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive)
|
||||||
@ -299,11 +308,16 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||||||
pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
||||||
use ForeignItemKind::*;
|
use ForeignItemKind::*;
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
(Static(lt, lm, le), Static(rt, rm, re)) => {
|
||||||
(Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => {
|
lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re)
|
||||||
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
|
}
|
||||||
},
|
(Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
|
||||||
(TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => {
|
eq_defaultness(*ld, *rd)
|
||||||
|
&& eq_fn_sig(lf, rf)
|
||||||
|
&& eq_generics(lg, rg)
|
||||||
|
&& both(lb, rb, |l, r| eq_block(l, r))
|
||||||
|
}
|
||||||
|
(TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
|
||||||
eq_defaultness(*ld, *rd)
|
eq_defaultness(*ld, *rd)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
||||||
@ -317,11 +331,16 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
|
|||||||
pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
use AssocItemKind::*;
|
use AssocItemKind::*;
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
|
(Const(ld, lt, le), Const(rd, rt, re)) => {
|
||||||
(Fn(ld, lf, lg, lb), Fn(rd, rf, rg, rb)) => {
|
eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re)
|
||||||
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
|
}
|
||||||
},
|
(Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
|
||||||
(TyAlias(ld, lg, lb, lt), TyAlias(rd, rg, rb, rt)) => {
|
eq_defaultness(*ld, *rd)
|
||||||
|
&& eq_fn_sig(lf, rf)
|
||||||
|
&& eq_generics(lg, rg)
|
||||||
|
&& both(lb, rb, |l, r| eq_block(l, r))
|
||||||
|
}
|
||||||
|
(TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
|
||||||
eq_defaultness(*ld, *rd)
|
eq_defaultness(*ld, *rd)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
&& over(lb, rb, |l, r| eq_generic_bound(l, r))
|
||||||
|
@ -3,7 +3,9 @@ use std::ops::Range;
|
|||||||
|
|
||||||
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then};
|
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::{Expr, ExprKind, Item, ItemKind, LitKind, MacCall, StrLit, StrStyle};
|
use rustc_ast::ast::{
|
||||||
|
Expr, ExprKind, ImplKind, Item, ItemKind, LitKind, MacCall, StrLit, StrStyle,
|
||||||
|
};
|
||||||
use rustc_ast::token;
|
use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -231,11 +233,7 @@ impl_lint_pass!(Write => [
|
|||||||
|
|
||||||
impl EarlyLintPass for Write {
|
impl EarlyLintPass for Write {
|
||||||
fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
|
fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
|
||||||
if let ItemKind::Impl {
|
if let ItemKind::Impl(box ImplKind { of_trait: Some(trait_ref), .. }) = &item.kind {
|
||||||
of_trait: Some(trait_ref),
|
|
||||||
..
|
|
||||||
} = &item.kind
|
|
||||||
{
|
|
||||||
let trait_name = trait_ref
|
let trait_name = trait_ref
|
||||||
.path
|
.path
|
||||||
.segments
|
.segments
|
||||||
@ -377,10 +375,15 @@ impl Write {
|
|||||||
/// (Some("string to write: {}"), Some(buf))
|
/// (Some("string to write: {}"), Some(buf))
|
||||||
/// ```
|
/// ```
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
|
fn check_tts<'a>(
|
||||||
|
&self,
|
||||||
|
cx: &EarlyContext<'a>,
|
||||||
|
tts: TokenStream,
|
||||||
|
is_write: bool,
|
||||||
|
) -> (Option<StrLit>, Option<Expr>) {
|
||||||
use rustc_parse_format::{
|
use rustc_parse_format::{
|
||||||
AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec, ParseMode, Parser,
|
AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied,
|
||||||
Piece,
|
FormatSpec, ParseMode, Parser, Piece,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None);
|
let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, false, None);
|
||||||
@ -410,7 +413,12 @@ impl Write {
|
|||||||
if let Piece::NextArgument(arg) = piece {
|
if let Piece::NextArgument(arg) = piece {
|
||||||
if !self.in_debug_impl && arg.format.ty == "?" {
|
if !self.in_debug_impl && arg.format.ty == "?" {
|
||||||
// FIXME: modify rustc's fmt string parser to give us the current span
|
// FIXME: modify rustc's fmt string parser to give us the current span
|
||||||
span_lint(cx, USE_DEBUG, parser.prev_token.span, "use of `Debug`-based formatting");
|
span_lint(
|
||||||
|
cx,
|
||||||
|
USE_DEBUG,
|
||||||
|
parser.prev_token.span,
|
||||||
|
"use of `Debug`-based formatting",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
}
|
}
|
||||||
@ -438,7 +446,9 @@ impl Write {
|
|||||||
return (Some(fmtstr), None);
|
return (Some(fmtstr), None);
|
||||||
};
|
};
|
||||||
match &token_expr.kind {
|
match &token_expr.kind {
|
||||||
ExprKind::Lit(lit) if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..)) => {
|
ExprKind::Lit(lit)
|
||||||
|
if !matches!(lit.kind, LitKind::Int(..) | LitKind::Float(..)) =>
|
||||||
|
{
|
||||||
let mut all_simple = true;
|
let mut all_simple = true;
|
||||||
let mut seen = false;
|
let mut seen = false;
|
||||||
for arg in &args {
|
for arg in &args {
|
||||||
@ -448,15 +458,15 @@ impl Write {
|
|||||||
all_simple &= arg.format == SIMPLE;
|
all_simple &= arg.format == SIMPLE;
|
||||||
seen = true;
|
seen = true;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
ArgumentNamed(_) => {},
|
ArgumentNamed(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if all_simple && seen {
|
if all_simple && seen {
|
||||||
span_lint(cx, lint, token_expr.span, "literal with an empty format string");
|
span_lint(cx, lint, token_expr.span, "literal with an empty format string");
|
||||||
}
|
}
|
||||||
idx += 1;
|
idx += 1;
|
||||||
},
|
}
|
||||||
ExprKind::Assign(lhs, rhs, _) => {
|
ExprKind::Assign(lhs, rhs, _) => {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Lit(ref lit) = rhs.kind;
|
if let ExprKind::Lit(ref lit) = rhs.kind;
|
||||||
@ -481,7 +491,7 @@ impl Write {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => idx += 1,
|
_ => idx += 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,11 +523,17 @@ impl Write {
|
|||||||
cx,
|
cx,
|
||||||
PRINT_WITH_NEWLINE,
|
PRINT_WITH_NEWLINE,
|
||||||
mac.span(),
|
mac.span(),
|
||||||
&format!("using `{}!()` with a format string that ends in a single newline", name),
|
&format!(
|
||||||
|
"using `{}!()` with a format string that ends in a single newline",
|
||||||
|
name
|
||||||
|
),
|
||||||
|err| {
|
|err| {
|
||||||
err.multipart_suggestion(
|
err.multipart_suggestion(
|
||||||
&format!("use `{}!` instead", suggested),
|
&format!("use `{}!` instead", suggested),
|
||||||
vec![(mac.path.span, suggested), (newline_span(&fmt_str), String::new())],
|
vec![
|
||||||
|
(mac.path.span, suggested),
|
||||||
|
(newline_span(&fmt_str), String::new()),
|
||||||
|
],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user