about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-28 21:43:15 +0000
committerbors <bors@rust-lang.org>2023-03-28 21:43:15 +0000
commit58fb8014146c22bfdf60f47c864537abc7b78486 (patch)
treeaa353b846b2d744cea7b7ed76728920c47536fce
parent84e42fb363d295c87e9b191b3e2816e25b6cb42e (diff)
parent6589d794927451ed5d503b108e0e6900bbf91d3d (diff)
downloadrust-58fb8014146c22bfdf60f47c864537abc7b78486.tar.gz
rust-58fb8014146c22bfdf60f47c864537abc7b78486.zip
Auto merge of #10561 - Alexendoo:format-args-ast-3, r=Manishearth
Replace remaining usage of `FormatArgsExpn`

Closes #10233

Removes `FormatArgsExpn` & friends now that they're unused

changelog: none

r? `@Manishearth`
-rw-r--r--clippy_lints/src/explicit_write.rs29
-rw-r--r--clippy_lints/src/format.rs91
-rw-r--r--clippy_lints/src/format_impl.rs60
-rw-r--r--clippy_lints/src/methods/expect_fun_call.rs27
-rw-r--r--clippy_utils/src/lib.rs1
-rw-r--r--clippy_utils/src/macros.rs727
6 files changed, 132 insertions, 803 deletions
diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs
index c0ea6f338a2..315df6c714f 100644
--- a/clippy_lints/src/explicit_write.rs
+++ b/clippy_lints/src/explicit_write.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::FormatArgsExpn;
+use clippy_utils::macros::{find_format_args, format_args_inputs_span};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, match_function_call, paths};
 use if_chain::if_chain;
@@ -8,7 +8,7 @@ use rustc_hir::def::Res;
 use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
+use rustc_span::{sym, ExpnId};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -43,23 +43,22 @@ declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
 
 impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            // match call to unwrap
-            if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind;
-            if unwrap_fun.ident.name == sym::unwrap;
+        // match call to unwrap
+        if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind
+            && unwrap_fun.ident.name == sym::unwrap
             // match call to write_fmt
-            if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind);
-            if write_fun.ident.name == sym!(write_fmt);
+            && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind)
+            && write_fun.ident.name == sym!(write_fmt)
             // match calls to std::io::stdout() / std::io::stderr ()
-            if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
+            && let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
                 Some("stdout")
             } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() {
                 Some("stderr")
             } else {
                 None
-            };
-            if let Some(format_args) = FormatArgsExpn::parse(cx, write_arg);
-            then {
+            }
+        {
+            find_format_args(cx, write_arg, ExpnId::root(), |format_args| {
                 let calling_macro =
                     // ordering is important here, since `writeln!` uses `write!` internally
                     if is_expn_of(write_call.span, "writeln").is_some() {
@@ -92,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 let mut applicability = Applicability::MachineApplicable;
                 let inputs_snippet = snippet_with_applicability(
                     cx,
-                    format_args.inputs_span(),
+                    format_args_inputs_span(format_args),
                     "..",
                     &mut applicability,
                 );
@@ -104,8 +103,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                     "try this",
                     format!("{prefix}{sugg_mac}!({inputs_snippet})"),
                     applicability,
-                )
-            }
+                );
+            });
         }
     }
 }
diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs
index 8040938c626..d34d6e9279e 100644
--- a/clippy_lints/src/format.rs
+++ b/clippy_lints/src/format.rs
@@ -1,14 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node};
+use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
+use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
@@ -44,55 +43,53 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
 
 impl<'tcx> LateLintPass<'tcx> for UselessFormat {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let (format_args, call_site) = if_chain! {
-            if let Some(macro_call) = root_macro_call_first_node(cx, expr);
-            if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id);
-            if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn);
-            then {
-                (format_args, macro_call.span)
-            } else {
-                return
-            }
-        };
+        let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
+        if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) {
+            return;
+        }
+
+        find_format_args(cx, expr, macro_call.expn, |format_args| {
+            let mut applicability = Applicability::MachineApplicable;
+            let call_site = macro_call.span;
 
-        let mut applicability = Applicability::MachineApplicable;
-        if format_args.args.is_empty() {
-            match *format_args.format_string.parts {
-                [] => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
-                [_] => {
+            match (format_args.arguments.all_args(), &format_args.template[..]) {
+                ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
+                ([], [_]) => {
                     // Simulate macro expansion, converting {{ and }} to { and }.
-                    let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}");
+                    let Some(snippet) = snippet_opt(cx, format_args.span) else { return };
+                    let s_expand = snippet.replace("{{", "{").replace("}}", "}");
                     let sugg = format!("{s_expand}.to_string()");
                     span_useless_format(cx, call_site, sugg, applicability);
                 },
-                [..] => {},
-            }
-        } else if let [arg] = &*format_args.args {
-            let value = arg.param.value;
-            if_chain! {
-                if format_args.format_string.parts == [kw::Empty];
-                if arg.format.is_default();
-                if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
-                    ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
-                    ty::Str => true,
-                    _ => false,
-                };
-                then {
-                    let is_new_string = match value.kind {
-                        ExprKind::Binary(..) => true,
-                        ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
-                        _ => false,
-                    };
-                    let sugg = if is_new_string {
-                        snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
-                    } else {
-                        let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
-                        format!("{}.to_string()", sugg.maybe_par())
-                    };
-                    span_useless_format(cx, call_site, sugg, applicability);
-                }
+                ([arg], [piece]) => {
+                    if let Ok(value) = find_format_arg_expr(expr, arg)
+                        && let FormatArgsPiece::Placeholder(placeholder) = piece
+                        && placeholder.format_trait == FormatTrait::Display
+                        && placeholder.format_options == FormatOptions::default()
+                        && match cx.typeck_results().expr_ty(value).peel_refs().kind() {
+                            ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
+                            ty::Str => true,
+                            _ => false,
+                        }
+                    {
+                        let is_new_string = match value.kind {
+                            ExprKind::Binary(..) => true,
+                            ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
+                            _ => false,
+                        };
+                        let sugg = if is_new_string {
+                            snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
+                        } else {
+                            let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
+                            format!("{}.to_string()", sugg.maybe_par())
+                        };
+                        span_useless_format(cx, call_site, sugg, applicability);
+
+                    }
+                },
+                _ => {},
             }
-        };
+        });
     }
 }
 
diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs
index ed1342a5465..e3ddbfb5981 100644
--- a/clippy_lints/src/format_impl.rs
+++ b/clippy_lints/src/format_impl.rs
@@ -1,11 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::macros::{is_format_macro, root_macro_call_first_node, FormatArg, FormatArgsExpn};
+use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node};
 use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
 use if_chain::if_chain;
+use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
 use rustc_span::{sym, symbol::kw, Symbol};
 
 declare_clippy_lint! {
@@ -89,7 +91,7 @@ declare_clippy_lint! {
 }
 
 #[derive(Clone, Copy)]
-struct FormatTrait {
+struct FormatTraitNames {
     /// e.g. `sym::Display`
     name: Symbol,
     /// `f` in `fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {}`
@@ -99,7 +101,7 @@ struct FormatTrait {
 #[derive(Default)]
 pub struct FormatImpl {
     // Whether we are inside Display or Debug trait impl - None for neither
-    format_trait_impl: Option<FormatTrait>,
+    format_trait_impl: Option<FormatTraitNames>,
 }
 
 impl FormatImpl {
@@ -161,43 +163,57 @@ fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
     }
 }
 
-fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTrait) {
+fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTraitNames) {
     // Check each arg in format calls - do we ever use Display on self (directly or via deref)?
-    if_chain! {
-        if let Some(outer_macro) = root_macro_call_first_node(cx, expr);
-        if let macro_def_id = outer_macro.def_id;
-        if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, outer_macro.expn);
-        if is_format_macro(cx, macro_def_id);
-        then {
-            for arg in format_args.args {
-                if arg.format.r#trait != impl_trait.name {
-                    continue;
+    if let Some(outer_macro) = root_macro_call_first_node(cx, expr)
+        && let macro_def_id = outer_macro.def_id
+        && is_format_macro(cx, macro_def_id)
+    {
+        find_format_args(cx, expr, outer_macro.expn, |format_args| {
+            for piece in &format_args.template {
+                if let FormatArgsPiece::Placeholder(placeholder) = piece
+                    && let trait_name = match placeholder.format_trait {
+                        FormatTrait::Display => sym::Display,
+                        FormatTrait::Debug => sym::Debug,
+                        FormatTrait::LowerExp => sym!(LowerExp),
+                        FormatTrait::UpperExp => sym!(UpperExp),
+                        FormatTrait::Octal => sym!(Octal),
+                        FormatTrait::Pointer => sym::Pointer,
+                        FormatTrait::Binary => sym!(Binary),
+                        FormatTrait::LowerHex => sym!(LowerHex),
+                        FormatTrait::UpperHex => sym!(UpperHex),
+                    }
+                    && trait_name == impl_trait.name
+                    && let Ok(index) = placeholder.argument.index
+                    && let Some(arg) = format_args.arguments.all_args().get(index)
+                    && let Ok(arg_expr) = find_format_arg_expr(expr, arg)
+                {
+                    check_format_arg_self(cx, expr.span, arg_expr, impl_trait);
                 }
-                check_format_arg_self(cx, expr, &arg, impl_trait);
             }
-        }
+        });
     }
 }
 
-fn check_format_arg_self(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &FormatArg<'_>, impl_trait: FormatTrait) {
+fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_trait: FormatTraitNames) {
     // Handle multiple dereferencing of references e.g. &&self
     // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
     // Since the argument to fmt is itself a reference: &self
-    let reference = peel_ref_operators(cx, arg.param.value);
+    let reference = peel_ref_operators(cx, arg);
     let map = cx.tcx.hir();
     // Is the reference self?
     if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
-        let FormatTrait { name, .. } = impl_trait;
+        let FormatTraitNames { name, .. } = impl_trait;
         span_lint(
             cx,
             RECURSIVE_FORMAT_IMPL,
-            expr.span,
+            span,
             &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
         );
     }
 }
 
-fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTrait) {
+fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) {
     if_chain! {
         if let Some(macro_call) = root_macro_call_first_node(cx, expr);
         if let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id);
@@ -227,7 +243,7 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait:
     }
 }
 
-fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTrait> {
+fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTraitNames> {
     if_chain! {
         if impl_item.ident.name == sym::fmt;
         if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
@@ -241,7 +257,7 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio
                 .and_then(|param| param.pat.simple_ident())
                 .map(|ident| ident.name);
 
-            Some(FormatTrait {
+            Some(FormatTraitNames {
                 name,
                 formatter_name,
             })
diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs
index a22285058d4..92d21bb8932 100644
--- a/clippy_lints/src/methods/expect_fun_call.rs
+++ b/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
+use clippy_utils::macros::{find_format_args, format_args_inputs_span, root_macro_call_first_node};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
@@ -136,18 +136,19 @@ pub(super) fn check<'tcx>(
         if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) {
             return;
         }
-        let Some(format_args) = FormatArgsExpn::find_nested(cx, arg_root, macro_call.expn) else { return };
-        let span = format_args.inputs_span();
-        let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
-        span_lint_and_sugg(
-            cx,
-            EXPECT_FUN_CALL,
-            span_replace_word,
-            &format!("use of `{name}` followed by a function call"),
-            "try this",
-            format!("unwrap_or_else({closure_args} panic!({sugg}))"),
-            applicability,
-        );
+        find_format_args(cx, arg_root, macro_call.expn, |format_args| {
+            let span = format_args_inputs_span(format_args);
+            let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
+            span_lint_and_sugg(
+                cx,
+                EXPECT_FUN_CALL,
+                span_replace_word,
+                &format!("use of `{name}` followed by a function call"),
+                "try this",
+                format!("unwrap_or_else({closure_args} panic!({sugg}))"),
+                applicability,
+            );
+        });
         return;
     }
 
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 2e839fdf472..f4af00599cd 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -33,7 +33,6 @@ extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_middle;
 extern crate rustc_mir_dataflow;
-extern crate rustc_parse_format;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs
index b03e0d4a1ca..62d388a5ece 100644
--- a/clippy_utils/src/macros.rs
+++ b/clippy_utils/src/macros.rs
@@ -1,24 +1,16 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
-use crate::source::snippet_opt;
 use crate::visitors::{for_each_expr, Descend};
 
 use arrayvec::ArrayVec;
-use itertools::{izip, Either, Itertools};
-use rustc_ast::ast::LitKind;
 use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, LangItem, Node, QPath, TyKind};
-use rustc_lexer::unescape::unescape_literal;
-use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
+use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
-use rustc_parse_format::{self as rpf, Alignment};
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
-use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Pos, Span, SpanData, Symbol};
+use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol};
 use std::cell::RefCell;
-use std::iter::{once, zip};
 use std::ops::ControlFlow;
 use std::sync::atomic::{AtomicBool, Ordering};
 
@@ -226,11 +218,11 @@ pub enum PanicExpn<'a> {
     /// A single argument that implements `Display` - `panic!("{}", object)`
     Display(&'a Expr<'a>),
     /// Anything else - `panic!("error {}: {}", a, b)`
-    Format(FormatArgsExpn<'a>),
+    Format(&'a Expr<'a>),
 }
 
 impl<'a> PanicExpn<'a> {
-    pub fn parse(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Self> {
+    pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
         let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else { return None };
         let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None };
         let result = match path.segments.last().unwrap().ident.as_str() {
@@ -240,7 +232,7 @@ impl<'a> PanicExpn<'a> {
                 let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None };
                 Self::Display(e)
             },
-            "panic_fmt" => Self::Format(FormatArgsExpn::parse(cx, arg)?),
+            "panic_fmt" => Self::Format(arg),
             // Since Rust 1.52, `assert_{eq,ne}` macros expand to use:
             // `core::panicking::assert_failed(.., left_val, right_val, None | Some(format_args!(..)));`
             "assert_failed" => {
@@ -252,7 +244,7 @@ impl<'a> PanicExpn<'a> {
                 // `msg_arg` is either `None` (no custom message) or `Some(format_args!(..))` (custom message)
                 let msg_arg = &rest[2];
                 match msg_arg.kind {
-                    ExprKind::Call(_, [fmt_arg]) => Self::Format(FormatArgsExpn::parse(cx, fmt_arg)?),
+                    ExprKind::Call(_, [fmt_arg]) => Self::Format(fmt_arg),
                     _ => Self::Empty,
                 }
             },
@@ -304,7 +296,7 @@ fn find_assert_args_inner<'a, const N: usize>(
     let mut args = ArrayVec::new();
     let panic_expn = for_each_expr(expr, |e| {
         if args.is_full() {
-            match PanicExpn::parse(cx, e) {
+            match PanicExpn::parse(e) {
                 Some(expn) => ControlFlow::Break(expn),
                 None => ControlFlow::Continue(Descend::Yes),
             }
@@ -452,6 +444,21 @@ pub fn format_placeholder_format_span(placeholder: &FormatPlaceholder) -> Option
     ))
 }
 
+/// Span covering the format string and values
+///
+/// ```ignore
+/// format("{}.{}", 10, 11)
+/// //     ^^^^^^^^^^^^^^^
+/// ```
+pub fn format_args_inputs_span(format_args: &FormatArgs) -> Span {
+    match format_args.arguments.explicit_args() {
+        [] => format_args.span,
+        [.., last] => format_args
+            .span
+            .to(hygiene::walk_chain(last.expr.span, format_args.span.ctxt())),
+    }
+}
+
 /// Returns the [`Span`] of the value at `index` extended to the previous comma, e.g. for the value
 /// `10`
 ///
@@ -473,251 +480,6 @@ pub fn format_arg_removal_span(format_args: &FormatArgs, index: usize) -> Option
     Some(current.with_lo(prev.hi()))
 }
 
-/// The format string doesn't exist in the HIR, so we reassemble it from source code
-#[derive(Debug)]
-pub struct FormatString {
-    /// Span of the whole format string literal, including `[r#]"`.
-    pub span: Span,
-    /// Snippet of the whole format string literal, including `[r#]"`.
-    pub snippet: String,
-    /// If the string is raw `r"..."`/`r#""#`, how many `#`s does it have on each side.
-    pub style: Option<usize>,
-    /// The unescaped value of the format string, e.g. `"val – {}"` for the literal
-    /// `"val \u{2013} {}"`.
-    pub unescaped: String,
-    /// The format string split by format args like `{..}`.
-    pub parts: Vec<Symbol>,
-}
-
-impl FormatString {
-    fn new(cx: &LateContext<'_>, pieces: &Expr<'_>) -> Option<Self> {
-        // format_args!(r"a {} b \", 1);
-        //
-        // expands to
-        //
-        // ::core::fmt::Arguments::new_v1(&["a ", " b \\"],
-        //      &[::core::fmt::ArgumentV1::new_display(&1)]);
-        //
-        // where `pieces` is the expression `&["a ", " b \\"]`. It has the span of `r"a {} b \"`
-        let span = pieces.span;
-        let snippet = snippet_opt(cx, span)?;
-
-        let (inner, style) = match tokenize(&snippet).next()?.kind {
-            TokenKind::Literal { kind, .. } => {
-                let style = match kind {
-                    LiteralKind::Str { .. } => None,
-                    LiteralKind::RawStr { n_hashes: Some(n), .. } => Some(n.into()),
-                    _ => return None,
-                };
-
-                let start = style.map_or(1, |n| 2 + n);
-                let end = snippet.len() - style.map_or(1, |n| 1 + n);
-
-                (&snippet[start..end], style)
-            },
-            _ => return None,
-        };
-
-        let mode = if style.is_some() {
-            unescape::Mode::RawStr
-        } else {
-            unescape::Mode::Str
-        };
-
-        let mut unescaped = String::with_capacity(inner.len());
-        // Sometimes the original string comes from a macro which accepts a malformed string, such as in a
-        // #[display(""somestring)] attribute (accepted by the `displaythis` crate). Reconstructing the
-        // string from the span will not be possible, so we will just return None here.
-        let mut unparsable = false;
-        unescape_literal(inner, mode, &mut |_, ch| match ch {
-            Ok(ch) => unescaped.push(ch),
-            Err(e) if !e.is_fatal() => (),
-            Err(_) => unparsable = true,
-        });
-        if unparsable {
-            return None;
-        }
-
-        let mut parts = Vec::new();
-        let _: Option<!> = for_each_expr(pieces, |expr| {
-            if let ExprKind::Lit(lit) = &expr.kind
-                && let LitKind::Str(symbol, _) = lit.node
-            {
-                parts.push(symbol);
-            }
-            ControlFlow::Continue(())
-        });
-
-        Some(Self {
-            span,
-            snippet,
-            style,
-            unescaped,
-            parts,
-        })
-    }
-}
-
-struct FormatArgsValues<'tcx> {
-    /// Values passed after the format string and implicit captures. `[1, z + 2, x]` for
-    /// `format!("{x} {} {}", 1, z + 2)`.
-    value_args: Vec<&'tcx Expr<'tcx>>,
-    /// Maps an `rt::v1::Argument::position` or an `rt::v1::Count::Param` to its index in
-    /// `value_args`
-    pos_to_value_index: Vec<usize>,
-    /// Used to check if a value is declared inline & to resolve `InnerSpan`s.
-    format_string_span: SpanData,
-}
-
-impl<'tcx> FormatArgsValues<'tcx> {
-    fn new_empty(format_string_span: SpanData) -> Self {
-        Self {
-            value_args: Vec::new(),
-            pos_to_value_index: Vec::new(),
-            format_string_span,
-        }
-    }
-
-    fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
-        let mut pos_to_value_index = Vec::new();
-        let mut value_args = Vec::new();
-        let _: Option<!> = for_each_expr(args, |expr| {
-            if expr.span.ctxt() == args.span.ctxt() {
-                // ArgumentV1::new_<format_trait>(<val>)
-                // ArgumentV1::from_usize(<val>)
-                if let ExprKind::Call(callee, [val]) = expr.kind
-                    && let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind
-                    && let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind
-                {
-                    let val_idx = if val.span.ctxt() == expr.span.ctxt()
-                        && let ExprKind::Field(_, field) = val.kind
-                        && let Ok(idx) = field.name.as_str().parse()
-                    {
-                        // tuple index
-                        idx
-                    } else {
-                        // assume the value expression is passed directly
-                        pos_to_value_index.len()
-                    };
-
-                    pos_to_value_index.push(val_idx);
-                }
-                ControlFlow::Continue(Descend::Yes)
-            } else {
-                // assume that any expr with a differing span is a value
-                value_args.push(expr);
-                ControlFlow::Continue(Descend::No)
-            }
-        });
-
-        Self {
-            value_args,
-            pos_to_value_index,
-            format_string_span,
-        }
-    }
-}
-
-/// The positions of a format argument's value, precision and width
-///
-/// A position is an index into the second argument of `Arguments::new_v1[_formatted]`
-#[derive(Debug, Default, Copy, Clone)]
-struct ParamPosition {
-    /// The position stored in `rt::v1::Argument::position`.
-    value: usize,
-    /// The position stored in `rt::v1::FormatSpec::width` if it is a `Count::Param`.
-    width: Option<usize>,
-    /// The position stored in `rt::v1::FormatSpec::precision` if it is a `Count::Param`.
-    precision: Option<usize>,
-}
-
-impl<'tcx> Visitor<'tcx> for ParamPosition {
-    fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
-        match field.ident.name {
-            sym::position => {
-                if let ExprKind::Lit(lit) = &field.expr.kind
-                    && let LitKind::Int(pos, _) = lit.node
-                {
-                    self.value = pos as usize;
-                }
-            },
-            sym::precision => {
-                self.precision = parse_count(field.expr);
-            },
-            sym::width => {
-                self.width = parse_count(field.expr);
-            },
-            _ => walk_expr(self, field.expr),
-        }
-    }
-}
-
-fn parse_count(expr: &Expr<'_>) -> Option<usize> {
-    // <::core::fmt::rt::v1::Count>::Param(1usize),
-    if let ExprKind::Call(ctor, [val]) = expr.kind
-        && let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind
-            && path.ident.name == sym::Param
-            && let ExprKind::Lit(lit) = &val.kind
-            && let LitKind::Int(pos, _) = lit.node
-    {
-        Some(pos as usize)
-    } else {
-        None
-    }
-}
-
-/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
-fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
-    if let ExprKind::AddrOf(.., array) = fmt_arg.kind
-        && let ExprKind::Array(specs) = array.kind
-    {
-        Some(specs.iter().map(|spec| {
-            if let ExprKind::Call(f, args) = spec.kind
-                && let ExprKind::Path(QPath::TypeRelative(ty, f)) = f.kind
-                && let TyKind::Path(QPath::LangItem(LangItem::FormatPlaceholder, _, _)) = ty.kind
-                && f.ident.name == sym::new
-                && let [position, _fill, _align, _flags, precision, width] = args
-                && let ExprKind::Lit(position) = &position.kind
-                && let LitKind::Int(position, _) = position.node {
-                    ParamPosition {
-                        value: position as usize,
-                        width: parse_count(width),
-                        precision: parse_count(precision),
-                    }
-            } else {
-                ParamPosition::default()
-            }
-        }))
-    } else {
-        None
-    }
-}
-
-/// `Span::from_inner`, but for `rustc_parse_format`'s `InnerSpan`
-fn span_from_inner(base: SpanData, inner: rpf::InnerSpan) -> Span {
-    Span::new(
-        base.lo + BytePos::from_usize(inner.start),
-        base.lo + BytePos::from_usize(inner.end),
-        base.ctxt,
-        base.parent,
-    )
-}
-
-/// How a format parameter is used in the format string
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum FormatParamKind {
-    /// An implicit parameter , such as `{}` or `{:?}`.
-    Implicit,
-    /// A parameter with an explicit number, e.g. `{1}`, `{0:?}`, or `{:.0$}`
-    Numbered,
-    /// A parameter with an asterisk precision. e.g. `{:.*}`.
-    Starred,
-    /// A named parameter with a named `value_arg`, such as the `x` in `format!("{x}", x = 1)`.
-    Named(Symbol),
-    /// An implicit named parameter, such as the `y` in `format!("{y}")`.
-    NamedInline(Symbol),
-}
-
 /// Where a format parameter is being used in the format string
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum FormatParamUsage {
@@ -729,451 +491,6 @@ pub enum FormatParamUsage {
     Precision,
 }
 
-/// A `FormatParam` is any place in a `FormatArgument` that refers to a supplied value, e.g.
-///
-/// ```
-/// let precision = 2;
-/// format!("{:.precision$}", 0.1234);
-/// ```
-///
-/// has two `FormatParam`s, a [`FormatParamKind::Implicit`] `.kind` with a `.value` of `0.1234`
-/// and a [`FormatParamKind::NamedInline("precision")`] `.kind` with a `.value` of `2`
-#[derive(Debug, Copy, Clone)]
-pub struct FormatParam<'tcx> {
-    /// The expression this parameter refers to.
-    pub value: &'tcx Expr<'tcx>,
-    /// How this parameter refers to its `value`.
-    pub kind: FormatParamKind,
-    /// Where this format param is being used - argument/width/precision
-    pub usage: FormatParamUsage,
-    /// Span of the parameter, may be zero width. Includes the whitespace of implicit parameters.
-    ///
-    /// ```text
-    /// format!("{}, {  }, {0}, {name}", ...);
-    ///          ^    ~~    ~    ~~~~
-    /// ```
-    pub span: Span,
-}
-
-impl<'tcx> FormatParam<'tcx> {
-    fn new(
-        mut kind: FormatParamKind,
-        usage: FormatParamUsage,
-        position: usize,
-        inner: rpf::InnerSpan,
-        values: &FormatArgsValues<'tcx>,
-    ) -> Option<Self> {
-        let value_index = *values.pos_to_value_index.get(position)?;
-        let value = *values.value_args.get(value_index)?;
-        let span = span_from_inner(values.format_string_span, inner);
-
-        // if a param is declared inline, e.g. `format!("{x}")`, the generated expr's span points
-        // into the format string
-        if let FormatParamKind::Named(name) = kind && values.format_string_span.contains(value.span.data()) {
-            kind = FormatParamKind::NamedInline(name);
-        }
-
-        Some(Self {
-            value,
-            kind,
-            usage,
-            span,
-        })
-    }
-}
-
-/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and
-/// [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
-#[derive(Debug, Copy, Clone)]
-pub enum Count<'tcx> {
-    /// Specified with a literal number, stores the value.
-    Is(usize, Span),
-    /// Specified using `$` and `*` syntaxes. The `*` format is still considered to be
-    /// `FormatParamKind::Numbered`.
-    Param(FormatParam<'tcx>),
-    /// Not specified.
-    Implied(Option<Span>),
-}
-
-impl<'tcx> Count<'tcx> {
-    fn new(
-        usage: FormatParamUsage,
-        count: rpf::Count<'_>,
-        position: Option<usize>,
-        inner: Option<rpf::InnerSpan>,
-        values: &FormatArgsValues<'tcx>,
-    ) -> Option<Self> {
-        let span = inner.map(|inner| span_from_inner(values.format_string_span, inner));
-
-        Some(match count {
-            rpf::Count::CountIs(val) => Self::Is(val, span?),
-            rpf::Count::CountIsName(name, _) => Self::Param(FormatParam::new(
-                FormatParamKind::Named(Symbol::intern(name)),
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountIsParam(_) => Self::Param(FormatParam::new(
-                FormatParamKind::Numbered,
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountIsStar(_) => Self::Param(FormatParam::new(
-                FormatParamKind::Starred,
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountImplied => Self::Implied(span),
-        })
-    }
-
-    pub fn is_implied(self) -> bool {
-        matches!(self, Count::Implied(_))
-    }
-
-    pub fn param(self) -> Option<FormatParam<'tcx>> {
-        match self {
-            Count::Param(param) => Some(param),
-            _ => None,
-        }
-    }
-
-    pub fn span(self) -> Option<Span> {
-        match self {
-            Count::Is(_, span) => Some(span),
-            Count::Param(param) => Some(param.span),
-            Count::Implied(span) => span,
-        }
-    }
-}
-
-/// Specification for the formatting of an argument in the format string. See
-/// <https://doc.rust-lang.org/std/fmt/index.html#formatting-parameters> for the precise meanings.
-#[derive(Debug)]
-pub struct FormatSpec<'tcx> {
-    /// Optionally specified character to fill alignment with.
-    pub fill: Option<char>,
-    /// Optionally specified alignment.
-    pub align: Alignment,
-    /// Whether all flag options are set to default (no flags specified).
-    pub no_flags: bool,
-    /// Represents either the maximum width or the integer precision.
-    pub precision: Count<'tcx>,
-    /// The minimum width, will be padded according to `width`/`align`
-    pub width: Count<'tcx>,
-    /// The formatting trait used by the argument, e.g. `sym::Display` for `{}`, `sym::Debug` for
-    /// `{:?}`.
-    pub r#trait: Symbol,
-    pub trait_span: Option<Span>,
-}
-
-impl<'tcx> FormatSpec<'tcx> {
-    fn new(spec: rpf::FormatSpec<'_>, positions: ParamPosition, values: &FormatArgsValues<'tcx>) -> Option<Self> {
-        Some(Self {
-            fill: spec.fill,
-            align: spec.align,
-            no_flags: spec.sign.is_none() && !spec.alternate && !spec.zero_pad && spec.debug_hex.is_none(),
-            precision: Count::new(
-                FormatParamUsage::Precision,
-                spec.precision,
-                positions.precision,
-                spec.precision_span,
-                values,
-            )?,
-            width: Count::new(
-                FormatParamUsage::Width,
-                spec.width,
-                positions.width,
-                spec.width_span,
-                values,
-            )?,
-            r#trait: match spec.ty {
-                "" => sym::Display,
-                "?" => sym::Debug,
-                "o" => sym!(Octal),
-                "x" => sym!(LowerHex),
-                "X" => sym!(UpperHex),
-                "p" => sym::Pointer,
-                "b" => sym!(Binary),
-                "e" => sym!(LowerExp),
-                "E" => sym!(UpperExp),
-                _ => return None,
-            },
-            trait_span: spec
-                .ty_span
-                .map(|span| span_from_inner(values.format_string_span, span)),
-        })
-    }
-
-    /// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`,
-    /// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}`
-    pub fn is_default(&self) -> bool {
-        self.r#trait == sym::Display && self.is_default_for_trait()
-    }
-
-    /// Has no other formatting specifiers than setting the format trait. returns true for `{}`,
-    /// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}`
-    pub fn is_default_for_trait(&self) -> bool {
-        self.width.is_implied() && self.precision.is_implied() && self.align == Alignment::AlignUnknown && self.no_flags
-    }
-}
-
-/// A format argument, such as `{}`, `{foo:?}`.
-#[derive(Debug)]
-pub struct FormatArg<'tcx> {
-    /// The parameter the argument refers to.
-    pub param: FormatParam<'tcx>,
-    /// How to format `param`.
-    pub format: FormatSpec<'tcx>,
-    /// span of the whole argument, `{..}`.
-    pub span: Span,
-}
-
-/// A parsed `format_args!` expansion.
-#[derive(Debug)]
-pub struct FormatArgsExpn<'tcx> {
-    /// The format string literal.
-    pub format_string: FormatString,
-    /// The format arguments, such as `{:?}`.
-    pub args: Vec<FormatArg<'tcx>>,
-    /// Has an added newline due to `println!()`/`writeln!()`/etc. The last format string part will
-    /// include this added newline.
-    pub newline: bool,
-    /// Spans of the commas between the format string and explicit values, excluding any trailing
-    /// comma
-    ///
-    /// ```ignore
-    /// format!("..", 1, 2, 3,)
-    /// //          ^  ^  ^
-    /// ```
-    comma_spans: Vec<Span>,
-    /// Explicit values passed after the format string, ignoring implicit captures. `[1, z + 2]` for
-    /// `format!("{x} {} {y}", 1, z + 2)`.
-    explicit_values: Vec<&'tcx Expr<'tcx>>,
-}
-
-impl<'tcx> FormatArgsExpn<'tcx> {
-    /// Gets the spans of the commas inbetween the format string and explicit args, not including
-    /// any trailing comma
-    ///
-    /// ```ignore
-    /// format!("{} {}", a, b)
-    /// //             ^  ^
-    /// ```
-    ///
-    /// Ensures that the format string and values aren't coming from a proc macro that sets the
-    /// output span to that of its input
-    fn comma_spans(cx: &LateContext<'_>, explicit_values: &[&Expr<'_>], fmt_span: Span) -> Option<Vec<Span>> {
-        // `format!("{} {} {c}", "one", "two", c = "three")`
-        //                       ^^^^^  ^^^^^      ^^^^^^^
-        let value_spans = explicit_values
-            .iter()
-            .map(|val| hygiene::walk_chain(val.span, fmt_span.ctxt()));
-
-        // `format!("{} {} {c}", "one", "two", c = "three")`
-        //                     ^^     ^^     ^^^^^^
-        let between_spans = once(fmt_span)
-            .chain(value_spans)
-            .tuple_windows()
-            .map(|(start, end)| start.between(end));
-
-        let mut comma_spans = Vec::new();
-        for between_span in between_spans {
-            let mut offset = 0;
-            let mut seen_comma = false;
-
-            for token in tokenize(&snippet_opt(cx, between_span)?) {
-                match token.kind {
-                    TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {},
-                    TokenKind::Comma if !seen_comma => {
-                        seen_comma = true;
-
-                        let base = between_span.data();
-                        comma_spans.push(Span::new(
-                            base.lo + BytePos(offset),
-                            base.lo + BytePos(offset + 1),
-                            base.ctxt,
-                            base.parent,
-                        ));
-                    },
-                    // named arguments, `start_val, name = end_val`
-                    //                            ^^^^^^^^^ between_span
-                    TokenKind::Ident | TokenKind::Eq if seen_comma => {},
-                    // An unexpected token usually indicates the format string or a value came from a proc macro output
-                    // that sets the span of its output to an input, e.g. `println!(some_proc_macro!("input"), ..)` that
-                    // emits a string literal with the span set to that of `"input"`
-                    _ => return None,
-                }
-                offset += token.len;
-            }
-
-            if !seen_comma {
-                return None;
-            }
-        }
-
-        Some(comma_spans)
-    }
-
-    pub fn parse(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<Self> {
-        let macro_name = macro_backtrace(expr.span)
-            .map(|macro_call| cx.tcx.item_name(macro_call.def_id))
-            .find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?;
-        let newline = macro_name == sym::format_args_nl;
-
-        // ::core::fmt::Arguments::new_const(pieces)
-        // ::core::fmt::Arguments::new_v1(pieces, args)
-        // ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
-        if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind
-            && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
-            && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
-            && matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted")
-        {
-            let format_string = FormatString::new(cx, pieces)?;
-
-            let mut parser = rpf::Parser::new(
-                &format_string.unescaped,
-                format_string.style,
-                Some(format_string.snippet.clone()),
-                // `format_string.unescaped` does not contain the appended newline
-                false,
-                rpf::ParseMode::Format,
-            );
-
-            let parsed_args = parser
-                .by_ref()
-                .filter_map(|piece| match piece {
-                    rpf::Piece::NextArgument(a) => Some(a),
-                    rpf::Piece::String(_) => None,
-                })
-                .collect_vec();
-            if !parser.errors.is_empty() {
-                return None;
-            }
-
-            let positions = if let Some(fmt_arg) = rest.get(1) {
-                // If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse
-                // them.
-
-                Either::Left(parse_rt_fmt(fmt_arg)?)
-            } else {
-                // If no format specs are given, the positions are in the given order and there are
-                // no `precision`/`width`s to consider.
-
-                Either::Right((0..).map(|n| ParamPosition {
-                    value: n,
-                    width: None,
-                    precision: None,
-                }))
-            };
-
-            let values = if let Some(args) = rest.first() {
-                FormatArgsValues::new(args, format_string.span.data())
-            } else {
-                FormatArgsValues::new_empty(format_string.span.data())
-            };
-
-            let args = izip!(positions, parsed_args, parser.arg_places)
-                .map(|(position, parsed_arg, arg_span)| {
-                    Some(FormatArg {
-                        param: FormatParam::new(
-                            match parsed_arg.position {
-                                rpf::Position::ArgumentImplicitlyIs(_) => FormatParamKind::Implicit,
-                                rpf::Position::ArgumentIs(_) => FormatParamKind::Numbered,
-                                // NamedInline is handled by `FormatParam::new()`
-                                rpf::Position::ArgumentNamed(name) => FormatParamKind::Named(Symbol::intern(name)),
-                            },
-                            FormatParamUsage::Argument,
-                            position.value,
-                            parsed_arg.position_span,
-                            &values,
-                        )?,
-                        format: FormatSpec::new(parsed_arg.format, position, &values)?,
-                        span: span_from_inner(values.format_string_span, arg_span),
-                    })
-                })
-                .collect::<Option<Vec<_>>>()?;
-
-            let mut explicit_values = values.value_args;
-            // remove values generated for implicitly captured vars
-            let len = explicit_values
-                .iter()
-                .take_while(|val| !format_string.span.contains(val.span))
-                .count();
-            explicit_values.truncate(len);
-
-            let comma_spans = Self::comma_spans(cx, &explicit_values, format_string.span)?;
-
-            Some(Self {
-                format_string,
-                args,
-                newline,
-                comma_spans,
-                explicit_values,
-            })
-        } else {
-            None
-        }
-    }
-
-    pub fn find_nested(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expn_id: ExpnId) -> Option<Self> {
-        for_each_expr(expr, |e| {
-            let e_ctxt = e.span.ctxt();
-            if e_ctxt == expr.span.ctxt() {
-                ControlFlow::Continue(Descend::Yes)
-            } else if e_ctxt.outer_expn().is_descendant_of(expn_id) {
-                if let Some(args) = FormatArgsExpn::parse(cx, e) {
-                    ControlFlow::Break(args)
-                } else {
-                    ControlFlow::Continue(Descend::No)
-                }
-            } else {
-                ControlFlow::Continue(Descend::No)
-            }
-        })
-    }
-
-    /// Source callsite span of all inputs
-    pub fn inputs_span(&self) -> Span {
-        match *self.explicit_values {
-            [] => self.format_string.span,
-            [.., last] => self
-                .format_string
-                .span
-                .to(hygiene::walk_chain(last.span, self.format_string.span.ctxt())),
-        }
-    }
-
-    /// Get the span of a value expanded to the previous comma, e.g. for the value `10`
-    ///
-    /// ```ignore
-    /// format("{}.{}", 10, 11)
-    /// //            ^^^^
-    /// ```
-    pub fn value_with_prev_comma_span(&self, value_id: HirId) -> Option<Span> {
-        for (comma_span, value) in zip(&self.comma_spans, &self.explicit_values) {
-            if value.hir_id == value_id {
-                return Some(comma_span.to(hygiene::walk_chain(value.span, comma_span.ctxt())));
-            }
-        }
-
-        None
-    }
-
-    /// Iterator of all format params, both values and those referenced by `width`/`precision`s.
-    pub fn params(&'tcx self) -> impl Iterator<Item = FormatParam<'tcx>> {
-        self.args
-            .iter()
-            .flat_map(|arg| [Some(arg.param), arg.format.precision.param(), arg.format.width.param()])
-            .flatten()
-    }
-}
-
 /// A node with a `HirId` and a `Span`
 pub trait HirNode {
     fn hir_id(&self) -> HirId;