Repository: rust-lang/rust-analyzer
Pull request #17279 (2024-05-22 13:46:18)

fix: Fix format_args lowering passing incorrect parameters to `rustc_parse_format`

Veykril: @bors r+
bors: :pushpin: Commit fd68caf694df382c62e2cdfc32c92b70e51d35d7 has been approved by `Veykril`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust-analyzer) for this repository.

<!-- @bors r=Veykril fd68caf694df382c62e2cdfc32c92b70e51d35d7 -->
<!-- homu: {"type":"Approved","sha":"fd68caf694df382c62e2cdfc32c92b70e51d35d7","approver":"Veykril","queue":"https://bors.rust-lang.org/homu/queue/rust-analyzer"} -->
bors: :hourglass: Testing commit fd68caf694df382c62e2cdfc32c92b70e51d35d7 with merge b0cd4b68037eff44b200d97c02ca69e150787b2d...
<!-- homu: {"type":"BuildStarted","head_sha":"fd68caf694df382c62e2cdfc32c92b70e51d35d7","merge_sha":"b0cd4b68037eff44b200d97c02ca69e150787b2d"} -->
bors: :broken_heart: Test failed - [checks-actions](https://github.com/rust-lang/rust-analyzer/actions/runs/9192590287/job/25282195853)
<!-- homu: {"type":"BuildFailed","builder_url":"https://github.com/rust-lang/rust-analyzer/actions/runs/9192590287/job/25282195853","builder_name":"checks-actions"} -->

Patch:
diff --git a/crates/hir-def/src/attr/builtin.rs b/crates/hir-def/src/attr/builtin.rs
index f4564c94bb..1fba2e2e4d 100644
--- a/crates/hir-def/src/attr/builtin.rs
+++ b/crates/hir-def/src/attr/builtin.rs
@@ -12,6 +12,9 @@ use std::sync::OnceLock;
 
 use rustc_hash::FxHashMap;
 
+/// Ignored attribute namespaces used by tools.
+pub const TOOL_MODULES: &[&str] = &["rustfmt", "clippy"];
+
 pub struct BuiltinAttribute {
     pub name: &'static str,
     pub template: AttributeTemplate,
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index 82f89393ad..c6d9ba6cfe 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -17,7 +17,7 @@ use syntax::{
         self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName,
         RangeItem, SlicePatComponents,
     },
-    AstNode, AstPtr, SyntaxNodePtr,
+    AstNode, AstPtr, AstToken as _, SyntaxNodePtr,
 };
 use triomphe::Arc;
 
@@ -1577,7 +1577,13 @@ impl ExprCollector<'_> {
             });
         });
         let template = f.template();
-        let fmt_snippet = template.as_ref().map(ToString::to_string);
+        let fmt_snippet = template.as_ref().and_then(|it| match it {
+            ast::Expr::Literal(literal) => match literal.kind() {
+                ast::LiteralKind::String(s) => Some(s.text().to_owned()),
+                _ => None,
+            },
+            _ => None,
+        });
         let mut mappings = vec![];
         let fmt = match template.and_then(|it| self.expand_macros_to_string(it)) {
             Some((s, is_direct_literal)) => format_args::parse(
diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs
index b097a721c7..de0fa982c8 100644
--- a/crates/hir-def/src/hir/format_args.rs
+++ b/crates/hir-def/src/hir/format_args.rs
@@ -175,7 +175,13 @@ pub(crate) fn parse(
     mut synth: impl FnMut(Name) -> ExprId,
     mut record_usage: impl FnMut(Name, Option<TextRange>),
 ) -> FormatArgs {
-    let text = s.text_without_quotes();
+    let Ok(text) = s.value() else {
+        return FormatArgs {
+            template: Default::default(),
+            arguments: args.finish(),
+            orphans: vec![],
+        };
+    };
     let str_style = match s.quote_offsets() {
         Some(offsets) => {
             let raw = usize::from(offsets.quotes.0.len()) - 1;
@@ -186,7 +192,7 @@ pub(crate) fn parse(
     };
 
     let mut parser =
-        parse::Parser::new(text, str_style, fmt_snippet, false, parse::ParseMode::Format);
+        parse::Parser::new(&text, str_style, fmt_snippet, false, parse::ParseMode::Format);
 
     let mut pieces = Vec::new();
     while let Some(piece) = parser.next() {
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 497b69889a..a528c4cc69 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -84,14 +84,6 @@ use crate::{
     LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
 };
 
-const PREDEFINED_TOOLS: &[SmolStr] = &[
-    SmolStr::new_static("clippy"),
-    SmolStr::new_static("rustfmt"),
-    SmolStr::new_static("diagnostic"),
-    SmolStr::new_static("miri"),
-    SmolStr::new_static("rust_analyzer"),
-];
-
 /// Contains the results of (early) name resolution.
 ///
 /// A `DefMap` stores the module tree and the definitions that are in scope in every module after
@@ -168,7 +160,7 @@ impl DefMapCrateData {
             fn_proc_macro_mapping: FxHashMap::default(),
             proc_macro_loading_error: None,
             registered_attrs: Vec::new(),
-            registered_tools: PREDEFINED_TOOLS.into(),
+            registered_tools: Vec::new(),
             unstable_features: FxHashSet::default(),
             rustc_coherence_is_core: false,
             no_core: false,
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index 3cb0666edf..eb7f4c05ae 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -10,7 +10,7 @@ use syntax::{ast, SmolStr};
 use triomphe::Arc;
 
 use crate::{
-    attr::builtin::find_builtin_attr_idx,
+    attr::builtin::{find_builtin_attr_idx, TOOL_MODULES},
     db::DefDatabase,
     item_scope::BuiltinShadowMode,
     nameres::path_resolution::ResolveMode,
@@ -82,7 +82,8 @@ impl DefMap {
             let name = name.to_smol_str();
             let pred = |n: &_| *n == name;
 
-            let is_tool = self.data.registered_tools.iter().map(SmolStr::as_str).any(pred);
+            let registered = self.data.registered_tools.iter().map(SmolStr::as_str);
+            let is_tool = TOOL_MODULES.iter().copied().chain(registered).any(pred);
             // FIXME: tool modules can be shadowed by actual modules
             if is_tool {
                 return true;
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 36e3a45889..b68fefc515 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -797,22 +797,19 @@ impl<'a> InferenceTable<'a> {
             })
             .build();
 
-        let b = TyBuilder::trait_ref(self.db, fn_once_trait);
-        if b.remaining() != 2 {
-            return None;
-        }
-        let mut trait_ref = b.push(ty.clone()).push(arg_ty).build();
-
         let projection = {
-            TyBuilder::assoc_type_projection(
-                self.db,
-                output_assoc_type,
-                Some(trait_ref.substitution.clone()),
-            )
-            .build()
+            let b = TyBuilder::subst_for_def(self.db, fn_once_trait, None);
+            if b.remaining() != 2 {
+                return None;
+            }
+            let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
+
+            TyBuilder::assoc_type_projection(self.db, output_assoc_type, Some(fn_once_subst))
+                .build()
         };
 
         let trait_env = self.trait_env.env.clone();
+        let mut trait_ref = projection.trait_ref(self.db);
         let obligation = InEnvironment {
             goal: trait_ref.clone().cast(Interner),
             environment: trait_env.clone(),
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 26a839f0e9..1727cec989 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -570,10 +570,6 @@ impl CallableSig {
         }
     }
 
-    pub fn abi(&self) -> FnAbi {
-        self.abi
-    }
-
     pub fn params(&self) -> &[Ty] {
         &self.params_and_return[0..self.params_and_return.len() - 1]
     }
@@ -896,16 +892,20 @@ where
     Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
 }
 
-pub fn callable_sig_from_fn_trait(
-    self_ty: &Ty,
-    trait_env: Arc<TraitEnvironment>,
+pub fn callable_sig_from_fnonce(
+    mut self_ty: &Ty,
+    env: Arc<TraitEnvironment>,
     db: &dyn HirDatabase,
-) -> Option<(FnTrait, CallableSig)> {
-    let krate = trait_env.krate;
+) -> Option<CallableSig> {
+    if let Some((ty, _, _)) = self_ty.as_reference() {
+        // This will happen when it implements fn or fn mut, since we add a autoborrow adjustment
+        self_ty = ty;
+    }
+    let krate = env.krate;
     let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
     let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
 
-    let mut table = InferenceTable::new(db, trait_env.clone());
+    let mut table = InferenceTable::new(db, env);
     let b = TyBuilder::trait_ref(db, fn_once_trait);
     if b.remaining() != 2 {
         return None;
@@ -915,56 +915,23 @@ pub fn callable_sig_from_fn_trait(
     // - Self: FnOnce<?args_ty>
     // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
     let args_ty = table.new_type_var();
-    let mut trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
+    let trait_ref = b.push(self_ty.clone()).push(args_ty.clone()).build();
     let projection = TyBuilder::assoc_type_projection(
         db,
         output_assoc_type,
         Some(trait_ref.substitution.clone()),
     )
     .build();
+    table.register_obligation(trait_ref.cast(Interner));
+    let ret_ty = table.normalize_projection_ty(projection);
 
-    let block = trait_env.block;
-    let trait_env = trait_env.env.clone();
-    let obligation =
-        InEnvironment { goal: trait_ref.clone().cast(Interner), environment: trait_env.clone() };
-    let canonical = table.canonicalize(obligation.clone());
-    if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
-        table.register_obligation(obligation.goal);
-        let return_ty = table.normalize_projection_ty(projection);
-        for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
-            let fn_x_trait = fn_x.get_id(db, krate)?;
-            trait_ref.trait_id = to_chalk_trait_id(fn_x_trait);
-            let obligation: chalk_ir::InEnvironment<chalk_ir::Goal<Interner>> = InEnvironment {
-                goal: trait_ref.clone().cast(Interner),
-                environment: trait_env.clone(),
-            };
-            let canonical = table.canonicalize(obligation.clone());
-            if db.trait_solve(krate, block, canonical.cast(Interner)).is_some() {
-                let ret_ty = table.resolve_completely(return_ty);
-                let args_ty = table.resolve_completely(args_ty);
-                let params = args_ty
-                    .as_tuple()?
-                    .iter(Interner)
-                    .map(|it| it.assert_ty_ref(Interner))
-                    .cloned()
-                    .collect();
-
-                return Some((
-                    fn_x,
-                    CallableSig::from_params_and_return(
-                        params,
-                        ret_ty,
-                        false,
-                        Safety::Safe,
-                        FnAbi::RustCall,
-                    ),
-                ));
-            }
-        }
-        unreachable!("It should at least implement FnOnce at this point");
-    } else {
-        None
-    }
+    let ret_ty = table.resolve_completely(ret_ty);
+    let args_ty = table.resolve_completely(args_ty);
+
+    let params =
+        args_ty.as_tuple()?.iter(Interner).map(|it| it.assert_ty_ref(Interner)).cloned().collect();
+
+    Some(CallableSig::from_params_and_return(params, ret_ty, false, Safety::Safe, FnAbi::RustCall))
 }
 
 struct PlaceholderCollector<'db> {
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 02f2cd7615..930bc7df5e 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -1,6 +1,5 @@
 //! Trait solving using Chalk.
 
-use core::fmt;
 use std::env::var;
 
 use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
@@ -210,25 +209,7 @@ pub enum FnTrait {
     Fn,
 }
 
-impl fmt::Display for FnTrait {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            FnTrait::FnOnce => write!(f, "FnOnce"),
-            FnTrait::FnMut => write!(f, "FnMut"),
-            FnTrait::Fn => write!(f, "Fn"),
-        }
-    }
-}
-
 impl FnTrait {
-    pub const fn function_name(&self) -> &'static str {
-        match self {
-            FnTrait::FnOnce => "call_once",
-            FnTrait::FnMut => "call_mut",
-            FnTrait::Fn => "call",
-        }
-    }
-
     const fn lang_item(self) -> LangItem {
         match self {
             FnTrait::FnOnce => LangItem::FnOnce,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 82d2bbb6cf..85f33a10fc 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,7 +35,7 @@ pub mod term_search;
 
 mod display;
 
-use std::{mem::discriminant, ops::ControlFlow};
+use std::{iter, mem::discriminant, ops::ControlFlow};
 
 use arrayvec::ArrayVec;
 use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
@@ -52,6 +52,7 @@ use hir_def::{
     path::ImportAlias,
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
+    src::HasSource as _,
     AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId,
     EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule,
     ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, MacroExpander,
@@ -140,7 +141,7 @@ pub use {
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
         layout::LayoutError,
         mir::{MirEvalError, MirLowerError},
-        FnAbi, PointerCast, Safety,
+        PointerCast, Safety,
     },
     // FIXME: Properly encapsulate mir
     hir_ty::{mir, Interner as ChalkTyInterner},
@@ -1964,7 +1965,7 @@ impl Function {
             .enumerate()
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
+                Param { func: self, ty, idx }
             })
             .collect()
     }
@@ -1990,7 +1991,7 @@ impl Function {
             .skip(skip)
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
+                Param { func: self, ty, idx }
             })
             .collect()
     }
@@ -2036,7 +2037,7 @@ impl Function {
             .skip(skip)
             .map(|(idx, ty)| {
                 let ty = Type { env: environment.clone(), ty: ty.clone() };
-                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
+                Param { func: self, ty, idx }
             })
             .collect()
     }
@@ -2166,24 +2167,17 @@ impl From<hir_ty::Mutability> for Access {
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Param {
-    func: Callee,
+    func: Function,
     /// The index in parameter list, including self parameter.
     idx: usize,
     ty: Type,
 }
 
 impl Param {
-    pub fn parent_fn(&self) -> Option<Function> {
-        match self.func {
-            Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
-            _ => None,
-        }
+    pub fn parent_fn(&self) -> Function {
+        self.func
     }
 
-    // pub fn parent_closure(&self) -> Option<Closure> {
-    //     self.func.as_ref().right().cloned()
-    // }
-
     pub fn index(&self) -> usize {
         self.idx
     }
@@ -2197,11 +2191,7 @@ impl Param {
     }
 
     pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
-        let parent = match self.func {
-            Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
-            Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
-            _ => return None,
-        };
+        let parent = DefWithBodyId::FunctionId(self.func.into());
         let body = db.body(parent);
         if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
             Some(Local { parent, binding_id: self_param })
@@ -2215,45 +2205,18 @@ impl Param {
     }
 
     pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
-        self.source(db).and_then(|p| p.value.right()?.pat())
+        self.source(db).and_then(|p| p.value.pat())
     }
 
-    pub fn source(
-        &self,
-        db: &dyn HirDatabase,
-    ) -> Option<InFile<Either<ast::SelfParam, ast::Param>>> {
-        match self.func {
-            Callee::Def(CallableDefId::FunctionId(func)) => {
-                let InFile { file_id, value } = Function { id: func }.source(db)?;
-                let params = value.param_list()?;
-                if let Some(self_param) = params.self_param() {
-                    if let Some(idx) = self.idx.checked_sub(1) {
-                        params.params().nth(idx).map(Either::Right)
-                    } else {
-                        Some(Either::Left(self_param))
-                    }
-                } else {
-                    params.params().nth(self.idx).map(Either::Right)
-                }
-                .map(|value| InFile { file_id, value })
-            }
-            Callee::Closure(closure, _) => {
-                let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
-                let (_, source_map) = db.body_with_source_map(owner);
-                let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
-                let root = db.parse_or_expand(file_id);
-                match value.to_node(&root) {
-                    ast::Expr::ClosureExpr(it) => it
-                        .param_list()?
-                        .params()
-                        .nth(self.idx)
-                        .map(Either::Right)
-                        .map(|value| InFile { file_id: ast.file_id, value }),
-                    _ => None,
-                }
-            }
-            _ => None,
+    pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
+        let InFile { file_id, value } = self.func.source(db)?;
+        let params = value.param_list()?;
+        if params.self_param().is_some() {
+            params.params().nth(self.idx.checked_sub(params.self_param().is_some() as usize)?)
+        } else {
+            params.params().nth(self.idx)
         }
+        .map(|value| InFile { file_id, value })
     }
 }
 
@@ -3409,21 +3372,34 @@ impl BuiltinAttr {
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct ToolModule {
-    krate: CrateId,
+    krate: Option<CrateId>,
     idx: u32,
 }
 
 impl ToolModule {
+    // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
     pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
-        let krate = krate.id;
+        if let builtin @ Some(_) = Self::builtin(name) {
+            return builtin;
+        }
         let idx =
-            db.crate_def_map(krate).registered_tools().iter().position(|it| it == name)? as u32;
-        Some(ToolModule { krate, idx })
+            db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)? as u32;
+        Some(ToolModule { krate: Some(krate.id), idx })
+    }
+
+    fn builtin(name: &str) -> Option<Self> {
+        hir_def::attr::builtin::TOOL_MODULES
+            .iter()
+            .position(|&tool| tool == name)
+            .map(|idx| ToolModule { krate: None, idx: idx as u32 })
     }
 
     pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
         // FIXME: Return a `Name` here
-        db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone()
+        match self.krate {
+            Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx as usize].clone(),
+            None => SmolStr::new(hir_def::attr::builtin::TOOL_MODULES[self.idx as usize]),
+        }
     }
 }
 
@@ -4316,37 +4292,27 @@ impl Type {
     }
 
     pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
+        let mut the_ty = &self.ty;
         let callee = match self.ty.kind(Interner) {
-            TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
+            TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
+                the_ty = ty;
+                Callee::Closure(ty.as_closure().unwrap())
+            }
+            TyKind::Closure(id, _) => Callee::Closure(*id),
             TyKind::Function(_) => Callee::FnPtr,
             TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
-            kind => {
-                // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
-                let (ty, kind) = if let TyKind::Ref(_, _, ty) = kind {
-                    (ty, ty.kind(Interner))
-                } else {
-                    (&self.ty, kind)
-                };
-                if let TyKind::Closure(closure, subst) = kind {
-                    let sig = ty.callable_sig(db)?;
-                    return Some(Callable {
-                        ty: self.clone(),
-                        sig,
-                        callee: Callee::Closure(*closure, subst.clone()),
-                        is_bound_method: false,
-                    });
-                }
-                let (fn_trait, sig) = hir_ty::callable_sig_from_fn_trait(ty, self.env.clone(), db)?;
+            _ => {
+                let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
                 return Some(Callable {
                     ty: self.clone(),
                     sig,
-                    callee: Callee::FnImpl(fn_trait),
+                    callee: Callee::Other,
                     is_bound_method: false,
                 });
             }
         };
 
-        let sig = self.ty.callable_sig(db)?;
+        let sig = the_ty.callable_sig(db)?;
         Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
     }
 
@@ -4963,39 +4929,37 @@ pub struct Callable {
     sig: CallableSig,
     callee: Callee,
     /// Whether this is a method that was called with method call syntax.
-    is_bound_method: bool,
+    pub(crate) is_bound_method: bool,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Debug)]
 enum Callee {
     Def(CallableDefId),
-    Closure(ClosureId, Substitution),
+    Closure(ClosureId),
     FnPtr,
-    FnImpl(FnTrait),
+    Other,
 }
 
 pub enum CallableKind {
     Function(Function),
     TupleStruct(Struct),
     TupleEnumVariant(Variant),
-    Closure(Closure),
+    Closure,
     FnPtr,
-    FnImpl(FnTrait),
+    /// Some other type that implements `FnOnce`.
+    Other,
 }
 
 impl Callable {
     pub fn kind(&self) -> CallableKind {
+        use Callee::*;
         match self.callee {
-            Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
-            Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
-            Callee::Def(CallableDefId::EnumVariantId(it)) => {
-                CallableKind::TupleEnumVariant(it.into())
-            }
-            Callee::Closure(id, ref subst) => {
-                CallableKind::Closure(Closure { id, subst: subst.clone() })
-            }
-            Callee::FnPtr => CallableKind::FnPtr,
-            Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
+            Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
+            Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
+            Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
+            Closure(_) => CallableKind::Closure,
+            FnPtr => CallableKind::FnPtr,
+            Other => CallableKind::Other,
         }
     }
     pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
@@ -5009,15 +4973,43 @@ impl Callable {
     pub fn n_params(&self) -> usize {
         self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
     }
-    pub fn params(&self) -> Vec<Param> {
-        self.sig
+    pub fn params(
+        &self,
+        db: &dyn HirDatabase,
+    ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
+        let types = self
+            .sig
             .params()
             .iter()
-            .enumerate()
             .skip(if self.is_bound_method { 1 } else { 0 })
-            .map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
-            .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
-            .collect()
+            .map(|ty| self.ty.derived(ty.clone()));
+        let map_param = |it: ast::Param| it.pat().map(Either::Right);
+        let patterns = match self.callee {
+            Callee::Def(CallableDefId::FunctionId(func)) => {
+                let src = func.lookup(db.upcast()).source(db.upcast());
+                src.value.param_list().map(|param_list| {
+                    param_list
+                        .self_param()
+                        .map(|it| Some(Either::Left(it)))
+                        .filter(|_| !self.is_bound_method)
+                        .into_iter()
+                        .chain(param_list.params().map(map_param))
+                })
+            }
+            Callee::Closure(closure_id) => match closure_source(db, closure_id) {
+                Some(src) => src.param_list().map(|param_list| {
+                    param_list
+                        .self_param()
+                        .map(|it| Some(Either::Left(it)))
+                        .filter(|_| !self.is_bound_method)
+                        .into_iter()
+                        .chain(param_list.params().map(map_param))
+                }),
+                None => None,
+            },
+            _ => None,
+        };
+        patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
     }
     pub fn return_type(&self) -> Type {
         self.ty.derived(self.sig.ret().clone())
@@ -5025,9 +5017,17 @@ impl Callable {
     pub fn sig(&self) -> &CallableSig {
         &self.sig
     }
+}
 
-    pub fn ty(&self) -> &Type {
-        &self.ty
+fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
+    let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
+    let (_, source_map) = db.body_with_source_map(owner);
+    let ast = source_map.expr_syntax(expr_id).ok()?;
+    let root = ast.file_syntax(db.upcast());
+    let expr = ast.value.to_node(&root);
+    match expr {
+        ast::Expr::ClosureExpr(it) => Some(it),
+        _ => None,
     }
 }
 
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index d229584064..057b03baef 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -307,8 +307,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         call: &ast::Expr,
     ) -> Option<Callable> {
-        let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
-        adjusted.unwrap_or(orig).as_callable(db)
+        self.type_of_expr(db, &call.clone())?.0.as_callable(db)
     }
 
     pub(crate) fn resolve_field(
diff --git a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
index 37ea5123a7..7f3b0d7588 100644
--- a/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
+++ b/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs
@@ -114,10 +114,10 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<'
     let callable = ctx.sema.resolve_method_call_as_callable(&call)?;
     let (_, receiver_ty) = callable.receiver_param(ctx.sema.db)?;
     let n_params = callable.n_params() + 1;
-    let params = callable.params();
+    let params = callable.params(ctx.sema.db);
 
     // FIXME: Check that the arg is of the form `() -> T`
-    if !params.first()?.ty().impls_fnonce(ctx.sema.db) {
+    if !params.first()?.1.impls_fnonce(ctx.sema.db) {
         return None;
     }
 
diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs
index 23a06404f3..1859825b3d 100644
--- a/crates/ide-assists/src/utils/suggest_name.rs
+++ b/crates/ide-assists/src/utils/suggest_name.rs
@@ -253,8 +253,11 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<St
     };
 
     let (idx, _) = arg_list.args().find_position(|it| it == expr).unwrap();
-    let param = func.params().into_iter().nth(idx)?;
-    let pat = param.source(sema.db)?.value.right()?.pat()?;
+    let (pat, _) = func.params(sema.db).into_iter().nth(idx)?;
+    let pat = match pat? {
+        either::Either::Right(pat) => pat,
+        _ => return None,
+    };
     let name = var_name_from_pat(&pat)?;
     normalize(&name.to_string())
 }
diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs
index 98d2e81754..5780b5a5bb 100644
--- a/crates/ide-db/src/active_parameter.rs
+++ b/crates/ide-db/src/active_parameter.rs
@@ -1,7 +1,7 @@
 //! This module provides functionality for querying callable information about a token.
 
 use either::Either;
-use hir::{InFile, Semantics, Type};
+use hir::{Semantics, Type};
 use parser::T;
 use syntax::{
     ast::{self, HasArgList, HasName},
@@ -13,7 +13,7 @@ use crate::RootDatabase;
 #[derive(Debug)]
 pub struct ActiveParameter {
     pub ty: Type,
-    pub src: Option<InFile<Either<ast::SelfParam, ast::Param>>>,
+    pub pat: Option<Either<ast::SelfParam, ast::Pat>>,
 }
 
 impl ActiveParameter {
@@ -22,18 +22,18 @@ impl ActiveParameter {
         let (signature, active_parameter) = callable_for_token(sema, token)?;
 
         let idx = active_parameter?;
-        let mut params = signature.params();
+        let mut params = signature.params(sema.db);
         if idx >= params.len() {
             cov_mark::hit!(too_many_arguments);
             return None;
         }
-        let param = params.swap_remove(idx);
-        Some(ActiveParameter { ty: param.ty().clone(), src: param.source(sema.db) })
+        let (pat, ty) = params.swap_remove(idx);
+        Some(ActiveParameter { ty, pat })
     }
 
     pub fn ident(&self) -> Option<ast::Name> {
-        self.src.as_ref().and_then(|param| match param.value.as_ref().right()?.pat()? {
-            ast::Pat::IdentPat(ident) => ident.name(),
+        self.pat.as_ref().and_then(|param| match param {
+            Either::Right(ast::Pat::IdentPat(ident)) => ident.name(),
             _ => None,
         })
     }
@@ -60,7 +60,10 @@ pub fn callable_for_node(
     token: &SyntaxToken,
 ) -> Option<(hir::Callable, Option<usize>)> {
     let callable = match calling_node {
-        ast::CallableExpr::Call(call) => sema.resolve_expr_as_callable(&call.expr()?),
+        ast::CallableExpr::Call(call) => {
+            let expr = call.expr()?;
+            sema.type_of_expr(&expr)?.adjusted().as_callable(sema.db)
+        }
         ast::CallableExpr::MethodCall(call) => sema.resolve_method_call_as_callable(call),
     }?;
     let active_param = calling_node.arg_list().map(|arg_list| {
diff --git a/crates/ide-db/src/syntax_helpers/format_string.rs b/crates/ide-db/src/syntax_helpers/format_string.rs
index 92478ef480..8302b015dd 100644
--- a/crates/ide-db/src/syntax_helpers/format_string.rs
+++ b/crates/ide-db/src/syntax_helpers/format_string.rs
@@ -41,7 +41,6 @@ pub enum FormatSpecifier {
     Escape,
 }
 
-// FIXME: Remove this, we can use rustc_format_parse instead
 pub fn lex_format_specifiers(
     string: &ast::String,
     mut callback: &mut dyn FnMut(TextRange, FormatSpecifier),
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs
index 654a1cd316..458b852e2a 100644
--- a/crates/ide/src/call_hierarchy.rs
+++ b/crates/ide/src/call_hierarchy.rs
@@ -109,12 +109,12 @@ pub(crate) fn outgoing_calls(
                     let expr = call.expr()?;
                     let callable = sema.type_of_expr(&expr)?.original.as_callable(db)?;
                     match callable.kind() {
-                        hir::CallableKind::Function(it) => it.try_to_nav(db),
-                        hir::CallableKind::TupleEnumVariant(it) => it.try_to_nav(db),
-                        hir::CallableKind::TupleStruct(it) => it.try_to_nav(db),
+                        hir::CallableKind::Function(it) => {
+                            let range = expr.syntax().text_range();
+                            it.try_to_nav(db).zip(Some(range))
+                        }
                         _ => None,
                     }
-                    .zip(Some(expr.syntax().text_range()))
                 }
                 ast::CallableExpr::MethodCall(expr) => {
                     let range = expr.name_ref()?.syntax().text_range();
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index fb50c49a3a..96e845b2f3 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -24,29 +24,34 @@ pub(super) fn hints(
 
     let (callable, arg_list) = get_callable(sema, &expr)?;
     let hints = callable
-        .params()
+        .params(sema.db)
         .into_iter()
         .zip(arg_list.args())
-        .filter_map(|(p, arg)| {
+        .filter_map(|((param, _ty), arg)| {
             // Only annotate hints for expressions that exist in the original file
             let range = sema.original_range_opt(arg.syntax())?;
-            let source = p.source(sema.db)?;
-            let (param_name, name_syntax) = match source.value.as_ref() {
+            let (param_name, name_syntax) = match param.as_ref()? {
                 Either::Left(pat) => (pat.name()?, pat.name()),
-                Either::Right(param) => match param.pat()? {
+                Either::Right(pat) => match pat {
                     ast::Pat::IdentPat(it) => (it.name()?, it.name()),
                     _ => return None,
                 },
             };
-            // make sure the file is cached so we can map out of macros
-            sema.parse_or_expand(source.file_id);
             Some((name_syntax, param_name, arg, range))
         })
         .filter(|(_, param_name, arg, _)| {
             !should_hide_param_name_hint(sema, &callable, &param_name.text(), arg)
         })
         .map(|(param, param_name, _, FileRange { range, .. })| {
-            let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
+            let mut linked_location = None;
+            if let Some(name) = param {
+                if let hir::CallableKind::Function(f) = callable.kind() {
+                    // assert the file is cached so we can map out of macros
+                    if sema.source(f).is_some() {
+                        linked_location = sema.original_range_opt(name.syntax());
+                    }
+                }
+            }
 
             let colon = if config.render_colons { ":" } else { "" };
             let label =
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 378a38892c..b2eb5a5fff 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -201,21 +201,7 @@ fn signature_help_for_call(
                 variant.name(db).display(db)
             );
         }
-        hir::CallableKind::Closure(closure) => {
-            let fn_trait = closure.fn_trait(db);
-            format_to!(res.signature, "impl {fn_trait}")
-        }
-        hir::CallableKind::FnPtr => format_to!(res.signature, "fn"),
-        hir::CallableKind::FnImpl(fn_trait) => match callable.ty().as_adt() {
-            // FIXME: Render docs of the concrete trait impl function
-            Some(adt) => format_to!(
-                res.signature,
-                "<{} as {fn_trait}>::{}",
-                adt.name(db).display(db),
-                fn_trait.function_name()
-            ),
-            None => format_to!(res.signature, "impl {fn_trait}"),
-        },
+        hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
     }
 
     res.signature.push('(');
@@ -224,15 +210,12 @@ fn signature_help_for_call(
             format_to!(res.signature, "{}", self_param.display(db))
         }
         let mut buf = String::new();
-        for (idx, p) in callable.params().into_iter().enumerate() {
+        for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
             buf.clear();
-            if let Some(param) = p.source(sema.db) {
-                match param.value {
-                    Either::Right(param) => match param.pat() {
-                        Some(pat) => format_to!(buf, "{}: ", pat),
-                        None => format_to!(buf, "?: "),
-                    },
-                    Either::Left(_) => format_to!(buf, "self: "),
+            if let Some(pat) = pat {
+                match pat {
+                    Either::Left(_self) => format_to!(buf, "self: "),
+                    Either::Right(pat) => format_to!(buf, "{}: ", pat),
                 }
             }
             // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
@@ -240,9 +223,9 @@ fn signature_help_for_call(
             // In that case, fall back to render definitions of the respective parameters.
             // This is overly conservative: we do not substitute known type vars
             // (see FIXME in tests::impl_trait) and falling back on any unknowns.
-            match (p.ty().contains_unknown(), fn_params.as_deref()) {
+            match (ty.contains_unknown(), fn_params.as_deref()) {
                 (true, Some(fn_params)) => format_to!(buf, "{}", fn_params[idx].ty().display(db)),
-                _ => format_to!(buf, "{}", p.ty().display(db)),
+                _ => format_to!(buf, "{}", ty.display(db)),
             }
             res.push_call_param(&buf);
         }
@@ -259,9 +242,9 @@ fn signature_help_for_call(
             render(func.ret_type(db))
         }
         hir::CallableKind::Function(_)
-        | hir::CallableKind::Closure(_)
+        | hir::CallableKind::Closure
         | hir::CallableKind::FnPtr
-        | hir::CallableKind::FnImpl(_) => render(callable.return_type()),
+        | hir::CallableKind::Other => render(callable.return_type()),
         hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
     }
     Some(res)
@@ -1362,43 +1345,15 @@ fn test() { S.foo($0); }
             r#"
 struct S;
 fn foo(s: S) -> i32 { 92 }
-fn main() {
-    let _move = S;
-    (|s| {{_move}; foo(s)})($0)
-}
-        "#,
-            expect![[r#"
-                impl FnOnce(s: S) -> i32
-                            ^^^^
-            "#]],
-        );
-        check(
-            r#"
-struct S;
-fn foo(s: S) -> i32 { 92 }
 fn main() {
     (|s| foo(s))($0)
 }
         "#,
             expect![[r#"
-                impl Fn(s: S) -> i32
-                        ^^^^
-            "#]],
-        );
-        check(
-            r#"
-struct S;
-fn foo(s: S) -> i32 { 92 }
-fn main() {
-    let mut mutate = 0;
-    (|s| { mutate = 1; foo(s) })($0)
-}
-        "#,
-            expect![[r#"
-                impl FnMut(s: S) -> i32
-                           ^^^^
+                (s: S) -> i32
+                 ^^^^
             "#]],
-        );
+        )
     }
 
     #[test]
@@ -1428,81 +1383,12 @@ fn main(f: fn(i32, f64) -> char) {
 }
         "#,
             expect![[r#"
-                fn(i32, f64) -> char
-                   ---  ^^^
+                (i32, f64) -> char
+                 ---  ^^^
             "#]],
         )
     }
 
-    #[test]
-    fn call_info_for_fn_impl() {
-        check(
-            r#"
-struct S;
-impl core::ops::FnOnce<(i32, f64)> for S {
-    type Output = char;
-}
-impl core::ops::FnMut<(i32, f64)> for S {}
-impl core::ops::Fn<(i32, f64)> for S {}
-fn main() {
-    S($0);
-}
-        "#,
-            expect![[r#"
-                <S as Fn>::call(i32, f64) -> char
-                                ^^^  ---
-            "#]],
-        );
-        check(
-            r#"
-struct S;
-impl core::ops::FnOnce<(i32, f64)> for S {
-    type Output = char;
-}
-impl core::ops::FnMut<(i32, f64)> for S {}
-impl core::ops::Fn<(i32, f64)> for S {}
-fn main() {
-    S(1, $0);
-}
-        "#,
-            expect![[r#"
-                <S as Fn>::call(i32, f64) -> char
-                                ---  ^^^
-            "#]],
-        );
-        check(
-            r#"
-struct S;
-impl core::ops::FnOnce<(i32, f64)> for S {
-    type Output = char;
-}
-impl core::ops::FnOnce<(char, char)> for S {
-    type Output = f64;
-}
-fn main() {
-    S($0);
-}
-        "#,
-            expect![""],
-        );
-        check(
-            r#"
-struct S;
-impl core::ops::FnOnce<(i32, f64)> for S {
-    type Output = char;
-}
-impl core::ops::FnOnce<(char, char)> for S {
-    type Output = f64;
-}
-fn main() {
-    // FIXME: The ide layer loses the calling info here so we get an ambiguous trait solve result
-    S(0i32, $0);
-}
-        "#,
-            expect![""],
-        );
-    }
-
     #[test]
     fn call_info_for_unclosed_call() {
         check(
@@ -1908,19 +1794,19 @@ fn f<F: FnOnce(u8, u16) -> i32>(f: F) {
 }
 "#,
             expect![[r#"
-                impl FnOnce(u8, u16) -> i32
-                            ^^  ---
+                (u8, u16) -> i32
+                 ^^  ---
             "#]],
         );
         check(
             r#"
-fn f<T, F: FnMut(&T, u16) -> &T>(f: F) {
+fn f<T, F: FnOnce(&T, u16) -> &T>(f: F) {
     f($0)
 }
 "#,
             expect![[r#"
-                impl FnMut(&T, u16) -> &T
-                           ^^  ---
+                (&T, u16) -> &T
+                 ^^  ---
             "#]],
         );
     }
@@ -1940,7 +1826,7 @@ fn take<C, Error>(
 }
 "#,
             expect![[r#"
-                impl Fn() -> i32
+                () -> i32
             "#]],
         );
     }
diff --git a/crates/ide/src/syntax_highlighting/escape.rs b/crates/ide/src/syntax_highlighting/escape.rs
index 2f387968c9..0439e509d2 100644
--- a/crates/ide/src/syntax_highlighting/escape.rs
+++ b/crates/ide/src/syntax_highlighting/escape.rs
@@ -9,9 +9,8 @@ pub(super) fn highlight_escape_string<T: IsString>(
     string: &T,
     start: TextSize,
 ) {
-    let text = string.text();
     string.escaped_char_ranges(&mut |piece_range, char| {
-        if text[piece_range.start().into()..].starts_with('\\') {
+        if string.text()[piece_range.start().into()..].starts_with('\\') {
             let highlight = match char {
                 Ok(_) => HlTag::EscapeSequence,
                 Err(_) => HlTag::InvalidEscapeSequence,
@@ -34,15 +33,17 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
     }
 
     let text = char.text();
-    let Some(text) = text
-        .strip_prefix('\'')
-        .and_then(|it| it.strip_suffix('\''))
-        .filter(|it| it.starts_with('\\'))
-    else {
+    if !text.starts_with('\'') || !text.ends_with('\'') {
         return;
-    };
+    }
+
+    let text = &text[1..text.len() - 1];
+    if !text.starts_with('\\') {
+        return;
+    }
 
-    let range = TextRange::at(start + TextSize::from(1), TextSize::from(text.len() as u32));
+    let range =
+        TextRange::new(start + TextSize::from(1), start + TextSize::from(text.len() as u32 + 1));
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
 
@@ -53,14 +54,16 @@ pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start:
     }
 
     let text = byte.text();
-    let Some(text) = text
-        .strip_prefix("b'")
-        .and_then(|it| it.strip_suffix('\''))
-        .filter(|it| it.starts_with('\\'))
-    else {
+    if !text.starts_with("b'") || !text.ends_with('\'') {
         return;
-    };
+    }
+
+    let text = &text[2..text.len() - 1];
+    if !text.starts_with('\\') {
+        return;
+    }
 
-    let range = TextRange::at(start + TextSize::from(2), TextSize::from(text.len() as u32));
+    let range =
+        TextRange::new(start + TextSize::from(2), start + TextSize::from(text.len() as u32 + 2));
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 79b87ecd58..f64e66183d 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -87,7 +87,6 @@ pub(crate) struct GlobalState {
     pub(crate) flycheck_sender: Sender<flycheck::Message>,
     pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
     pub(crate) last_flycheck_error: Option<String>,
-    pub(crate) diagnostics_received: bool,
 
     // Test explorer
     pub(crate) test_run_session: Option<Vec<flycheck::CargoTestHandle>>,
@@ -225,7 +224,6 @@ impl GlobalState {
             flycheck_sender,
             flycheck_receiver,
             last_flycheck_error: None,
-            diagnostics_received: false,
 
             test_run_session: None,
             test_run_sender,
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 7acd302867..5435be3dc2 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -804,10 +804,6 @@ impl GlobalState {
     fn handle_flycheck_msg(&mut self, message: flycheck::Message) {
         match message {
             flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => {
-                if !self.diagnostics_received {
-                    self.diagnostics.clear_check(id);
-                    self.diagnostics_received = true;
-                }
                 let snap = self.snapshot();
                 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
                     &self.config.diagnostics_map(),
@@ -836,7 +832,7 @@ impl GlobalState {
             flycheck::Message::Progress { id, progress } => {
                 let (state, message) = match progress {
                     flycheck::Progress::DidStart => {
-                        self.diagnostics_received = false;
+                        self.diagnostics.clear_check(id);
                         (Progress::Begin, None)
                     }
                     flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)),
@@ -852,9 +848,6 @@ impl GlobalState {
                     flycheck::Progress::DidFinish(result) => {
                         self.last_flycheck_error =
                             result.err().map(|err| format!("cargo check failed to start: {err}"));
-                        if !self.diagnostics_received {
-                            self.diagnostics.clear_check(id);
-                        }
                         (Progress::End, None)
                     }
                 };
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 1ce548f8fc..16599881d6 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -8,7 +8,6 @@ use std::{
 use rustc_lexer::unescape::{
     unescape_byte, unescape_char, unescape_mixed, unescape_unicode, EscapeError, MixedUnit, Mode,
 };
-use stdx::always;
 
 use crate::{
     ast::{self, AstToken},
@@ -182,25 +181,25 @@ pub trait IsString: AstToken {
         self.quote_offsets().map(|it| it.quotes.1)
     }
     fn escaped_char_ranges(&self, cb: &mut dyn FnMut(TextRange, Result<char, EscapeError>)) {
-        let Some(text_range_no_quotes) = self.text_range_between_quotes() else { return };
+        let text_range_no_quotes = match self.text_range_between_quotes() {
+            Some(it) => it,
+            None => return,
+        };
 
         let start = self.syntax().text_range().start();
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
         unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| {
-            if let Some((s, e)) = range.start.try_into().ok().zip(range.end.try_into().ok()) {
-                cb(TextRange::new(s, e) + offset, unescaped_char);
-            }
+            let text_range =
+                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
+            cb(text_range + offset, unescaped_char);
         });
     }
     fn map_range_up(&self, range: TextRange) -> Option<TextRange> {
         let contents_range = self.text_range_between_quotes()?;
-        if always!(TextRange::up_to(contents_range.len()).contains_range(range)) {
-            Some(range + contents_range.start())
-        } else {
-            None
-        }
+        assert!(TextRange::up_to(contents_range.len()).contains_range(range));
+        Some(range + contents_range.start())
     }
 }
 


Test patch:
diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs
index 4c8a54f7c8..e8b26d5373 100644
--- a/crates/hir-def/src/body/tests.rs
+++ b/crates/hir-def/src/body/tests.rs
@@ -150,7 +150,7 @@ fn desugar_builtin_format_args() {
 fn main() {
     let are = "are";
     let count = 10;
-    builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
+    builtin#format_args("\u{1b}hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
 }
 "#,
     );
@@ -161,7 +161,7 @@ fn main() {
             let count = 10;
             builtin#lang(Arguments::new_v1_formatted)(
                 &[
-                    "hello ", " ", " friends, we ", " ", "",
+                    "\u{1b}hello ", " ", " friends, we ", " ", "",
                 ],
                 &[
                     builtin#lang(Argument::new_display)(