Repository: rust-lang/rust-analyzer
Pull request #19084 (2025-02-03 10:06:33)

Split cache priming into distinct phases
We want the `DefMap`'s to be computed ASAP, but for local packages we compute the import map (and the even more expensive symbol index) which would delay the def map computation of local leaf crates by a fair bit, so instead we do the def maps first in an initial phase, then follow up on the other indices in a second one.


Patch:
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 651502965e..2ccdc8c042 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -14,4 +14,3 @@ f247090558c9ba3c551566eae5882b7ca865225f
 b2f6fd4f961fc7e4fbfdb80cae2e6065f8436f15
 c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
 f532576ac53ddcc666bc8d59e0b6437065e2f599
-4704881b641884de50645637108b6b6f5b68aaf9
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index a0fc8c31ea..c2cea07190 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -129,9 +129,9 @@ impl fmt::Display for CrateName {
 }
 
 impl ops::Deref for CrateName {
-    type Target = str;
-    fn deref(&self) -> &str {
-        self.0.as_str()
+    type Target = Symbol;
+    fn deref(&self) -> &Symbol {
+        &self.0
     }
 }
 
@@ -230,8 +230,8 @@ impl fmt::Display for CrateDisplayName {
 }
 
 impl ops::Deref for CrateDisplayName {
-    type Target = str;
-    fn deref(&self) -> &str {
+    type Target = Symbol;
+    fn deref(&self) -> &Symbol {
         &self.crate_name
     }
 }
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 34635997bd..6137bd34d6 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -519,7 +519,7 @@ mod tests {
                 crate_graph[krate]
                     .display_name
                     .as_ref()
-                    .is_some_and(|it| &**it.crate_name() == crate_name)
+                    .is_some_and(|it| it.crate_name().as_str() == crate_name)
             })
             .expect("could not find crate");
 
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 166e00c9d2..e83ce6dc42 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -501,5 +501,4 @@ language_item_table! {
 
     String,                  sym::String,              string,                     Target::Struct,         GenericRequirement::None;
     CStr,                    sym::CStr,                c_str,                      Target::Struct,         GenericRequirement::None;
-    Ordering,                sym::Ordering,            ordering,                   Target::Enum,           GenericRequirement::None;
 }
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 39d383f015..3b6e3c5916 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -337,7 +337,7 @@ impl DefMap {
     pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
         let crate_graph = db.crate_graph();
         let krate = &crate_graph[crate_id];
-        let name = krate.display_name.as_deref().unwrap_or_default();
+        let name = krate.display_name.as_deref().map(Symbol::as_str).unwrap_or_default();
         let _p = tracing::info_span!("crate_def_map_query", ?name).entered();
 
         let module_data = ModuleData::new(
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 848870c3a3..21e5fb5ef9 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -262,6 +262,6 @@ impl AsName for ast::FieldKind {
 
 impl AsName for base_db::Dependency {
     fn as_name(&self) -> Name {
-        Name::new_root(&self.name)
+        Name::new_symbol_root((*self.name).clone())
     }
 }
diff --git a/crates/hir-expand/src/prettify_macro_expansion_.rs b/crates/hir-expand/src/prettify_macro_expansion_.rs
index 6ff7831fd8..c744fbce77 100644
--- a/crates/hir-expand/src/prettify_macro_expansion_.rs
+++ b/crates/hir-expand/src/prettify_macro_expansion_.rs
@@ -41,9 +41,9 @@ pub fn prettify_macro_expansion(
                 } else if let Some(dep) =
                     target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
                 {
-                    make::tokens::ident(&dep.name)
+                    make::tokens::ident(dep.name.as_str())
                 } else if let Some(crate_name) = &crate_graph[macro_def_crate].display_name {
-                    make::tokens::ident(crate_name.crate_name())
+                    make::tokens::ident(crate_name.crate_name().as_str())
                 } else {
                     return dollar_crate.clone();
                 }
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 617ebba881..3c258e3c4c 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -466,9 +466,6 @@ pub struct InferenceResult {
     pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
     type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
     /// Whether there are any type-mismatching errors in the result.
-    // FIXME: This isn't as useful as initially thought due to us falling back placeholders to
-    // `TyKind::Error`.
-    // Which will then mark this field.
     pub(crate) has_errors: bool,
     /// Interned common types to return references to.
     // FIXME: Move this into `InferenceContext`
@@ -946,7 +943,7 @@ impl<'a> InferenceContext<'a> {
             let ty = self.insert_type_vars(ty);
             let ty = self.normalize_associated_types_in(ty);
 
-            self.infer_top_pat(*pat, &ty, None);
+            self.infer_top_pat(*pat, &ty);
             if ty
                 .data(Interner)
                 .flags
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 86e5afdb50..b951443897 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -43,9 +43,9 @@ use crate::{
     primitive::{self, UintTy},
     static_lifetime, to_chalk_trait_id,
     traits::FnTrait,
-    Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext,
-    DeclOrigin, FnAbi, FnPointer, FnSig, FnSubst, Interner, Rawness, Scalar, Substitution,
-    TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
+    Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, FnAbi, FnPointer,
+    FnSig, FnSubst, Interner, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty,
+    TyBuilder, TyExt, TyKind,
 };
 
 use super::{
@@ -334,11 +334,7 @@ impl InferenceContext<'_> {
                     ExprIsRead::No
                 };
                 let input_ty = self.infer_expr(expr, &Expectation::none(), child_is_read);
-                self.infer_top_pat(
-                    pat,
-                    &input_ty,
-                    Some(DeclContext { origin: DeclOrigin::LetExpr }),
-                );
+                self.infer_top_pat(pat, &input_ty);
                 self.result.standard_types.bool_.clone()
             }
             Expr::Block { statements, tail, label, id } => {
@@ -465,7 +461,7 @@ impl InferenceContext<'_> {
 
                 // Now go through the argument patterns
                 for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) {
-                    self.infer_top_pat(*arg_pat, arg_ty, None);
+                    self.infer_top_pat(*arg_pat, arg_ty);
                 }
 
                 // FIXME: lift these out into a struct
@@ -586,7 +582,7 @@ impl InferenceContext<'_> {
                     let mut all_arms_diverge = Diverges::Always;
                     for arm in arms.iter() {
                         let input_ty = self.resolve_ty_shallow(&input_ty);
-                        self.infer_top_pat(arm.pat, &input_ty, None);
+                        self.infer_top_pat(arm.pat, &input_ty);
                     }
 
                     let expected = expected.adjust_for_branches(&mut self.table);
@@ -931,7 +927,7 @@ impl InferenceContext<'_> {
                     let resolver_guard =
                         self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, tgt_expr);
                     self.inside_assignment = true;
-                    self.infer_top_pat(target, &rhs_ty, None);
+                    self.infer_top_pat(target, &rhs_ty);
                     self.inside_assignment = false;
                     self.resolver.reset_to_guard(resolver_guard);
                 }
@@ -1636,11 +1632,8 @@ impl InferenceContext<'_> {
                                 decl_ty
                             };
 
-                            let decl = DeclContext {
-                                origin: DeclOrigin::LocalDecl { has_else: else_branch.is_some() },
-                            };
+                            this.infer_top_pat(*pat, &ty);
 
-                            this.infer_top_pat(*pat, &ty, Some(decl));
                             if let Some(expr) = else_branch {
                                 let previous_diverges =
                                     mem::replace(&mut this.diverges, Diverges::Maybe);
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 5ff22bea34..ca8d5bae5e 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -6,21 +6,20 @@ use hir_def::{
     expr_store::Body,
     hir::{Binding, BindingAnnotation, BindingId, Expr, ExprId, Literal, Pat, PatId},
     path::Path,
-    HasModule,
 };
 use hir_expand::name::Name;
 use stdx::TupleExt;
 
 use crate::{
-    consteval::{self, try_const_usize, usize_const},
+    consteval::{try_const_usize, usize_const},
     infer::{
         coerce::CoerceNever, expr::ExprIsRead, BindingMode, Expectation, InferenceContext,
         TypeMismatch,
     },
     lower::lower_to_chalk_mutability,
     primitive::UintTy,
-    static_lifetime, DeclContext, DeclOrigin, InferenceDiagnostic, Interner, Mutability, Scalar,
-    Substitution, Ty, TyBuilder, TyExt, TyKind,
+    static_lifetime, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty,
+    TyBuilder, TyExt, TyKind,
 };
 
 impl InferenceContext<'_> {
@@ -35,7 +34,6 @@ impl InferenceContext<'_> {
         id: PatId,
         ellipsis: Option<u32>,
         subs: &[PatId],
-        decl: Option<DeclContext>,
     ) -> Ty {
         let (ty, def) = self.resolve_variant(id.into(), path, true);
         let var_data = def.map(|it| it.variant_data(self.db.upcast()));
@@ -94,13 +92,13 @@ impl InferenceContext<'_> {
                         }
                     };
 
-                    self.infer_pat(subpat, &expected_ty, default_bm, decl);
+                    self.infer_pat(subpat, &expected_ty, default_bm);
                 }
             }
             None => {
                 let err_ty = self.err_ty();
                 for &inner in subs {
-                    self.infer_pat(inner, &err_ty, default_bm, decl);
+                    self.infer_pat(inner, &err_ty, default_bm);
                 }
             }
         }
@@ -116,7 +114,6 @@ impl InferenceContext<'_> {
         default_bm: BindingMode,
         id: PatId,
         subs: impl ExactSizeIterator<Item = (Name, PatId)>,
-        decl: Option<DeclContext>,
     ) -> Ty {
         let (ty, def) = self.resolve_variant(id.into(), path, false);
         if let Some(variant) = def {
@@ -165,13 +162,13 @@ impl InferenceContext<'_> {
                         }
                     };
 
-                    self.infer_pat(inner, &expected_ty, default_bm, decl);
+                    self.infer_pat(inner, &expected_ty, default_bm);
                 }
             }
             None => {
                 let err_ty = self.err_ty();
                 for (_, inner) in subs {
-                    self.infer_pat(inner, &err_ty, default_bm, decl);
+                    self.infer_pat(inner, &err_ty, default_bm);
                 }
             }
         }
@@ -188,7 +185,6 @@ impl InferenceContext<'_> {
         default_bm: BindingMode,
         ellipsis: Option<u32>,
         subs: &[PatId],
-        decl: Option<DeclContext>,
     ) -> Ty {
         let expected = self.resolve_ty_shallow(expected);
         let expectations = match expected.as_tuple() {
@@ -213,12 +209,12 @@ impl InferenceContext<'_> {
 
         // Process pre
         for (ty, pat) in inner_tys.iter_mut().zip(pre) {
-            *ty = self.infer_pat(*pat, ty, default_bm, decl);
+            *ty = self.infer_pat(*pat, ty, default_bm);
         }
 
         // Process post
         for (ty, pat) in inner_tys.iter_mut().skip(pre.len() + n_uncovered_patterns).zip(post) {
-            *ty = self.infer_pat(*pat, ty, default_bm, decl);
+            *ty = self.infer_pat(*pat, ty, default_bm);
         }
 
         TyKind::Tuple(inner_tys.len(), Substitution::from_iter(Interner, inner_tys))
@@ -227,17 +223,11 @@ impl InferenceContext<'_> {
 
     /// The resolver needs to be updated to the surrounding expression when inside assignment
     /// (because there, `Pat::Path` can refer to a variable).
-    pub(super) fn infer_top_pat(&mut self, pat: PatId, expected: &Ty, decl: Option<DeclContext>) {
-        self.infer_pat(pat, expected, BindingMode::default(), decl);
+    pub(super) fn infer_top_pat(&mut self, pat: PatId, expected: &Ty) {
+        self.infer_pat(pat, expected, BindingMode::default());
     }
 
-    fn infer_pat(
-        &mut self,
-        pat: PatId,
-        expected: &Ty,
-        mut default_bm: BindingMode,
-        decl: Option<DeclContext>,
-    ) -> Ty {
+    fn infer_pat(&mut self, pat: PatId, expected: &Ty, mut default_bm: BindingMode) -> Ty {
         let mut expected = self.resolve_ty_shallow(expected);
 
         if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment {
@@ -271,11 +261,11 @@ impl InferenceContext<'_> {
 
         let ty = match &self.body[pat] {
             Pat::Tuple { args, ellipsis } => {
-                self.infer_tuple_pat_like(&expected, default_bm, *ellipsis, args, decl)
+                self.infer_tuple_pat_like(&expected, default_bm, *ellipsis, args)
             }
             Pat::Or(pats) => {
                 for pat in pats.iter() {
-                    self.infer_pat(*pat, &expected, default_bm, decl);
+                    self.infer_pat(*pat, &expected, default_bm);
                 }
                 expected.clone()
             }
@@ -284,7 +274,6 @@ impl InferenceContext<'_> {
                 lower_to_chalk_mutability(mutability),
                 &expected,
                 default_bm,
-                decl,
             ),
             Pat::TupleStruct { path: p, args: subpats, ellipsis } => self
                 .infer_tuple_struct_pat_like(
@@ -294,11 +283,10 @@ impl InferenceContext<'_> {
                     pat,
                     *ellipsis,
                     subpats,
-                    decl,
                 ),
             Pat::Record { path: p, args: fields, ellipsis: _ } => {
                 let subs = fields.iter().map(|f| (f.name.clone(), f.pat));
-                self.infer_record_pat_like(p.as_deref(), &expected, default_bm, pat, subs, decl)
+                self.infer_record_pat_like(p.as_deref(), &expected, default_bm, pat, subs)
             }
             Pat::Path(path) => {
                 let ty = self.infer_path(path, pat.into()).unwrap_or_else(|| self.err_ty());
@@ -331,10 +319,10 @@ impl InferenceContext<'_> {
                 }
             }
             Pat::Bind { id, subpat } => {
-                return self.infer_bind_pat(pat, *id, default_bm, *subpat, &expected, decl);
+                return self.infer_bind_pat(pat, *id, default_bm, *subpat, &expected);
             }
             Pat::Slice { prefix, slice, suffix } => {
-                self.infer_slice_pat(&expected, prefix, slice, suffix, default_bm, decl)
+                self.infer_slice_pat(&expected, prefix, slice, suffix, default_bm)
             }
             Pat::Wild => expected.clone(),
             Pat::Range { .. } => {
@@ -357,7 +345,7 @@ impl InferenceContext<'_> {
                         _ => (self.result.standard_types.unknown.clone(), None),
                     };
 
-                    let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm, decl);
+                    let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
                     let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty);
 
                     if let Some(alloc_ty) = alloc_ty {
@@ -432,7 +420,6 @@ impl InferenceContext<'_> {
         mutability: Mutability,
         expected: &Ty,
         default_bm: BindingMode,
-        decl: Option<DeclContext>,
     ) -> Ty {
         let (expectation_type, expectation_lt) = match expected.as_reference() {
             Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime.clone()),
@@ -446,7 +433,7 @@ impl InferenceContext<'_> {
                 (inner_ty, inner_lt)
             }
         };
-        let subty = self.infer_pat(inner_pat, &expectation_type, default_bm, decl);
+        let subty = self.infer_pat(inner_pat, &expectation_type, default_bm);
         TyKind::Ref(mutability, expectation_lt, subty).intern(Interner)
     }
 
@@ -457,7 +444,6 @@ impl InferenceContext<'_> {
         default_bm: BindingMode,
         subpat: Option<PatId>,
         expected: &Ty,
-        decl: Option<DeclContext>,
     ) -> Ty {
         let Binding { mode, .. } = self.body.bindings[binding];
         let mode = if mode == BindingAnnotation::Unannotated {
@@ -468,7 +454,7 @@ impl InferenceContext<'_> {
         self.result.binding_modes.insert(pat, mode);
 
         let inner_ty = match subpat {
-            Some(subpat) => self.infer_pat(subpat, expected, default_bm, decl),
+            Some(subpat) => self.infer_pat(subpat, expected, default_bm),
             None => expected.clone(),
         };
         let inner_ty = self.insert_type_vars_shallow(inner_ty);
@@ -492,28 +478,14 @@ impl InferenceContext<'_> {
         slice: &Option<PatId>,
         suffix: &[PatId],
         default_bm: BindingMode,
-        decl: Option<DeclContext>,
     ) -> Ty {
-        let expected = self.resolve_ty_shallow(expected);
-
-        // If `expected` is an infer ty, we try to equate it to an array if the given pattern
-        // allows it. See issue #16609
-        if self.pat_is_irrefutable(decl) && expected.is_ty_var() {
-            if let Some(resolved_array_ty) =
-                self.try_resolve_slice_ty_to_array_ty(prefix, suffix, slice)
-            {
-                self.unify(&expected, &resolved_array_ty);
-            }
-        }
-
-        let expected = self.resolve_ty_shallow(&expected);
         let elem_ty = match expected.kind(Interner) {
             TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
             _ => self.err_ty(),
         };
 
         for &pat_id in prefix.iter().chain(suffix.iter()) {
-            self.infer_pat(pat_id, &elem_ty, default_bm, decl);
+            self.infer_pat(pat_id, &elem_ty, default_bm);
         }
 
         if let &Some(slice_pat_id) = slice {
@@ -527,7 +499,7 @@ impl InferenceContext<'_> {
                 _ => TyKind::Slice(elem_ty.clone()),
             }
             .intern(Interner);
-            self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm, decl);
+            self.infer_pat(slice_pat_id, &rest_pat_ty, default_bm);
         }
 
         match expected.kind(Interner) {
@@ -581,59 +553,6 @@ impl InferenceContext<'_> {
             | Pat::Expr(_) => false,
         }
     }
-
-    fn try_resolve_slice_ty_to_array_ty(
-        &mut self,
-        before: &[PatId],
-        suffix: &[PatId],
-        slice: &Option<PatId>,
-    ) -> Option<Ty> {
-        if !slice.is_none() {
-            return None;
-        }
-
-        let len = before.len() + suffix.len();
-        let size =
-            consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db.upcast()));
-
-        let elem_ty = self.table.new_type_var();
-        let array_ty = TyKind::Array(elem_ty.clone(), size).intern(Interner);
-        Some(array_ty)
-    }
-
-    /// Used to determine whether we can infer the expected type in the slice pattern to be of type array.
-    /// This is only possible if we're in an irrefutable pattern. If we were to allow this in refutable
-    /// patterns we wouldn't e.g. report ambiguity in the following situation:
-    ///
-    /// ```ignore(rust)
-    ///    struct Zeroes;
-    ///    const ARR: [usize; 2] = [0; 2];
-    ///    const ARR2: [usize; 2] = [2; 2];
-    ///
-    ///    impl Into<&'static [usize; 2]> for Zeroes {
-    ///        fn into(self) -> &'static [usize; 2] {
-    ///            &ARR
-    ///        }
-    ///    }
-    ///
-    ///    impl Into<&'static [usize]> for Zeroes {
-    ///        fn into(self) -> &'static [usize] {
-    ///            &ARR2
-    ///        }
-    ///    }
-    ///
-    ///    fn main() {
-    ///        let &[a, b]: &[usize] = Zeroes.into() else {
-    ///           ..
-    ///        };
-    ///    }
-    /// ```
-    ///
-    /// If we're in an irrefutable pattern we prefer the array impl candidate given that
-    /// the slice impl candidate would be rejected anyway (if no ambiguity existed).
-    fn pat_is_irrefutable(&self, decl_ctxt: Option<DeclContext>) -> bool {
-        matches!(decl_ctxt, Some(DeclContext { origin: DeclOrigin::LocalDecl { has_else: false } }))
-    }
 }
 
 pub(super) fn contains_explicit_ref_binding(body: &Body, pat_id: PatId) -> bool {
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 55d81875a2..4b159b7541 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -1049,20 +1049,3 @@ pub fn known_const_to_ast(
     }
     Some(make::expr_const_value(konst.display(db, edition).to_string().as_str()))
 }
-
-#[derive(Debug, Copy, Clone)]
-pub(crate) enum DeclOrigin {
-    LetExpr,
-    /// from `let x = ..`
-    LocalDecl {
-        has_else: bool,
-    },
-}
-
-/// Provides context for checking patterns in declarations. More specifically this
-/// allows us to infer array types if the pattern is irrefutable and allows us to infer
-/// the size of the array. See issue rust-lang/rust#76342.
-#[derive(Debug, Copy, Clone)]
-pub(crate) struct DeclContext {
-    pub(crate) origin: DeclOrigin,
-}
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index db94351dcc..1cea67ee96 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -4,7 +4,6 @@
 //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
 use std::ops::ControlFlow;
 
-use arrayvec::ArrayVec;
 use base_db::CrateId;
 use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
 use hir_def::{
@@ -733,27 +732,15 @@ fn lookup_impl_assoc_item_for_trait_ref(
     let self_ty = trait_ref.self_type_parameter(Interner);
     let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty)?;
     let impls = db.trait_impls_in_deps(env.krate);
-
-    let trait_module = hir_trait_id.module(db.upcast());
-    let type_module = match self_ty_fp {
-        TyFingerprint::Adt(adt_id) => Some(adt_id.module(db.upcast())),
-        TyFingerprint::ForeignType(type_id) => {
-            Some(from_foreign_def_id(type_id).module(db.upcast()))
+    let self_impls = match self_ty.kind(Interner) {
+        TyKind::Adt(id, _) => {
+            id.0.module(db.upcast()).containing_block().and_then(|it| db.trait_impls_in_block(it))
         }
-        TyFingerprint::Dyn(trait_id) => Some(trait_id.module(db.upcast())),
         _ => None,
     };
-
-    let def_blocks: ArrayVec<_, 2> =
-        [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())]
-            .into_iter()
-            .flatten()
-            .filter_map(|block_id| db.trait_impls_in_block(block_id))
-            .collect();
-
     let impls = impls
         .iter()
-        .chain(&def_blocks)
+        .chain(self_impls.as_ref())
         .flat_map(|impls| impls.for_trait_and_self_ty(hir_trait_id, self_ty_fp));
 
     let table = InferenceTable::new(db, env);
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 6b20522cf3..8e4c4db102 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1644,15 +1644,14 @@ impl Evaluator<'_> {
             Variants::Multiple { tag, tag_encoding, variants, .. } => {
                 let size = tag.size(&*self.target_data_layout).bytes_usize();
                 let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field
-                let is_signed = tag.is_signed();
                 match tag_encoding {
                     TagEncoding::Direct => {
                         let tag = &bytes[offset..offset + size];
-                        Ok(i128::from_le_bytes(pad16(tag, is_signed)))
+                        Ok(i128::from_le_bytes(pad16(tag, false)))
                     }
                     TagEncoding::Niche { untagged_variant, niche_start, .. } => {
                         let tag = &bytes[offset..offset + size];
-                        let candidate_tag = i128::from_le_bytes(pad16(tag, is_signed))
+                        let candidate_tag = i128::from_le_bytes(pad16(tag, false))
                             .wrapping_sub(*niche_start as i128)
                             as usize;
                         let idx = variants
@@ -2944,10 +2943,10 @@ pub fn render_const_using_debug_impl(
     // a3 = ::core::fmt::Arguments::new_v1(a1, a2)
     // FIXME: similarly, we should call function here, not directly working with memory.
     let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size())?;
-    evaluator.write_memory(a3, &a1.to_bytes())?;
-    evaluator.write_memory(a3.offset(evaluator.ptr_size()), &[1])?;
-    evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a2.to_bytes())?;
+    evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a1.to_bytes())?;
     evaluator.write_memory(a3.offset(3 * evaluator.ptr_size()), &[1])?;
+    evaluator.write_memory(a3.offset(4 * evaluator.ptr_size()), &a2.to_bytes())?;
+    evaluator.write_memory(a3.offset(5 * evaluator.ptr_size()), &[1])?;
     let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully(
         db.upcast(),
         &hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]),
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 38b189a517..0a78f4a5b2 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -1,12 +1,11 @@
 //! Interpret intrinsics, lang items and `extern "C"` wellknown functions which their implementation
 //! is not available.
 //!
-use std::cmp::{self, Ordering};
+use std::cmp;
 
 use chalk_ir::TyKind;
 use hir_def::{
     builtin_type::{BuiltinInt, BuiltinUint},
-    lang_item::LangItemTarget,
     resolver::HasResolver,
 };
 use hir_expand::name::Name;
@@ -1318,82 +1317,6 @@ impl Evaluator<'_> {
                 self.write_memory_using_ref(dst, size)?.fill(val);
                 Ok(())
             }
-            "ptr_metadata" => {
-                let [ptr] = args else {
-                    return Err(MirEvalError::InternalError(
-                        "ptr_metadata args are not provided".into(),
-                    ));
-                };
-                let arg = ptr.interval.get(self)?.to_owned();
-                let metadata = &arg[self.ptr_size()..];
-                destination.write_from_bytes(self, metadata)?;
-                Ok(())
-            }
-            "three_way_compare" => {
-                let [lhs, rhs] = args else {
-                    return Err(MirEvalError::InternalError(
-                        "three_way_compare args are not provided".into(),
-                    ));
-                };
-                let Some(ty) =
-                    generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
-                else {
-                    return Err(MirEvalError::InternalError(
-                        "three_way_compare generic arg is not provided".into(),
-                    ));
-                };
-                let signed = match ty.as_builtin().unwrap() {
-                    BuiltinType::Int(_) => true,
-                    BuiltinType::Uint(_) => false,
-                    _ => {
-                        return Err(MirEvalError::InternalError(
-                            "three_way_compare expects an integral type".into(),
-                        ))
-                    }
-                };
-                let rhs = rhs.get(self)?;
-                let lhs = lhs.get(self)?;
-                let mut result = Ordering::Equal;
-                for (l, r) in lhs.iter().zip(rhs).rev() {
-                    let it = l.cmp(r);
-                    if it != Ordering::Equal {
-                        result = it;
-                        break;
-                    }
-                }
-                if signed {
-                    if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() {
-                        if l != r {
-                            result = (l as i8).cmp(&(r as i8));
-                        }
-                    }
-                }
-                if let Some(LangItemTarget::EnumId(e)) =
-                    self.db.lang_item(self.crate_id, LangItem::Ordering)
-                {
-                    let ty = self.db.ty(e.into());
-                    let r = self
-                        .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
-                    destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;
-                    Ok(())
-                } else {
-                    Err(MirEvalError::InternalError("Ordering enum not found".into()))
-                }
-            }
-            "aggregate_raw_ptr" => {
-                let [data, meta] = args else {
-                    return Err(MirEvalError::InternalError(
-                        "aggregate_raw_ptr args are not provided".into(),
-                    ));
-                };
-                destination.write_from_interval(self, data.interval)?;
-                Interval {
-                    addr: destination.addr.offset(data.interval.size),
-                    size: destination.size - data.interval.size,
-                }
-                .write_from_interval(self, meta.interval)?;
-                Ok(())
-            }
             _ if needs_override => not_supported!("intrinsic {name} is not implemented"),
             _ => return Ok(false),
         }
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 549450e9be..cc6ed122af 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -2156,7 +2156,7 @@ pub fn lower_to_mir(
     // need to take this input explicitly.
     root_expr: ExprId,
 ) -> Result<MirBody> {
-    if infer.type_mismatches().next().is_some() {
+    if infer.has_errors {
         return Err(MirLowerError::HasErrors);
     }
     let mut ctx = MirLowerCtx::new(db, owner, body, infer);
diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs
index 0002fda0ba..22dc3d9e29 100644
--- a/crates/ide-db/src/prime_caches.rs
+++ b/crates/ide-db/src/prime_caches.rs
@@ -6,12 +6,13 @@ mod topologic_sort;
 
 use std::time::Duration;
 
-use hir::db::DefDatabase;
+use hir::{db::DefDatabase, Symbol};
+use itertools::Itertools;
 
 use crate::{
     base_db::{
         ra_salsa::{Database, ParallelDatabase, Snapshot},
-        Cancelled, CrateId, SourceDatabase, SourceRootDatabase,
+        Cancelled, CrateId, SourceDatabase,
     },
     symbol_index::SymbolsDatabase,
     FxIndexMap, RootDatabase,
@@ -21,11 +22,12 @@ use crate::{
 #[derive(Debug)]
 pub struct ParallelPrimeCachesProgress {
     /// the crates that we are currently priming.
-    pub crates_currently_indexing: Vec<String>,
+    pub crates_currently_indexing: Vec<Symbol>,
     /// the total number of crates we want to prime.
     pub crates_total: usize,
     /// the total number of crates that have finished priming
     pub crates_done: usize,
+    pub work_type: &'static str,
 }
 
 pub fn parallel_prime_caches(
@@ -47,41 +49,32 @@ pub fn parallel_prime_caches(
     };
 
     enum ParallelPrimeCacheWorkerProgress {
-        BeginCrate { crate_id: CrateId, crate_name: String },
+        BeginCrate { crate_id: CrateId, crate_name: Symbol },
         EndCrate { crate_id: CrateId },
     }
 
+    // We split off def map computation from other work,
+    // as the def map is the relevant one. Once the defmaps are computed
+    // the project is ready to go, the other indices are just nice to have for some IDE features.
+    #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
+    enum PrimingPhase {
+        DefMap,
+        ImportMap,
+        CrateSymbols,
+    }
+
     let (work_sender, progress_receiver) = {
         let (progress_sender, progress_receiver) = crossbeam_channel::unbounded();
         let (work_sender, work_receiver) = crossbeam_channel::unbounded();
-        let graph = graph.clone();
-        let local_roots = db.local_roots();
         let prime_caches_worker = move |db: Snapshot<RootDatabase>| {
-            while let Ok((crate_id, crate_name)) = work_receiver.recv() {
+            while let Ok((crate_id, crate_name, kind)) = work_receiver.recv() {
                 progress_sender
                     .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?;
 
-                // Compute the DefMap and possibly ImportMap
-                let file_id = graph[crate_id].root_file_id;
-                let root_id = db.file_source_root(file_id);
-                if db.source_root(root_id).is_library {
-                    db.crate_def_map(crate_id);
-                } else {
-                    // This also computes the DefMap
-                    db.import_map(crate_id);
-                }
-
-                // Compute the symbol search index.
-                // This primes the cache for `ide_db::symbol_index::world_symbols()`.
-                //
-                // We do this for workspace crates only (members of local_roots), because doing it
-                // for all dependencies could be *very* unnecessarily slow in a large project.
-                //
-                // FIXME: We should do it unconditionally if the configuration is set to default to
-                // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
-                // would need to pipe that configuration information down here.
-                if local_roots.contains(&root_id) {
-                    db.crate_symbols(crate_id.into());
+                match kind {
+                    PrimingPhase::DefMap => _ = db.crate_def_map(crate_id),
+                    PrimingPhase::ImportMap => _ = db.import_map(crate_id),
+                    PrimingPhase::CrateSymbols => _ = db.crate_symbols(crate_id.into()),
                 }
 
                 progress_sender.send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?;
@@ -112,16 +105,34 @@ pub fn parallel_prime_caches(
     let mut crates_currently_indexing =
         FxIndexMap::with_capacity_and_hasher(num_worker_threads, Default::default());
 
+    let mut additional_phases = vec![];
+
     while crates_done < crates_total {
         db.unwind_if_cancelled();
 
         for crate_id in &mut crates_to_prime {
-            work_sender
-                .send((
-                    crate_id,
-                    graph[crate_id].display_name.as_deref().unwrap_or_default().to_owned(),
-                ))
-                .ok();
+            let krate = &graph[crate_id];
+            let name = krate
+                .display_name
+                .as_deref()
+                .cloned()
+                .unwrap_or_else(|| Symbol::integer(crate_id.into_raw().into_u32() as usize));
+            if krate.origin.is_lang() {
+                additional_phases.push((crate_id, name.clone(), PrimingPhase::ImportMap));
+            } else if krate.origin.is_local() {
+                // Compute the symbol search index.
+                // This primes the cache for `ide_db::symbol_index::world_symbols()`.
+                //
+                // We do this for workspace crates only (members of local_roots), because doing it
+                // for all dependencies could be *very* unnecessarily slow in a large project.
+                //
+                // FIXME: We should do it unconditionally if the configuration is set to default to
+                // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
+                // would need to pipe that configuration information down here.
+                additional_phases.push((crate_id, name.clone(), PrimingPhase::CrateSymbols));
+            }
+
+            work_sender.send((crate_id, name, PrimingPhase::DefMap)).ok();
         }
 
         // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision
@@ -153,6 +164,50 @@ pub fn parallel_prime_caches(
             crates_currently_indexing: crates_currently_indexing.values().cloned().collect(),
             crates_done,
             crates_total,
+            work_type: "Indexing",
+        };
+
+        cb(progress);
+    }
+
+    let mut crates_done = 0;
+    let crates_total = additional_phases.len();
+    for w in additional_phases.into_iter().sorted_by_key(|&(_, _, phase)| phase) {
+        work_sender.send(w).ok();
+    }
+
+    while crates_done < crates_total {
+        db.unwind_if_cancelled();
+
+        // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision
+        // is cancelled on a regular basis. workers will only exit if they are processing a task that is cancelled, or
+        // if this thread exits, and closes the work channel.
+        let worker_progress = match progress_receiver.recv_timeout(Duration::from_millis(10)) {
+            Ok(p) => p,
+            Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
+                continue;
+            }
+            Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
+                // our workers may have died from a cancelled task, so we'll check and re-raise here.
+                db.unwind_if_cancelled();
+                break;
+            }
+        };
+        match worker_progress {
+            ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name } => {
+                crates_currently_indexing.insert(crate_id, crate_name);
+            }
+            ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => {
+                crates_currently_indexing.swap_remove(&crate_id);
+                crates_done += 1;
+            }
+        };
+
+        let progress = ParallelPrimeCachesProgress {
+            crates_currently_indexing: crates_currently_indexing.values().cloned().collect(),
+            crates_done,
+            crates_total,
+            work_type: "Populating symbols",
         };
 
         cb(progress);
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index 246330e6ef..0cc80bda2c 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -936,7 +936,6 @@ fn func() {
     fn override_lint_level() {
         check_diagnostics(
             r#"
-#![allow(unused_variables)]
 #[warn(nonstandard_style)]
 fn foo() {
     let BAR;
@@ -993,7 +992,6 @@ struct QUX;
 const foo: i32 = 0;
 fn BAR() {
     let BAZ;
-    _ = BAZ;
 }
         "#,
         );
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 0e3c4c7aa3..1397979144 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -831,14 +831,13 @@ fn f() {
 
     #[test]
     fn or_pattern() {
+        // FIXME: `None` is inferred as unknown here for some reason
         check_diagnostics(
             r#"
 //- minicore: option
 fn f(_: i32) {}
 fn main() {
     let ((Some(mut x), None) | (_, Some(mut x))) = (None, Some(7)) else { return };
-             //^^^^^ 💡 warn: variable does not need to be mutable
-
     f(x);
 }
 "#,
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 66ea49a98a..d97c12ebaf 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -289,10 +289,7 @@ fn def_to_non_local_moniker(
     definition: Definition,
     from_crate: Crate,
 ) -> Option<Moniker> {
-    let module = match definition {
-        Definition::Module(module) if module.is_crate_root() => module,
-        _ => definition.module(db)?,
-    };
+    let module = definition.module(db)?;
     let krate = module.krate();
     let edition = krate.edition(db);
 
@@ -325,18 +322,12 @@ fn def_to_non_local_moniker(
                         name: name.display(db, edition).to_string(),
                         desc: def_to_kind(db, def).into(),
                     });
+                } else if reverse_description.is_empty() {
+                    // Don't allow the last descriptor to be absent.
+                    return None;
                 } else {
                     match def {
-                        Definition::Module(module) if module.is_crate_root() => {
-                            // only include `crate` namespace by itself because we prefer
-                            // `rust-analyzer cargo foo . bar/` over `rust-analyzer cargo foo . crate/bar/`
-                            if reverse_description.is_empty() {
-                                reverse_description.push(MonikerDescriptor {
-                                    name: "crate".to_owned(),
-                                    desc: MonikerDescriptorKind::Namespace,
-                                });
-                            }
-                        }
+                        Definition::Module(module) if module.is_crate_root() => {}
                         _ => {
                             tracing::error!(?def, "Encountered enclosing definition with no name");
                         }
@@ -349,9 +340,6 @@ fn def_to_non_local_moniker(
         };
         def = next_def;
     }
-    if reverse_description.is_empty() {
-        return None;
-    }
     reverse_description.reverse();
     let description = reverse_description;
 
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 3121bb7a8e..8050a38b3c 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -169,10 +169,10 @@ impl StaticIndex<'_> {
             .unwrap();
         // hovers
         let sema = hir::Semantics::new(self.db);
-        let root = sema.parse_guess_edition(file_id).syntax().clone();
+        let tokens_or_nodes = sema.parse_guess_edition(file_id).syntax().clone();
         let edition =
             sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
-        let tokens = root.descendants_with_tokens().filter_map(|it| match it {
+        let tokens = tokens_or_nodes.descendants_with_tokens().filter_map(|it| match it {
             syntax::NodeOrToken::Node(_) => None,
             syntax::NodeOrToken::Token(it) => Some(it),
         });
@@ -194,19 +194,24 @@ impl StaticIndex<'_> {
             )
         });
         let mut result = StaticIndexedFile { file_id, inlay_hints, folds, tokens: vec![] };
-
-        let mut add_token = |def: Definition, range: TextRange, scope_node: &SyntaxNode| {
+        for token in tokens {
+            let range = token.text_range();
+            let node = token.parent().unwrap();
+            let def = match get_definition(&sema, token.clone()) {
+                Some(it) => it,
+                None => continue,
+            };
             let id = if let Some(it) = self.def_map.get(&def) {
                 *it
             } else {
                 let it = self.tokens.insert(TokenStaticData {
-                    documentation: documentation_for_definition(&sema, def, scope_node),
+                    documentation: documentation_for_definition(&sema, def, &node),
                     hover: Some(hover_for_definition(
                         &sema,
                         file_id,
                         def,
                         None,
-                        scope_node,
+                        &node,
                         None,
                         false,
                         &hover_config,
@@ -235,22 +240,6 @@ impl StaticIndex<'_> {
                 },
             });
             result.tokens.push((range, id));
-        };
-
-        if let Some(module) = sema.file_to_module_def(file_id) {
-            let def = Definition::Module(module);
-            let range = root.text_range();
-            add_token(def, range, &root);
-        }
-
-        for token in tokens {
-            let range = token.text_range();
-            let node = token.parent().unwrap();
-            let def = match get_definition(&sema, token.clone()) {
-                Some(it) => it,
-                None => continue,
-            };
-            add_token(def, range, &node);
         }
         self.files.push(result);
     }
@@ -311,10 +300,6 @@ mod tests {
         let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect();
         for f in s.files {
             for (range, _) in f.tokens {
-                if range.start() == TextSize::from(0) {
-                    // ignore whole file range corresponding to module definition
-                    continue;
-                }
                 let it = FileRange { file_id: f.file_id, range };
                 if !range_set.contains(&it) {
                     panic!("additional range {it:?}");
diff --git a/crates/ide/src/view_crate_graph.rs b/crates/ide/src/view_crate_graph.rs
index 24a986b85b..eb6eb7da1e 100644
--- a/crates/ide/src/view_crate_graph.rs
+++ b/crates/ide/src/view_crate_graph.rs
@@ -84,7 +84,8 @@ impl<'a> dot::Labeller<'a, CrateId, Edge<'a>> for DotCrateGraph {
     }
 
     fn node_label(&'a self, n: &CrateId) -> LabelText<'a> {
-        let name = self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name);
+        let name =
+            self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name.as_str());
         LabelText::LabelStr(name.into())
     }
 }
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index 8df7c59aa7..fce4feb01d 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -347,7 +347,6 @@ define_symbols! {
     option,
     Option,
     Ord,
-    Ordering,
     Output,
     CallRefFuture,
     CallOnceFuture,
@@ -481,6 +480,7 @@ define_symbols! {
     u64,
     u8,
     unadjusted,
+    unknown,
     Unknown,
     unpin,
     unreachable_2015,
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index a396396761..feee40a1fc 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -508,5 +508,5 @@ fn serialize_crate_name<S>(name: &CrateName, se: S) -> Result<S::Ok, S::Error>
 where
     S: serde::Serializer,
 {
-    se.serialize_str(name)
+    se.serialize_str(name.as_str())
 }
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index 28f25975d6..6a3ceb640b 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -4,7 +4,7 @@
 use project_model::{CargoConfig, RustLibSource};
 use rustc_hash::FxHashSet;
 
-use hir::{db::HirDatabase, Crate, HirFileIdExt, Module};
+use hir::{db::HirDatabase, sym, Crate, HirFileIdExt, Module};
 use ide::{AnalysisHost, AssistResolveStrategy, Diagnostic, DiagnosticsConfig, Severity};
 use ide_db::{base_db::SourceRootDatabase, LineIndexDatabase};
 use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
@@ -60,7 +60,7 @@ impl flags::Diagnostics {
             let file_id = module.definition_source_file_id(db).original_file(db);
             if !visited_files.contains(&file_id) {
                 let crate_name =
-                    module.krate().display_name(db).as_deref().unwrap_or("unknown").to_owned();
+                    module.krate().display_name(db).as_deref().unwrap_or(&sym::unknown).to_owned();
                 println!(
                     "processing crate: {crate_name}, module: {}",
                     _vfs.file_path(file_id.into())
diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs
index ee7b698975..dc0f722aae 100644
--- a/crates/rust-analyzer/src/cli/scip.rs
+++ b/crates/rust-analyzer/src/cli/scip.rs
@@ -444,14 +444,14 @@ impl SymbolGenerator {
                     MonikerResult::Moniker(moniker) => TokenSymbols {
                         symbol: scip::symbol::format_symbol(moniker_to_symbol(moniker)),
                         enclosing_symbol: None,
-                        is_inherent_impl: match &moniker.identifier.description[..] {
-                            // inherent impls are represented as impl#[SelfType]
-                            [.., descriptor, _] => {
+                        is_inherent_impl: moniker
+                            .identifier
+                            .description
+                            .get(moniker.identifier.description.len() - 2)
+                            .is_some_and(|descriptor| {
                                 descriptor.desc == MonikerDescriptorKind::Type
                                     && descriptor.name == "impl"
-                            }
-                            _ => false,
-                        },
+                            }),
                     },
                     MonikerResult::Local { enclosing_moniker } => {
                         let local_symbol = scip::types::Symbol::new_local(local_count);
@@ -549,9 +549,7 @@ mod test {
                 continue;
             }
             for &(range, id) in &file.tokens {
-                // check if cursor is within token, ignoring token for the module defined by the file (whose range is the whole file)
-                if range.start() != TextSize::from(0) && range.contains(offset - TextSize::from(1))
-                {
+                if range.contains(offset - TextSize::from(1)) {
                     let token = si.tokens.get(id).unwrap();
                     found_symbol = match token.moniker.as_ref() {
                         None => None,
@@ -887,7 +885,7 @@ pub mod example_mod {
         );
 
         let file = si.files.first().unwrap();
-        let (_, token_id) = file.tokens.get(1).unwrap(); // first token is file module, second is `bar`
+        let (_, token_id) = file.tokens.first().unwrap();
         let token = si.tokens.get(*token_id).unwrap();
 
         assert_eq!(token.documentation.as_ref().map(|d| d.as_str()), Some("foo"));
diff --git a/crates/rust-analyzer/src/cli/unresolved_references.rs b/crates/rust-analyzer/src/cli/unresolved_references.rs
index 986bd018b4..021b1bff39 100644
--- a/crates/rust-analyzer/src/cli/unresolved_references.rs
+++ b/crates/rust-analyzer/src/cli/unresolved_references.rs
@@ -1,5 +1,5 @@
 //! Reports references in code that the IDE layer cannot resolve.
-use hir::{db::HirDatabase, AnyDiagnostic, Crate, HirFileIdExt as _, Module, Semantics};
+use hir::{db::HirDatabase, sym, AnyDiagnostic, Crate, HirFileIdExt as _, Module, Semantics};
 use ide::{AnalysisHost, RootDatabase, TextRange};
 use ide_db::{
     base_db::{SourceDatabase, SourceRootDatabase},
@@ -66,7 +66,7 @@ impl flags::UnresolvedReferences {
             let file_id = module.definition_source_file_id(db).original_file(db);
             if !visited_files.contains(&file_id) {
                 let crate_name =
-                    module.krate().display_name(db).as_deref().unwrap_or("unknown").to_owned();
+                    module.krate().display_name(db).as_deref().unwrap_or(&sym::unknown).to_owned();
                 let file_path = vfs.file_path(file_id.into());
                 eprintln!("processing crate: {crate_name}, module: {file_path}",);
 
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index de0ee639ca..ebc65373b5 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -325,26 +325,30 @@ impl GlobalState {
                 }
 
                 for progress in prime_caches_progress {
-                    let (state, message, fraction);
+                    let (state, message, fraction, title);
                     match progress {
                         PrimeCachesProgress::Begin => {
                             state = Progress::Begin;
                             message = None;
                             fraction = 0.0;
+                            title = "Indexing";
                         }
                         PrimeCachesProgress::Report(report) => {
                             state = Progress::Report;
+                            title = report.work_type;
 
-                            message = match &report.crates_currently_indexing[..] {
+                            message = match &*report.crates_currently_indexing {
                                 [crate_name] => Some(format!(
-                                    "{}/{} ({crate_name})",
-                                    report.crates_done, report.crates_total
+                                    "{}/{} ({})",
+                                    report.crates_done,
+                                    report.crates_total,
+                                    crate_name.as_str(),
                                 )),
                                 [crate_name, rest @ ..] => Some(format!(
                                     "{}/{} ({} + {} more)",
                                     report.crates_done,
                                     report.crates_total,
-                                    crate_name,
+                                    crate_name.as_str(),
                                     rest.len()
                                 )),
                                 _ => None,
@@ -356,6 +360,7 @@ impl GlobalState {
                             state = Progress::End;
                             message = None;
                             fraction = 1.0;
+                            title = "Indexing";
 
                             self.prime_caches_queue.op_completed(());
                             if cancelled {
@@ -365,7 +370,13 @@ impl GlobalState {
                         }
                     };
 
-                    self.report_progress("Indexing", state, message, Some(fraction), None);
+                    self.report_progress(
+                        title,
+                        state,
+                        message,
+                        Some(fraction),
+                        Some("rustAnalyzer/cachePriming".to_owned()),
+                    );
                 }
             }
             Event::Vfs(message) => {


Test patch:
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index 50a1ecd006..1563660457 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -3814,50 +3814,3 @@ async fn foo(a: (), b: i32) -> u32 {
         "#,
     );
 }
-
-#[test]
-fn irrefutable_slices() {
-    check_infer(
-        r#"
-//- minicore: from
-struct A;
-
-impl From<A> for [u8; 2] {
-    fn from(a: A) -> Self {
-        [0; 2]
-    }
-}
-impl From<A> for [u8; 3] {
-    fn from(a: A) -> Self {
-        [0; 3]
-    }
-}
-
-
-fn main() {
-    let a = A;
-    let [b, c] = a.into();
-}
-"#,
-        expect![[r#"
-            50..51 'a': A
-            64..86 '{     ...     }': [u8; 2]
-            74..80 '[0; 2]': [u8; 2]
-            75..76 '0': u8
-            78..79 '2': usize
-            128..129 'a': A
-            142..164 '{     ...     }': [u8; 3]
-            152..158 '[0; 3]': [u8; 3]
-            153..154 '0': u8
-            156..157 '3': usize
-            179..224 '{     ...o(); }': ()
-            189..190 'a': A
-            193..194 'A': A
-            204..210 '[b, c]': [u8; 2]
-            205..206 'b': u8
-            208..209 'c': u8
-            213..214 'a': A
-            213..221 'a.into()': [u8; 2]
-        "#]],
-    );
-}
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index f111383112..2856086543 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -230,7 +230,7 @@ fn rust_project_is_proc_macro_has_proc_macro_dep() {
     let crate_data = &crate_graph[crate_id];
     // Assert that the project crate with `is_proc_macro` has a dependency
     // on the proc_macro sysroot crate.
-    crate_data.dependencies.iter().find(|&dep| dep.name.deref() == "proc_macro").unwrap();
+    crate_data.dependencies.iter().find(|&dep| *dep.name.deref() == sym::proc_macro).unwrap();
 }
 
 #[test]
diff --git a/crates/rust-analyzer/tests/slow-tests/cli.rs b/crates/rust-analyzer/tests/slow-tests/cli.rs
index 4ef930e985..fba5466691 100644
--- a/crates/rust-analyzer/tests/slow-tests/cli.rs
+++ b/crates/rust-analyzer/tests/slow-tests/cli.rs
@@ -43,93 +43,89 @@ mod tests {
     expect![[r#"
         {"id":2,"type":"vertex","label":"foldingRangeResult","result":[{"startLine":2,"startCharacter":43,"endLine":6,"endCharacter":1},{"startLine":3,"startCharacter":19,"endLine":5,"endCharacter":5},{"startLine":9,"startCharacter":10,"endLine":12,"endCharacter":1}]}
         {"id":3,"type":"edge","label":"textDocument/foldingRange","inV":2,"outV":1}
-        {"id":4,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":13,"character":0}}
+        {"id":4,"type":"vertex","label":"range","start":{"line":0,"character":3},"end":{"line":0,"character":8}}
         {"id":5,"type":"vertex","label":"resultSet"}
         {"id":6,"type":"edge","label":"next","inV":5,"outV":4}
-        {"id":7,"type":"vertex","label":"range","start":{"line":0,"character":3},"end":{"line":0,"character":8}}
+        {"id":7,"type":"vertex","label":"range","start":{"line":2,"character":13},"end":{"line":2,"character":43}}
         {"id":8,"type":"vertex","label":"resultSet"}
         {"id":9,"type":"edge","label":"next","inV":8,"outV":7}
-        {"id":10,"type":"vertex","label":"range","start":{"line":2,"character":13},"end":{"line":2,"character":43}}
-        {"id":11,"type":"vertex","label":"resultSet"}
-        {"id":12,"type":"edge","label":"next","inV":11,"outV":10}
-        {"id":13,"type":"vertex","label":"range","start":{"line":8,"character":0},"end":{"line":8,"character":30}}
-        {"id":14,"type":"edge","label":"next","inV":11,"outV":13}
-        {"id":15,"type":"vertex","label":"range","start":{"line":8,"character":32},"end":{"line":8,"character":39}}
+        {"id":10,"type":"vertex","label":"range","start":{"line":8,"character":0},"end":{"line":8,"character":30}}
+        {"id":11,"type":"edge","label":"next","inV":8,"outV":10}
+        {"id":12,"type":"vertex","label":"range","start":{"line":8,"character":32},"end":{"line":8,"character":39}}
+        {"id":13,"type":"vertex","label":"resultSet"}
+        {"id":14,"type":"edge","label":"next","inV":13,"outV":12}
+        {"id":15,"type":"vertex","label":"range","start":{"line":9,"character":4},"end":{"line":9,"character":9}}
         {"id":16,"type":"vertex","label":"resultSet"}
         {"id":17,"type":"edge","label":"next","inV":16,"outV":15}
-        {"id":18,"type":"vertex","label":"range","start":{"line":9,"character":4},"end":{"line":9,"character":9}}
+        {"id":18,"type":"vertex","label":"range","start":{"line":10,"character":8},"end":{"line":10,"character":13}}
         {"id":19,"type":"vertex","label":"resultSet"}
         {"id":20,"type":"edge","label":"next","inV":19,"outV":18}
-        {"id":21,"type":"vertex","label":"range","start":{"line":10,"character":8},"end":{"line":10,"character":13}}
-        {"id":22,"type":"edge","label":"next","inV":5,"outV":21}
-        {"id":23,"type":"vertex","label":"range","start":{"line":11,"character":4},"end":{"line":11,"character":34}}
-        {"id":24,"type":"edge","label":"next","inV":11,"outV":23}
-        {"id":25,"type":"vertex","label":"range","start":{"line":11,"character":36},"end":{"line":11,"character":43}}
-        {"id":26,"type":"vertex","label":"resultSet"}
-        {"id":27,"type":"edge","label":"next","inV":26,"outV":25}
-        {"id":28,"type":"edge","label":"contains","inVs":[4,7,10,13,15,18,21,23,25],"outV":1}
-        {"id":29,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nextern crate foo\n```"}}}
-        {"id":30,"type":"edge","label":"textDocument/hover","inV":29,"outV":5}
-        {"id":31,"type":"vertex","label":"packageInformation","name":"foo","manager":"cargo","version":"0.0.0"}
-        {"id":32,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::crate","unique":"scheme","kind":"export"}
-        {"id":33,"type":"edge","label":"packageInformation","inV":31,"outV":32}
-        {"id":34,"type":"edge","label":"moniker","inV":32,"outV":5}
-        {"id":35,"type":"vertex","label":"definitionResult"}
-        {"id":36,"type":"edge","label":"item","document":1,"inVs":[4],"outV":35}
-        {"id":37,"type":"edge","label":"textDocument/definition","inV":35,"outV":5}
-        {"id":38,"type":"vertex","label":"referenceResult"}
-        {"id":39,"type":"edge","label":"textDocument/references","inV":38,"outV":5}
-        {"id":40,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[4],"outV":38}
-        {"id":41,"type":"edge","label":"item","document":1,"property":"references","inVs":[21],"outV":38}
-        {"id":42,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\n#[allow]\n```\n\n---\n\nValid forms are:\n\n* \\#\\[allow(lint1, lint2, ..., /\\*opt\\*/ reason = \"...\")\\]"}}}
-        {"id":43,"type":"edge","label":"textDocument/hover","inV":42,"outV":8}
-        {"id":44,"type":"vertex","label":"referenceResult"}
-        {"id":45,"type":"edge","label":"textDocument/references","inV":44,"outV":8}
-        {"id":46,"type":"edge","label":"item","document":1,"property":"references","inVs":[7],"outV":44}
-        {"id":47,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nmacro_rules! generate_const_from_identifier\n```"}}}
-        {"id":48,"type":"edge","label":"textDocument/hover","inV":47,"outV":11}
-        {"id":49,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::generate_const_from_identifier","unique":"scheme","kind":"export"}
-        {"id":50,"type":"edge","label":"packageInformation","inV":31,"outV":49}
-        {"id":51,"type":"edge","label":"moniker","inV":49,"outV":11}
-        {"id":52,"type":"vertex","label":"definitionResult"}
-        {"id":53,"type":"edge","label":"item","document":1,"inVs":[10],"outV":52}
-        {"id":54,"type":"edge","label":"textDocument/definition","inV":52,"outV":11}
-        {"id":55,"type":"vertex","label":"referenceResult"}
-        {"id":56,"type":"edge","label":"textDocument/references","inV":55,"outV":11}
-        {"id":57,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[10],"outV":55}
-        {"id":58,"type":"edge","label":"item","document":1,"property":"references","inVs":[13,23],"outV":55}
-        {"id":59,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nconst REQ_001: &str = \"encoded_data\"\n```"}}}
-        {"id":60,"type":"edge","label":"textDocument/hover","inV":59,"outV":16}
-        {"id":61,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::REQ_001","unique":"scheme","kind":"export"}
-        {"id":62,"type":"edge","label":"packageInformation","inV":31,"outV":61}
-        {"id":63,"type":"edge","label":"moniker","inV":61,"outV":16}
-        {"id":64,"type":"vertex","label":"definitionResult"}
-        {"id":65,"type":"edge","label":"item","document":1,"inVs":[15],"outV":64}
-        {"id":66,"type":"edge","label":"textDocument/definition","inV":64,"outV":16}
-        {"id":67,"type":"vertex","label":"referenceResult"}
-        {"id":68,"type":"edge","label":"textDocument/references","inV":67,"outV":16}
-        {"id":69,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[15],"outV":67}
-        {"id":70,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nmod tests\n```"}}}
-        {"id":71,"type":"edge","label":"textDocument/hover","inV":70,"outV":19}
-        {"id":72,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::tests","unique":"scheme","kind":"export"}
-        {"id":73,"type":"edge","label":"packageInformation","inV":31,"outV":72}
-        {"id":74,"type":"edge","label":"moniker","inV":72,"outV":19}
-        {"id":75,"type":"vertex","label":"definitionResult"}
-        {"id":76,"type":"edge","label":"item","document":1,"inVs":[18],"outV":75}
-        {"id":77,"type":"edge","label":"textDocument/definition","inV":75,"outV":19}
-        {"id":78,"type":"vertex","label":"referenceResult"}
-        {"id":79,"type":"edge","label":"textDocument/references","inV":78,"outV":19}
-        {"id":80,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[18],"outV":78}
-        {"id":81,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo::tests\n```\n\n```rust\nconst REQ_002: &str = \"encoded_data\"\n```"}}}
-        {"id":82,"type":"edge","label":"textDocument/hover","inV":81,"outV":26}
-        {"id":83,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::tests::REQ_002","unique":"scheme","kind":"export"}
-        {"id":84,"type":"edge","label":"packageInformation","inV":31,"outV":83}
-        {"id":85,"type":"edge","label":"moniker","inV":83,"outV":26}
-        {"id":86,"type":"vertex","label":"definitionResult"}
-        {"id":87,"type":"edge","label":"item","document":1,"inVs":[25],"outV":86}
-        {"id":88,"type":"edge","label":"textDocument/definition","inV":86,"outV":26}
-        {"id":89,"type":"vertex","label":"referenceResult"}
-        {"id":90,"type":"edge","label":"textDocument/references","inV":89,"outV":26}
-        {"id":91,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[25],"outV":89}
+        {"id":21,"type":"vertex","label":"range","start":{"line":11,"character":4},"end":{"line":11,"character":34}}
+        {"id":22,"type":"edge","label":"next","inV":8,"outV":21}
+        {"id":23,"type":"vertex","label":"range","start":{"line":11,"character":36},"end":{"line":11,"character":43}}
+        {"id":24,"type":"vertex","label":"resultSet"}
+        {"id":25,"type":"edge","label":"next","inV":24,"outV":23}
+        {"id":26,"type":"edge","label":"contains","inVs":[4,7,10,12,15,18,21,23],"outV":1}
+        {"id":27,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\n#[allow]\n```\n\n---\n\nValid forms are:\n\n* \\#\\[allow(lint1, lint2, ..., /\\*opt\\*/ reason = \"...\")\\]"}}}
+        {"id":28,"type":"edge","label":"textDocument/hover","inV":27,"outV":5}
+        {"id":29,"type":"vertex","label":"referenceResult"}
+        {"id":30,"type":"edge","label":"textDocument/references","inV":29,"outV":5}
+        {"id":31,"type":"edge","label":"item","document":1,"property":"references","inVs":[4],"outV":29}
+        {"id":32,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nmacro_rules! generate_const_from_identifier\n```"}}}
+        {"id":33,"type":"edge","label":"textDocument/hover","inV":32,"outV":8}
+        {"id":34,"type":"vertex","label":"packageInformation","name":"foo","manager":"cargo","version":"0.0.0"}
+        {"id":35,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::generate_const_from_identifier","unique":"scheme","kind":"export"}
+        {"id":36,"type":"edge","label":"packageInformation","inV":34,"outV":35}
+        {"id":37,"type":"edge","label":"moniker","inV":35,"outV":8}
+        {"id":38,"type":"vertex","label":"definitionResult"}
+        {"id":39,"type":"edge","label":"item","document":1,"inVs":[7],"outV":38}
+        {"id":40,"type":"edge","label":"textDocument/definition","inV":38,"outV":8}
+        {"id":41,"type":"vertex","label":"referenceResult"}
+        {"id":42,"type":"edge","label":"textDocument/references","inV":41,"outV":8}
+        {"id":43,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[7],"outV":41}
+        {"id":44,"type":"edge","label":"item","document":1,"property":"references","inVs":[10,21],"outV":41}
+        {"id":45,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nconst REQ_001: &str = \"encoded_data\"\n```"}}}
+        {"id":46,"type":"edge","label":"textDocument/hover","inV":45,"outV":13}
+        {"id":47,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::REQ_001","unique":"scheme","kind":"export"}
+        {"id":48,"type":"edge","label":"packageInformation","inV":34,"outV":47}
+        {"id":49,"type":"edge","label":"moniker","inV":47,"outV":13}
+        {"id":50,"type":"vertex","label":"definitionResult"}
+        {"id":51,"type":"edge","label":"item","document":1,"inVs":[12],"outV":50}
+        {"id":52,"type":"edge","label":"textDocument/definition","inV":50,"outV":13}
+        {"id":53,"type":"vertex","label":"referenceResult"}
+        {"id":54,"type":"edge","label":"textDocument/references","inV":53,"outV":13}
+        {"id":55,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[12],"outV":53}
+        {"id":56,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo\n```\n\n```rust\nmod tests\n```"}}}
+        {"id":57,"type":"edge","label":"textDocument/hover","inV":56,"outV":16}
+        {"id":58,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::tests","unique":"scheme","kind":"export"}
+        {"id":59,"type":"edge","label":"packageInformation","inV":34,"outV":58}
+        {"id":60,"type":"edge","label":"moniker","inV":58,"outV":16}
+        {"id":61,"type":"vertex","label":"definitionResult"}
+        {"id":62,"type":"edge","label":"item","document":1,"inVs":[15],"outV":61}
+        {"id":63,"type":"edge","label":"textDocument/definition","inV":61,"outV":16}
+        {"id":64,"type":"vertex","label":"referenceResult"}
+        {"id":65,"type":"edge","label":"textDocument/references","inV":64,"outV":16}
+        {"id":66,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[15],"outV":64}
+        {"id":67,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nextern crate foo\n```"}}}
+        {"id":68,"type":"edge","label":"textDocument/hover","inV":67,"outV":19}
+        {"id":69,"type":"vertex","label":"definitionResult"}
+        {"id":70,"type":"vertex","label":"range","start":{"line":0,"character":0},"end":{"line":13,"character":0}}
+        {"id":71,"type":"edge","label":"contains","inVs":[70],"outV":1}
+        {"id":72,"type":"edge","label":"item","document":1,"inVs":[70],"outV":69}
+        {"id":73,"type":"edge","label":"textDocument/definition","inV":69,"outV":19}
+        {"id":74,"type":"vertex","label":"referenceResult"}
+        {"id":75,"type":"edge","label":"textDocument/references","inV":74,"outV":19}
+        {"id":76,"type":"edge","label":"item","document":1,"property":"references","inVs":[18],"outV":74}
+        {"id":77,"type":"vertex","label":"hoverResult","result":{"contents":{"kind":"markdown","value":"\n```rust\nfoo::tests\n```\n\n```rust\nconst REQ_002: &str = \"encoded_data\"\n```"}}}
+        {"id":78,"type":"edge","label":"textDocument/hover","inV":77,"outV":24}
+        {"id":79,"type":"vertex","label":"moniker","scheme":"rust-analyzer","identifier":"foo::tests::REQ_002","unique":"scheme","kind":"export"}
+        {"id":80,"type":"edge","label":"packageInformation","inV":34,"outV":79}
+        {"id":81,"type":"edge","label":"moniker","inV":79,"outV":24}
+        {"id":82,"type":"vertex","label":"definitionResult"}
+        {"id":83,"type":"edge","label":"item","document":1,"inVs":[23],"outV":82}
+        {"id":84,"type":"edge","label":"textDocument/definition","inV":82,"outV":24}
+        {"id":85,"type":"vertex","label":"referenceResult"}
+        {"id":86,"type":"edge","label":"textDocument/references","inV":85,"outV":24}
+        {"id":87,"type":"edge","label":"item","document":1,"property":"definitions","inVs":[23],"outV":85}
     "#]].assert_eq(stdout);
 }
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 866379d940..ca59658359 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -258,15 +258,7 @@ impl ChangeFixture {
                 let to_id = crates[&to];
                 let sysroot = crate_graph[to_id].origin.is_lang();
                 crate_graph
-                    .add_dep(
-                        from_id,
-                        Dependency::with_prelude(
-                            CrateName::new(&to).unwrap(),
-                            to_id,
-                            prelude,
-                            sysroot,
-                        ),
-                    )
+                    .add_dep(from_id, Dependency::with_prelude(to.clone(), to_id, prelude, sysroot))
                     .unwrap();
             }
         }