Repository: rust-lang/rust-analyzer
Pull request #13799 (2022-12-20 10:32:32)

Rename `checkOnSave` settings to `check`
Now that flychecks can be triggered without saving the setting name doesn't make that much sense anymore. This PR renames it to just `check`, but keeps `checkOnSave` as the enabling setting.

lnicola: Sounds like a good idea to be consistent about this. I don't think the more obscure name is a problem.
Veykril: Oh okay, let's not use flycheck publicly if it clashes with terminology from emacs, that does sound like a bad choice. `externalCheck` sounds good, though maybe `check` itself really would be fine as well.

Patch:
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 08fd4453df..2b24b5c31b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2926,13 +2926,6 @@ impl Type {
         matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
     }
 
-    pub fn is_int_or_uint(&self) -> bool {
-        match self.ty.kind(Interner) {
-            TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)) => true,
-            _ => false,
-        }
-    }
-
     pub fn remove_ref(&self) -> Option<Type> {
         match &self.ty.kind(Interner) {
             TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
diff --git a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/crates/ide-assists/src/handlers/move_format_string_arg.rs
similarity index 84%
rename from crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
rename to crates/ide-assists/src/handlers/move_format_string_arg.rs
index 4f3b6e0c28..11db6ae7f7 100644
--- a/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
+++ b/crates/ide-assists/src/handlers/move_format_string_arg.rs
@@ -10,7 +10,7 @@ use itertools::Itertools;
 use stdx::format_to;
 use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxKind::COMMA, TextRange};
 
-// Assist: extract_expressions_from_format_string
+// Assist: move_format_string_arg
 //
 // Move an expression out of a format string.
 //
@@ -23,7 +23,7 @@ use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxKind::COMMA, TextRange};
 // }
 //
 // fn main() {
-//     print!("{var} {x + 1}$0");
+//     print!("{x + 1}$0");
 // }
 // ```
 // ->
@@ -36,14 +36,11 @@ use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxKind::COMMA, TextRange};
 // }
 //
 // fn main() {
-//     print!("{var} {}"$0, x + 1);
+//     print!("{}"$0, x + 1);
 // }
 // ```
 
-pub(crate) fn extract_expressions_from_format_string(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
+pub(crate) fn move_format_string_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let fmt_string = ctx.find_token_at_offset::<ast::String>()?;
     let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
 
@@ -61,7 +58,7 @@ pub(crate) fn extract_expressions_from_format_string(
 
     acc.add(
         AssistId(
-            "extract_expressions_from_format_string",
+            "move_format_string_arg",
             // if there aren't any expressions, then make the assist a RefactorExtract
             if extracted_args.iter().filter(|f| matches!(f, Arg::Expr(_))).count() == 0 {
                 AssistKind::RefactorExtract
@@ -69,7 +66,7 @@ pub(crate) fn extract_expressions_from_format_string(
                 AssistKind::QuickFix
             },
         ),
-        "Extract format expressions",
+        "Extract format args",
         tt.syntax().text_range(),
         |edit| {
             let fmt_range = fmt_string.syntax().text_range();
@@ -121,14 +118,15 @@ pub(crate) fn extract_expressions_from_format_string(
             let mut placeholder_idx = 1;
 
             for extracted_args in extracted_args {
+                // remove expr from format string
+                args.push_str(", ");
+
                 match extracted_args {
-                    Arg::Expr(s)=> {
-                        args.push_str(", ");
+                    Arg::Ident(s) | Arg::Expr(s) => {
                         // insert arg
                         args.push_str(&s);
                     }
                     Arg::Placeholder => {
-                        args.push_str(", ");
                         // try matching with existing argument
                         match existing_args.next() {
                             Some(ea) => {
@@ -141,7 +139,6 @@ pub(crate) fn extract_expressions_from_format_string(
                             }
                         }
                     }
-                    Arg::Ident(_s) => (),
                 }
             }
 
@@ -174,7 +171,7 @@ macro_rules! print {
     #[test]
     fn multiple_middle_arg() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -195,7 +192,7 @@ fn main() {
     #[test]
     fn single_arg() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -216,7 +213,7 @@ fn main() {
     #[test]
     fn multiple_middle_placeholders_arg() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -237,7 +234,7 @@ fn main() {
     #[test]
     fn multiple_trailing_args() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -258,7 +255,7 @@ fn main() {
     #[test]
     fn improper_commas() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -279,7 +276,7 @@ fn main() {
     #[test]
     fn nested_tt() {
         check_assist(
-            extract_expressions_from_format_string,
+            move_format_string_arg,
             &add_macro_decl(
                 r#"
 fn main() {
@@ -292,29 +289,6 @@ fn main() {
 fn main() {
     print!("My name is {} {}"$0, stringify!(Paperino), x + x)
 }
-"#,
-            ),
-        );
-    }
-
-    #[test]
-    fn extract_only_expressions() {
-        check_assist(
-            extract_expressions_from_format_string,
-            &add_macro_decl(
-                r#"
-fn main() {
-    let var = 1 + 1;
-    print!("foobar {var} {var:?} {x$0 + x}")
-}
-"#,
-            ),
-            &add_macro_decl(
-                r#"
-fn main() {
-    let var = 1 + 1;
-    print!("foobar {var} {var:?} {}"$0, x + x)
-}
 "#,
             ),
         );
diff --git a/crates/ide-assists/src/handlers/replace_arith_op.rs b/crates/ide-assists/src/handlers/replace_arith_op.rs
deleted file mode 100644
index f1ca35cafc..0000000000
--- a/crates/ide-assists/src/handlers/replace_arith_op.rs
+++ /dev/null
@@ -1,226 +0,0 @@
-use ide_db::assists::{AssistId, AssistKind, GroupLabel};
-use syntax::{
-    ast::{self, ArithOp, BinaryOp},
-    AstNode, TextRange,
-};
-
-use crate::assist_context::{AssistContext, Assists};
-
-// Assist: replace_arith_with_checked
-//
-// Replaces arithmetic on integers with the `checked_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.checked_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_checked(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Checked)
-}
-
-// Assist: replace_arith_with_saturating
-//
-// Replaces arithmetic on integers with the `saturating_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.saturating_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_saturating(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Saturating)
-}
-
-// Assist: replace_arith_with_wrapping
-//
-// Replaces arithmetic on integers with the `wrapping_*` equivalent.
-//
-// ```
-// fn main() {
-//   let x = 1 $0+ 2;
-// }
-// ```
-// ->
-// ```
-// fn main() {
-//   let x = 1.wrapping_add(2);
-// }
-// ```
-pub(crate) fn replace_arith_with_wrapping(
-    acc: &mut Assists,
-    ctx: &AssistContext<'_>,
-) -> Option<()> {
-    replace_arith(acc, ctx, ArithKind::Wrapping)
-}
-
-fn replace_arith(acc: &mut Assists, ctx: &AssistContext<'_>, kind: ArithKind) -> Option<()> {
-    let (lhs, op, rhs) = parse_binary_op(ctx)?;
-
-    if !is_primitive_int(ctx, &lhs) || !is_primitive_int(ctx, &rhs) {
-        return None;
-    }
-
-    let start = lhs.syntax().text_range().start();
-    let end = rhs.syntax().text_range().end();
-    let range = TextRange::new(start, end);
-
-    acc.add_group(
-        &GroupLabel("replace_arith".into()),
-        kind.assist_id(),
-        kind.label(),
-        range,
-        |builder| {
-            let method_name = kind.method_name(op);
-
-            builder.replace(range, format!("{lhs}.{method_name}({rhs})"))
-        },
-    )
-}
-
-fn is_primitive_int(ctx: &AssistContext<'_>, expr: &ast::Expr) -> bool {
-    match ctx.sema.type_of_expr(expr) {
-        Some(ty) => ty.adjusted().is_int_or_uint(),
-        _ => false,
-    }
-}
-
-/// Extract the operands of an arithmetic expression (e.g. `1 + 2` or `1.checked_add(2)`)
-fn parse_binary_op(ctx: &AssistContext<'_>) -> Option<(ast::Expr, ArithOp, ast::Expr)> {
-    let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
-
-    let op = match expr.op_kind() {
-        Some(BinaryOp::ArithOp(ArithOp::Add)) => ArithOp::Add,
-        Some(BinaryOp::ArithOp(ArithOp::Sub)) => ArithOp::Sub,
-        Some(BinaryOp::ArithOp(ArithOp::Mul)) => ArithOp::Mul,
-        Some(BinaryOp::ArithOp(ArithOp::Div)) => ArithOp::Div,
-        _ => return None,
-    };
-
-    let lhs = expr.lhs()?;
-    let rhs = expr.rhs()?;
-
-    Some((lhs, op, rhs))
-}
-
-pub(crate) enum ArithKind {
-    Saturating,
-    Wrapping,
-    Checked,
-}
-
-impl ArithKind {
-    fn assist_id(&self) -> AssistId {
-        let s = match self {
-            ArithKind::Saturating => "replace_arith_with_saturating",
-            ArithKind::Checked => "replace_arith_with_checked",
-            ArithKind::Wrapping => "replace_arith_with_wrapping",
-        };
-
-        AssistId(s, AssistKind::RefactorRewrite)
-    }
-
-    fn label(&self) -> &'static str {
-        match self {
-            ArithKind::Saturating => "Replace arithmetic with call to saturating_*",
-            ArithKind::Checked => "Replace arithmetic with call to checked_*",
-            ArithKind::Wrapping => "Replace arithmetic with call to wrapping_*",
-        }
-    }
-
-    fn method_name(&self, op: ArithOp) -> String {
-        let prefix = match self {
-            ArithKind::Checked => "checked_",
-            ArithKind::Wrapping => "wrapping_",
-            ArithKind::Saturating => "saturating_",
-        };
-
-        let suffix = match op {
-            ArithOp::Add => "add",
-            ArithOp::Sub => "sub",
-            ArithOp::Mul => "mul",
-            ArithOp::Div => "div",
-            _ => unreachable!("this function should only be called with +, -, / or *"),
-        };
-        format!("{prefix}{suffix}")
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::tests::check_assist;
-
-    use super::*;
-
-    #[test]
-    fn arith_kind_method_name() {
-        assert_eq!(ArithKind::Saturating.method_name(ArithOp::Add), "saturating_add");
-        assert_eq!(ArithKind::Checked.method_name(ArithOp::Sub), "checked_sub");
-    }
-
-    #[test]
-    fn replace_arith_with_checked_add() {
-        check_assist(
-            replace_arith_with_checked,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.checked_add(2);
-}
-"#,
-        )
-    }
-
-    #[test]
-    fn replace_arith_with_saturating_add() {
-        check_assist(
-            replace_arith_with_saturating,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.saturating_add(2);
-}
-"#,
-        )
-    }
-
-    #[test]
-    fn replace_arith_with_wrapping_add() {
-        check_assist(
-            replace_arith_with_wrapping,
-            r#"
-fn main() {
-    let x = 1 $0+ 2;
-}
-"#,
-            r#"
-fn main() {
-    let x = 1.wrapping_add(2);
-}
-"#,
-        )
-    }
-}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index f7ac9d8fd6..8b1247c640 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -128,7 +128,6 @@ mod handlers {
     mod convert_while_to_loop;
     mod destructure_tuple_binding;
     mod expand_glob_import;
-    mod extract_expressions_from_format_string;
     mod extract_function;
     mod extract_module;
     mod extract_struct_from_enum_variant;
@@ -139,6 +138,7 @@ mod handlers {
     mod flip_binexpr;
     mod flip_comma;
     mod flip_trait_bound;
+    mod move_format_string_arg;
     mod generate_constant;
     mod generate_default_from_enum_variant;
     mod generate_default_from_new;
@@ -186,7 +186,6 @@ mod handlers {
     mod replace_derive_with_manual_impl;
     mod replace_if_let_with_match;
     mod replace_or_with_or_else;
-    mod replace_arith_op;
     mod introduce_named_generic;
     mod replace_let_with_if_let;
     mod replace_qualified_name_with_use;
@@ -231,7 +230,6 @@ mod handlers {
             convert_while_to_loop::convert_while_to_loop,
             destructure_tuple_binding::destructure_tuple_binding,
             expand_glob_import::expand_glob_import,
-            extract_expressions_from_format_string::extract_expressions_from_format_string,
             extract_struct_from_enum_variant::extract_struct_from_enum_variant,
             extract_type_alias::extract_type_alias,
             fix_visibility::fix_visibility,
@@ -266,6 +264,7 @@ mod handlers {
             merge_match_arms::merge_match_arms,
             move_bounds::move_bounds_to_where_clause,
             move_const_to_impl::move_const_to_impl,
+            move_format_string_arg::move_format_string_arg,
             move_guard::move_arm_cond_to_match_guard,
             move_guard::move_guard_to_arm_body,
             move_module_to_file::move_module_to_file,
@@ -294,9 +293,6 @@ mod handlers {
             replace_or_with_or_else::replace_or_with_or_else,
             replace_turbofish_with_explicit_type::replace_turbofish_with_explicit_type,
             replace_qualified_name_with_use::replace_qualified_name_with_use,
-            replace_arith_op::replace_arith_with_wrapping,
-            replace_arith_op::replace_arith_with_checked,
-            replace_arith_op::replace_arith_with_saturating,
             sort_items::sort_items,
             split_import::split_import,
             toggle_ignore::toggle_ignore,
diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs
index f4f37d77d8..3db400604b 100644
--- a/crates/ide-completion/src/completions/postfix.rs
+++ b/crates/ide-completion/src/completions/postfix.rs
@@ -595,12 +595,12 @@ fn main() {
         check_edit(
             "format",
             r#"fn main() { "{some_var:?}".$0 }"#,
-            r#"fn main() { format!("{some_var:?}") }"#,
+            r#"fn main() { format!("{:?}", some_var) }"#,
         );
         check_edit(
             "panic",
             r#"fn main() { "Panic with {a}".$0 }"#,
-            r#"fn main() { panic!("Panic with {a}") }"#,
+            r#"fn main() { panic!("Panic with {}", a) }"#,
         );
         check_edit(
             "println",
diff --git a/crates/ide-completion/src/completions/postfix/format_like.rs b/crates/ide-completion/src/completions/postfix/format_like.rs
index dfcc78e923..d64d6379a9 100644
--- a/crates/ide-completion/src/completions/postfix/format_like.rs
+++ b/crates/ide-completion/src/completions/postfix/format_like.rs
@@ -54,11 +54,7 @@ pub(crate) fn add_format_like_completions(
     if let Ok((out, exprs)) = parse_format_exprs(receiver_text.text()) {
         let exprs = with_placeholders(exprs);
         for (label, macro_name) in KINDS {
-            let snippet = if exprs.is_empty() {
-                format!(r#"{}({})"#, macro_name, out)
-            } else {
-                format!(r#"{}({}, {})"#, macro_name, out, exprs.join(", "))
-            };
+            let snippet = format!(r#"{macro_name}({out}, {})"#, exprs.join(", "));
 
             postfix_snippet(label, macro_name, &snippet).add_to(acc);
         }
@@ -76,9 +72,10 @@ mod tests {
             ("eprintln!", "{}", r#"eprintln!("{}", $1)"#),
             (
                 "log::info!",
-                "{} {ident} {} {2 + 2}",
-                r#"log::info!("{} {ident} {} {}", $1, $2, 2 + 2)"#,
+                "{} {expr} {} {2 + 2}",
+                r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
             ),
+            ("format!", "{expr:?}", r#"format!("{:?}", expr)"#),
         ];
 
         for (kind, input, output) in test_vector {
@@ -88,18 +85,4 @@ mod tests {
             assert_eq!(&snippet, output);
         }
     }
-
-    #[test]
-    fn test_into_suggestion_no_epxrs() {
-        let test_vector = &[
-            ("println!", "{ident}", r#"println!("{ident}")"#),
-            ("format!", "{ident:?}", r#"format!("{ident:?}")"#),
-        ];
-
-        for (kind, input, output) in test_vector {
-            let (parsed_string, _exprs) = parse_format_exprs(input).unwrap();
-            let snippet = format!(r#"{}("{}")"#, kind, parsed_string);
-            assert_eq!(&snippet, output);
-        }
-    }
 }
diff --git a/crates/ide-db/src/syntax_helpers/format_string_exprs.rs b/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
index fcef71fb74..f5f03d70b0 100644
--- a/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
+++ b/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
@@ -140,8 +140,8 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                         output.push_str(trimmed);
                     } else if matches!(state, State::Expr) {
                         extracted_expressions.push(Arg::Expr(trimmed.into()));
-                    } else if matches!(state, State::Ident) {
-                        output.push_str(trimmed);
+                    } else {
+                        extracted_expressions.push(Arg::Ident(trimmed.into()));
                     }
 
                     output.push(chr);
@@ -218,9 +218,9 @@ mod tests {
         let test_vector = &[
             ("no expressions", expect![["no expressions"]]),
             (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
-            ("{expr} is {2 + 2}", expect![["{expr} is {}; 2 + 2"]]),
-            ("{expr:?}", expect![["{expr:?}"]]),
-            ("{expr:1$}", expect![[r"{expr:1\$}"]]),
+            ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
+            ("{expr:?}", expect![["{:?}; expr"]]),
+            ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
             ("{:1$}", expect![[r"{:1\$}; $1"]]),
             ("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
             ("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
@@ -230,8 +230,8 @@ mod tests {
             ("malformed}", expect![["-"]]),
             ("{{correct", expect![["{{correct"]]),
             ("correct}}", expect![["correct}}"]]),
-            ("{correct}}}", expect![["{correct}}}"]]),
-            ("{correct}}}}}", expect![["{correct}}}}}"]]),
+            ("{correct}}}", expect![["{}}}; correct"]]),
+            ("{correct}}}}}", expect![["{}}}}}; correct"]]),
             ("{incorrect}}", expect![["-"]]),
             ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
             ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
@@ -239,7 +239,7 @@ mod tests {
                 "{SomeStruct { val_a: 0, val_b: 1 }}",
                 expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
             ),
-            ("{expr:?} is {2.32f64:.5}", expect![["{expr:?} is {:.5}; 2.32f64"]]),
+            ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
             (
                 "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                 expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
@@ -262,6 +262,8 @@ mod tests {
                 .unwrap()
                 .1,
             vec![
+                Arg::Ident("_ident".to_owned()),
+                Arg::Ident("r#raw_ident".to_owned()),
                 Arg::Expr("expr.obj".to_owned()),
                 Arg::Expr("name {thing: 42}".to_owned()),
                 Arg::Placeholder
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 0f515a6d5c..b97c8106be 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -124,22 +124,23 @@ config_data! {
         /// Unsets `#[cfg(test)]` for the specified crates.
         cargo_unsetTest: Vec<String>     = "[\"core\"]",
 
+        /// Run the check command for diagnostics on save.
+        checkOnSave | checkOnSave_enable: bool                         = "true",
+
         /// Check all targets and tests (`--all-targets`).
-        checkOnSave_allTargets: bool                     = "true",
+        check_allTargets | checkOnSave_allTargets: bool                  = "true",
         /// Cargo command to use for `cargo check`.
-        checkOnSave_command: String                      = "\"check\"",
-        /// Run specified `cargo check` command for diagnostics on save.
-        checkOnSave_enable: bool                         = "true",
+        check_command | checkOnSave_command: String                      = "\"check\"",
         /// Extra arguments for `cargo check`.
-        checkOnSave_extraArgs: Vec<String>               = "[]",
+        check_extraArgs | checkOnSave_extraArgs: Vec<String>             = "[]",
         /// Extra environment variables that will be set when running `cargo check`.
         /// Extends `#rust-analyzer.cargo.extraEnv#`.
-        checkOnSave_extraEnv: FxHashMap<String, String> = "{}",
+        check_extraEnv | checkOnSave_extraEnv: FxHashMap<String, String> = "{}",
         /// List of features to activate. Defaults to
         /// `#rust-analyzer.cargo.features#`.
         ///
         /// Set to `"all"` to pass `--all-features` to Cargo.
-        checkOnSave_features: Option<CargoFeaturesDef>      = "null",
+        check_features | checkOnSave_features: Option<CargoFeaturesDef>  = "null",
         /// Specifies the working directory for running checks.
         /// - "workspace": run checks for workspaces in the corresponding workspaces' root directories.
         // FIXME: Ideally we would support this in some way
@@ -147,16 +148,16 @@ config_data! {
         /// - "root": run checks in the project's root directory.
         /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
         /// is set.
-        checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"",
+        check_invocationLocation | checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"",
         /// Specifies the invocation strategy to use when running the checkOnSave command.
         /// If `per_workspace` is set, the command will be executed for each workspace.
         /// If `once` is set, the command will be executed once.
         /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
         /// is set.
-        checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"",
+        check_invocationStrategy | checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"",
         /// Whether to pass `--no-default-features` to Cargo. Defaults to
         /// `#rust-analyzer.cargo.noDefaultFeatures#`.
-        checkOnSave_noDefaultFeatures: Option<bool>      = "null",
+        check_noDefaultFeatures | checkOnSave_noDefaultFeatures: Option<bool>         = "null",
         /// Override the command rust-analyzer uses instead of `cargo check` for
         /// diagnostics on save. The command is required to output json and
         /// should therefore include `--message-format=json` or a similar option.
@@ -175,14 +176,14 @@ config_data! {
         /// cargo check --workspace --message-format=json --all-targets
         /// ```
         /// .
-        checkOnSave_overrideCommand: Option<Vec<String>> = "null",
+        check_overrideCommand | checkOnSave_overrideCommand: Option<Vec<String>>             = "null",
         /// Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
         ///
         /// Can be a single target, e.g. `"x86_64-unknown-linux-gnu"` or a list of targets, e.g.
         /// `["aarch64-apple-darwin", "x86_64-apple-darwin"]`.
         ///
         /// Aliased as `"checkOnSave.targets"`.
-        checkOnSave_target | checkOnSave_targets: Option<CheckOnSaveTargets>           = "null",
+        check_targets | checkOnSave_targets | checkOnSave_target: Option<CheckOnSaveTargets> = "null",
 
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
@@ -409,9 +410,6 @@ config_data! {
         /// Whether to show `can't find Cargo.toml` error message.
         notifications_cargoTomlNotFound: bool      = "true",
 
-        /// How many worker threads in the main loop. The default `null` means to pick automatically.
-        numThreads: Option<usize> = "null",
-
         /// Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set.
         procMacro_attributes_enable: bool = "true",
         /// Enable support for procedural macros, implies `#rust-analyzer.cargo.buildScripts.enable#`.
@@ -789,9 +787,9 @@ impl Config {
 
     fn validate(&self, error_sink: &mut Vec<(String, serde_json::Error)>) {
         use serde::de::Error;
-        if self.data.checkOnSave_command.is_empty() {
+        if self.data.check_command.is_empty() {
             error_sink.push((
-                "/checkOnSave/command".to_string(),
+                "/check/command".to_string(),
                 serde_json::Error::custom("expected a non-empty string"),
             ));
         }
@@ -1036,7 +1034,7 @@ impl Config {
 
     pub fn check_on_save_extra_env(&self) -> FxHashMap<String, String> {
         let mut extra_env = self.data.cargo_extraEnv.clone();
-        extra_env.extend(self.data.checkOnSave_extraEnv.clone());
+        extra_env.extend(self.data.check_extraEnv.clone());
         extra_env
     }
 
@@ -1148,7 +1146,7 @@ impl Config {
     }
 
     pub fn flycheck(&self) -> FlycheckConfig {
-        match &self.data.checkOnSave_overrideCommand {
+        match &self.data.check_overrideCommand {
             Some(args) if !args.is_empty() => {
                 let mut args = args.clone();
                 let command = args.remove(0);
@@ -1156,13 +1154,13 @@ impl Config {
                     command,
                     args,
                     extra_env: self.check_on_save_extra_env(),
-                    invocation_strategy: match self.data.checkOnSave_invocationStrategy {
+                    invocation_strategy: match self.data.check_invocationStrategy {
                         InvocationStrategy::Once => flycheck::InvocationStrategy::Once,
                         InvocationStrategy::PerWorkspace => {
                             flycheck::InvocationStrategy::PerWorkspace
                         }
                     },
-                    invocation_location: match self.data.checkOnSave_invocationLocation {
+                    invocation_location: match self.data.check_invocationLocation {
                         InvocationLocation::Root => {
                             flycheck::InvocationLocation::Root(self.root_path.clone())
                         }
@@ -1171,42 +1169,42 @@ impl Config {
                 }
             }
             Some(_) | None => FlycheckConfig::CargoCommand {
-                command: self.data.checkOnSave_command.clone(),
+                command: self.data.check_command.clone(),
                 target_triples: self
                     .data
-                    .checkOnSave_target
+                    .check_targets
                     .clone()
                     .and_then(|targets| match &targets.0[..] {
                         [] => None,
                         targets => Some(targets.into()),
                     })
                     .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()),
-                all_targets: self.data.checkOnSave_allTargets,
+                all_targets: self.data.check_allTargets,
                 no_default_features: self
                     .data
-                    .checkOnSave_noDefaultFeatures
+                    .check_noDefaultFeatures
                     .unwrap_or(self.data.cargo_noDefaultFeatures),
                 all_features: matches!(
-                    self.data.checkOnSave_features.as_ref().unwrap_or(&self.data.cargo_features),
+                    self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features),
                     CargoFeaturesDef::All
                 ),
                 features: match self
                     .data
-                    .checkOnSave_features
+                    .check_features
                     .clone()
                     .unwrap_or_else(|| self.data.cargo_features.clone())
                 {
                     CargoFeaturesDef::All => vec![],
                     CargoFeaturesDef::Selected(it) => it,
                 },
-                extra_args: self.data.checkOnSave_extraArgs.clone(),
+                extra_args: self.data.check_extraArgs.clone(),
                 extra_env: self.check_on_save_extra_env(),
             },
         }
     }
 
     pub fn check_on_save(&self) -> bool {
-        self.data.checkOnSave_enable
+        self.data.checkOnSave
     }
 
     pub fn runnables(&self) -> RunnablesConfig {
@@ -1485,10 +1483,6 @@ impl Config {
         }
     }
 
-    pub fn main_loop_num_threads(&self) -> usize {
-        self.data.numThreads.unwrap_or(num_cpus::get_physical().try_into().unwrap_or(1))
-    }
-
     pub fn typing_autoclose_angle(&self) -> bool {
         self.data.typing_autoClosingAngleBrackets_enable
     }
@@ -1869,35 +1863,30 @@ fn get_field<T: DeserializeOwned>(
     alias: Option<&'static str>,
     default: &str,
 ) -> T {
-    let default = serde_json::from_str(default).unwrap();
     // XXX: check alias first, to work-around the VS Code where it pre-fills the
     // defaults instead of sending an empty object.
     alias
         .into_iter()
         .chain(iter::once(field))
-        .find_map(move |field| {
+        .filter_map(move |field| {
             let mut pointer = field.replace('_', "/");
             pointer.insert(0, '/');
-            json.pointer_mut(&pointer).and_then(|it| match serde_json::from_value(it.take()) {
-                Ok(it) => Some(it),
-                Err(e) => {
-                    tracing::warn!("Failed to deserialize config field at {}: {:?}", pointer, e);
-                    error_sink.push((pointer, e));
-                    None
-                }
-            })
+            json.pointer_mut(&pointer)
+                .map(|it| serde_json::from_value(it.take()).map_err(|e| (e, pointer)))
+        })
+        .find(Result::is_ok)
+        .and_then(|res| match res {
+            Ok(it) => Some(it),
+            Err((e, pointer)) => {
+                tracing::warn!("Failed to deserialize config field at {}: {:?}", pointer, e);
+                error_sink.push((pointer, e));
+                None
+            }
         })
-        .unwrap_or(default)
+        .unwrap_or_else(|| serde_json::from_str(default).unwrap())
 }
 
 fn schema(fields: &[(&'static str, &'static str, &[&str], &str)]) -> serde_json::Value {
-    for ((f1, ..), (f2, ..)) in fields.iter().zip(&fields[1..]) {
-        fn key(f: &str) -> &str {
-            f.splitn(2, '_').next().unwrap()
-        }
-        assert!(key(f1) <= key(f2), "wrong field order: {f1:?} {f2:?}");
-    }
-
     let map = fields
         .iter()
         .map(|(field, ty, doc, default)| {
@@ -1971,15 +1960,6 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
             "type": ["null", "array"],
             "items": { "type": "string" },
         },
-        "MergeBehaviorDef" => set! {
-            "type": "string",
-            "enum": ["none", "crate", "module"],
-            "enumDescriptions": [
-                "Do not merge imports at all.",
-                "Merge imports from the same crate into a single `use` statement.",
-                "Merge imports from the same module into a single `use` statement."
-            ],
-        },
         "ExprFillDefaultDef" => set! {
             "type": "string",
             "enum": ["todo", "default"],
diff --git a/crates/rust-analyzer/src/config/patch_old_style.rs b/crates/rust-analyzer/src/config/patch_old_style.rs
index 3b174a7193..de6ac946a6 100644
--- a/crates/rust-analyzer/src/config/patch_old_style.rs
+++ b/crates/rust-analyzer/src/config/patch_old_style.rs
@@ -4,6 +4,9 @@ use serde_json::{json, Value};
 /// This function patches the json config to the new expected keys.
 /// That is we try to load old known config keys here and convert them to the new ones.
 /// See https://github.com/rust-lang/rust-analyzer/pull/12010
+///
+/// We already have an alias system for simple cases, but if we make structural changes
+/// the alias infra fails down.
 pub(super) fn patch_json_for_outdated_configs(json: &mut Value) {
     let copy = json.clone();
 
@@ -105,9 +108,9 @@ pub(super) fn patch_json_for_outdated_configs(json: &mut Value) {
         merge(json, json!({ "cargo": { "features": "all" } }));
     }
 
-    // checkOnSave_allFeatures, checkOnSave_features -> checkOnSave_features
+    // checkOnSave_allFeatures, checkOnSave_features -> check_features
     if let Some(Value::Bool(true)) = copy.pointer("/checkOnSave/allFeatures") {
-        merge(json, json!({ "checkOnSave": { "features": "all" } }));
+        merge(json, json!({ "check": { "features": "all" } }));
     }
 
     // completion_addCallArgumentSnippets completion_addCallParenthesis -> completion_callable_snippets
@@ -121,6 +124,16 @@ pub(super) fn patch_json_for_outdated_configs(json: &mut Value) {
         (_, _) => return,
     };
     merge(json, json!({ "completion": { "callable": {"snippets": res }} }));
+
+    // We need to do this due to the checkOnSave_enable -> checkOnSave change, as that key now can either be an object or a bool
+    // checkOnSave_* -> check_*
+    if let Some(Value::Object(obj)) = copy.pointer("/checkOnSave") {
+        // checkOnSave_enable -> checkOnSave
+        if let Some(b @ Value::Bool(_)) = obj.get("enable") {
+            merge(json, json!({ "checkOnSave": b }));
+        }
+        merge(json, json!({ "check": obj }));
+    }
 }
 
 fn merge(dst: &mut Value, src: Value) {
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index c6f4e9ce07..7f6ced26ce 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -134,7 +134,7 @@ impl GlobalState {
 
         let task_pool = {
             let (sender, receiver) = unbounded();
-            let handle = TaskPool::new_with_threads(sender, config.main_loop_num_threads());
+            let handle = TaskPool::new(sender);
             Handle { handle, receiver }
         };
 
diff --git a/crates/rust-analyzer/src/task_pool.rs b/crates/rust-analyzer/src/task_pool.rs
index 616e449984..aeeb3b7c58 100644
--- a/crates/rust-analyzer/src/task_pool.rs
+++ b/crates/rust-analyzer/src/task_pool.rs
@@ -8,13 +8,12 @@ pub(crate) struct TaskPool<T> {
 }
 
 impl<T> TaskPool<T> {
-    pub(crate) fn new_with_threads(sender: Sender<T>, threads: usize) -> TaskPool<T> {
+    pub(crate) fn new(sender: Sender<T>) -> TaskPool<T> {
         const STACK_SIZE: usize = 8 * 1024 * 1024;
 
         let inner = threadpool::Builder::new()
             .thread_name("Worker".into())
             .thread_stack_size(STACK_SIZE)
-            .num_threads(threads)
             .build();
         TaskPool { sender, inner }
     }
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index d9794e7052..7bdfd4288a 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -109,33 +109,33 @@ Compilation target override (target triple).
 --
 Unsets `#[cfg(test)]` for the specified crates.
 --
-[[rust-analyzer.checkOnSave.allTargets]]rust-analyzer.checkOnSave.allTargets (default: `true`)::
+[[rust-analyzer.checkOnSave]]rust-analyzer.checkOnSave (default: `true`)::
 +
 --
-Check all targets and tests (`--all-targets`).
+Run the check command for diagnostics on save.
 --
-[[rust-analyzer.checkOnSave.command]]rust-analyzer.checkOnSave.command (default: `"check"`)::
+[[rust-analyzer.check.allTargets]]rust-analyzer.check.allTargets (default: `true`)::
 +
 --
-Cargo command to use for `cargo check`.
+Check all targets and tests (`--all-targets`).
 --
-[[rust-analyzer.checkOnSave.enable]]rust-analyzer.checkOnSave.enable (default: `true`)::
+[[rust-analyzer.check.command]]rust-analyzer.check.command (default: `"check"`)::
 +
 --
-Run specified `cargo check` command for diagnostics on save.
+Cargo command to use for `cargo check`.
 --
-[[rust-analyzer.checkOnSave.extraArgs]]rust-analyzer.checkOnSave.extraArgs (default: `[]`)::
+[[rust-analyzer.check.extraArgs]]rust-analyzer.check.extraArgs (default: `[]`)::
 +
 --
 Extra arguments for `cargo check`.
 --
-[[rust-analyzer.checkOnSave.extraEnv]]rust-analyzer.checkOnSave.extraEnv (default: `{}`)::
+[[rust-analyzer.check.extraEnv]]rust-analyzer.check.extraEnv (default: `{}`)::
 +
 --
 Extra environment variables that will be set when running `cargo check`.
 Extends `#rust-analyzer.cargo.extraEnv#`.
 --
-[[rust-analyzer.checkOnSave.features]]rust-analyzer.checkOnSave.features (default: `null`)::
+[[rust-analyzer.check.features]]rust-analyzer.check.features (default: `null`)::
 +
 --
 List of features to activate. Defaults to
@@ -143,7 +143,7 @@ List of features to activate. Defaults to
 
 Set to `"all"` to pass `--all-features` to Cargo.
 --
-[[rust-analyzer.checkOnSave.invocationLocation]]rust-analyzer.checkOnSave.invocationLocation (default: `"workspace"`)::
+[[rust-analyzer.check.invocationLocation]]rust-analyzer.check.invocationLocation (default: `"workspace"`)::
 +
 --
 Specifies the working directory for running checks.
@@ -153,7 +153,7 @@ Specifies the working directory for running checks.
 This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
 is set.
 --
-[[rust-analyzer.checkOnSave.invocationStrategy]]rust-analyzer.checkOnSave.invocationStrategy (default: `"per_workspace"`)::
+[[rust-analyzer.check.invocationStrategy]]rust-analyzer.check.invocationStrategy (default: `"per_workspace"`)::
 +
 --
 Specifies the invocation strategy to use when running the checkOnSave command.
@@ -162,13 +162,13 @@ If `once` is set, the command will be executed once.
 This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
 is set.
 --
-[[rust-analyzer.checkOnSave.noDefaultFeatures]]rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`)::
+[[rust-analyzer.check.noDefaultFeatures]]rust-analyzer.check.noDefaultFeatures (default: `null`)::
 +
 --
 Whether to pass `--no-default-features` to Cargo. Defaults to
 `#rust-analyzer.cargo.noDefaultFeatures#`.
 --
-[[rust-analyzer.checkOnSave.overrideCommand]]rust-analyzer.checkOnSave.overrideCommand (default: `null`)::
+[[rust-analyzer.check.overrideCommand]]rust-analyzer.check.overrideCommand (default: `null`)::
 +
 --
 Override the command rust-analyzer uses instead of `cargo check` for
@@ -190,7 +190,7 @@ cargo check --workspace --message-format=json --all-targets
 ```
 .
 --
-[[rust-analyzer.checkOnSave.target]]rust-analyzer.checkOnSave.target (default: `null`)::
+[[rust-analyzer.check.targets]]rust-analyzer.check.targets (default: `null`)::
 +
 --
 Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.
@@ -619,11 +619,6 @@ Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
 --
 Whether to show `can't find Cargo.toml` error message.
 --
-[[rust-analyzer.numThreads]]rust-analyzer.numThreads (default: `null`)::
-+
---
-How many worker threads in the main loop. The default `null` means to pick automatically.
---
 [[rust-analyzer.procMacro.attributes.enable]]rust-analyzer.procMacro.attributes.enable (default: `true`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index f508dde4f6..56018b9929 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -556,22 +556,22 @@
                         "type": "string"
                     }
                 },
-                "rust-analyzer.checkOnSave.allTargets": {
+                "rust-analyzer.checkOnSave": {
+                    "markdownDescription": "Run the check command for diagnostics on save.",
+                    "default": true,
+                    "type": "boolean"
+                },
+                "rust-analyzer.check.allTargets": {
                     "markdownDescription": "Check all targets and tests (`--all-targets`).",
                     "default": true,
                     "type": "boolean"
                 },
-                "rust-analyzer.checkOnSave.command": {
+                "rust-analyzer.check.command": {
                     "markdownDescription": "Cargo command to use for `cargo check`.",
                     "default": "check",
                     "type": "string"
                 },
-                "rust-analyzer.checkOnSave.enable": {
-                    "markdownDescription": "Run specified `cargo check` command for diagnostics on save.",
-                    "default": true,
-                    "type": "boolean"
-                },
-                "rust-analyzer.checkOnSave.extraArgs": {
+                "rust-analyzer.check.extraArgs": {
                     "markdownDescription": "Extra arguments for `cargo check`.",
                     "default": [],
                     "type": "array",
@@ -579,12 +579,12 @@
                         "type": "string"
                     }
                 },
-                "rust-analyzer.checkOnSave.extraEnv": {
+                "rust-analyzer.check.extraEnv": {
                     "markdownDescription": "Extra environment variables that will be set when running `cargo check`.\nExtends `#rust-analyzer.cargo.extraEnv#`.",
                     "default": {},
                     "type": "object"
                 },
-                "rust-analyzer.checkOnSave.features": {
+                "rust-analyzer.check.features": {
                     "markdownDescription": "List of features to activate. Defaults to\n`#rust-analyzer.cargo.features#`.\n\nSet to `\"all\"` to pass `--all-features` to Cargo.",
                     "default": null,
                     "anyOf": [
@@ -608,7 +608,7 @@
                         }
                     ]
                 },
-                "rust-analyzer.checkOnSave.invocationLocation": {
+                "rust-analyzer.check.invocationLocation": {
                     "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n    This falls back to \"root\" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.",
                     "default": "workspace",
                     "type": "string",
@@ -621,7 +621,7 @@
                         "The command will be executed in the project root."
                     ]
                 },
-                "rust-analyzer.checkOnSave.invocationStrategy": {
+                "rust-analyzer.check.invocationStrategy": {
                     "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.",
                     "default": "per_workspace",
                     "type": "string",
@@ -634,7 +634,7 @@
                         "The command will be executed once."
                     ]
                 },
-                "rust-analyzer.checkOnSave.noDefaultFeatures": {
+                "rust-analyzer.check.noDefaultFeatures": {
                     "markdownDescription": "Whether to pass `--no-default-features` to Cargo. Defaults to\n`#rust-analyzer.cargo.noDefaultFeatures#`.",
                     "default": null,
                     "type": [
@@ -642,7 +642,7 @@
                         "boolean"
                     ]
                 },
-                "rust-analyzer.checkOnSave.overrideCommand": {
+                "rust-analyzer.check.overrideCommand": {
                     "markdownDescription": "Override the command rust-analyzer uses instead of `cargo check` for\ndiagnostics on save. The command is required to output json and\nshould therefore include `--message-format=json` or a similar option.\n\nIf you're changing this because you're using some tool wrapping\nCargo, you might also want to change\n`#rust-analyzer.cargo.buildScripts.overrideCommand#`.\n\nIf there are multiple linked projects, this command is invoked for\neach of them, with the working directory being the project root\n(i.e., the folder containing the `Cargo.toml`).\n\nAn example command would be:\n\n```bash\ncargo check --workspace --message-format=json --all-targets\n```\n.",
                     "default": null,
                     "type": [
@@ -653,7 +653,7 @@
                         "type": "string"
                     }
                 },
-                "rust-analyzer.checkOnSave.target": {
+                "rust-analyzer.check.targets": {
                     "markdownDescription": "Check for specific targets. Defaults to `#rust-analyzer.cargo.target#` if empty.\n\nCan be a single target, e.g. `\"x86_64-unknown-linux-gnu\"` or a list of targets, e.g.\n`[\"aarch64-apple-darwin\", \"x86_64-apple-darwin\"]`.\n\nAliased as `\"checkOnSave.targets\"`.",
                     "default": null,
                     "anyOf": [
@@ -1177,15 +1177,6 @@
                     "default": true,
                     "type": "boolean"
                 },
-                "rust-analyzer.numThreads": {
-                    "markdownDescription": "How many worker threads in the main loop. The default `null` means to pick automatically.",
-                    "default": null,
-                    "type": [
-                        "null",
-                        "integer"
-                    ],
-                    "minimum": 0
-                },
                 "rust-analyzer.procMacro.attributes.enable": {
                     "markdownDescription": "Expand attribute macros. Requires `#rust-analyzer.procMacro.enable#` to be set.",
                     "default": true,


Test patch:
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 210df6999d..80b8c27c7c 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -624,37 +624,6 @@ fn qux(bar: Bar, baz: Baz) {}
     )
 }
 
-#[test]
-fn doctest_extract_expressions_from_format_string() {
-    check_doc_test(
-        "extract_expressions_from_format_string",
-        r#####"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
-macro_rules! print {
-    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-}
-
-fn main() {
-    print!("{var} {x + 1}$0");
-}
-"#####,
-        r#####"
-macro_rules! format_args {
-    ($lit:literal $(tt:tt)*) => { 0 },
-}
-macro_rules! print {
-    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
-}
-
-fn main() {
-    print!("{var} {}"$0, x + 1);
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_extract_function() {
     check_doc_test(
@@ -1734,6 +1703,37 @@ impl S {
     )
 }
 
+#[test]
+fn doctest_move_format_string_arg() {
+    check_doc_test(
+        "move_format_string_arg",
+        r#####"
+macro_rules! format_args {
+    ($lit:literal $(tt:tt)*) => { 0 },
+}
+macro_rules! print {
+    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+}
+
+fn main() {
+    print!("{x + 1}$0");
+}
+"#####,
+        r#####"
+macro_rules! format_args {
+    ($lit:literal $(tt:tt)*) => { 0 },
+}
+macro_rules! print {
+    ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+}
+
+fn main() {
+    print!("{}"$0, x + 1);
+}
+"#####,
+    )
+}
+
 #[test]
 fn doctest_move_from_mod_rs() {
     check_doc_test(
@@ -2066,57 +2066,6 @@ impl Foo for Bar {
     )
 }
 
-#[test]
-fn doctest_replace_arith_with_checked() {
-    check_doc_test(
-        "replace_arith_with_checked",
-        r#####"
-fn main() {
-  let x = 1 $0+ 2;
-}
-"#####,
-        r#####"
-fn main() {
-  let x = 1.checked_add(2);
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_replace_arith_with_saturating() {
-    check_doc_test(
-        "replace_arith_with_saturating",
-        r#####"
-fn main() {
-  let x = 1 $0+ 2;
-}
-"#####,
-        r#####"
-fn main() {
-  let x = 1.saturating_add(2);
-}
-"#####,
-    )
-}
-
-#[test]
-fn doctest_replace_arith_with_wrapping() {
-    check_doc_test(
-        "replace_arith_with_wrapping",
-        r#####"
-fn main() {
-  let x = 1 $0+ 2;
-}
-"#####,
-        r#####"
-fn main() {
-  let x = 1.wrapping_add(2);
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_replace_char_with_string() {
     check_doc_test(