Repository: rust-lang/rust-analyzer
Pull request #16920 (2024-03-22 10:47:56)

internal: Fix new nightly clippy lints

Veykril: @bors r+
bors: :pushpin: Commit c68316ac78628b84105ed1c95e2c8f3d7ca78db2 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 c68316ac78628b84105ed1c95e2c8f3d7ca78db2 -->
<!-- homu: {"type":"Approved","sha":"c68316ac78628b84105ed1c95e2c8f3d7ca78db2","approver":"Veykril","queue":"https://bors.rust-lang.org/homu/queue/rust-analyzer"} -->
bors: :hourglass: Testing commit c68316ac78628b84105ed1c95e2c8f3d7ca78db2 with merge 425fc74351c961ad5842913d6b6088eb0e3488a3...
<!-- homu: {"type":"BuildStarted","head_sha":"c68316ac78628b84105ed1c95e2c8f3d7ca78db2","merge_sha":"425fc74351c961ad5842913d6b6088eb0e3488a3"} -->
bors: :broken_heart: Test failed - [checks-actions](https://github.com/rust-lang/rust-analyzer/actions/runs/8389152140/job/22975121476)
<!-- homu: {"type":"BuildFailed","builder_url":"https://github.com/rust-lang/rust-analyzer/actions/runs/8389152140/job/22975121476","builder_name":"checks-actions"} -->

Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 0d99d06bcd..97c1b64494 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -22,8 +22,6 @@ Otherwise please try to provide information which will help us to fix the issue
 
 **rustc version**: (eg. output of `rustc -V`)
 
-**editor or extension**: (eg. VSCode, Vim, Emacs, etc. For VSCode users, specify your extension version; for users of other editors, provide the distribution if applicable)
-
 **relevant settings**: (eg. client settings, or environment variables like `CARGO`, `RUSTC`, `RUSTUP_HOME` or `CARGO_HOME`)
 
 **repository link (if public, optional)**: (eg. [rust-analyzer](https://github.com/rust-lang/rust-analyzer))
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 11014338d7..dc0a6c2d91 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -36,7 +36,6 @@ jobs:
           - os: ubuntu-20.04
             target: x86_64-unknown-linux-gnu
             code-target: linux-x64
-            container: rockylinux:8
           - os: ubuntu-20.04
             target: aarch64-unknown-linux-gnu
             code-target: linux-arm64
@@ -59,18 +58,10 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v4
+        uses: actions/checkout@v3
         with:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
-      - name: Install toolchain dependencies
-        if: matrix.container == 'rockylinux:8'
-        shell: bash
-        run: |
-          dnf install -y gcc
-          curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --profile minimal --default-toolchain none -y
-          echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH
-
       - name: Install Rust toolchain
         run: |
           rustup update --no-self-update stable
@@ -78,9 +69,9 @@ jobs:
           rustup component add rust-src
 
       - name: Install Node.js
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@v3
         with:
-          node-version: 18
+          node-version: 16
 
       - name: Update apt repositories
         if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf'
@@ -190,7 +181,7 @@ jobs:
       - name: Install Nodejs
         uses: actions/setup-node@v4
         with:
-          node-version: 20
+          node-version: 18
 
       - run: echo "TAG=$(date --iso -u)" >> $GITHUB_ENV
         if: github.ref == 'refs/heads/release'
diff --git a/Cargo.toml b/Cargo.toml
index d9343d2b96..99338d9d97 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -188,6 +188,8 @@ enum_variant_names = "allow"
 new_ret_no_self = "allow"
 # Has a bunch of false positives
 useless_asref = "allow"
+# Has false positives
+assigning_clones = "allow"
 
 ## Following lints should be tackled at some point
 too_many_arguments = "allow"
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 4638b37719..1d2c7c3a55 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -22,8 +22,8 @@ use crate::{
     lower::LowerCtx,
     nameres::{DefMap, MacroSubNs},
     type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
-    AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
-    LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
+    AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
+    TypeOrConstParamId, TypeParamId,
 };
 
 /// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -102,52 +102,6 @@ impl TypeOrConstParamData {
 
 impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub enum GenericParamData {
-    TypeParamData(TypeParamData),
-    ConstParamData(ConstParamData),
-    LifetimeParamData(LifetimeParamData),
-}
-
-impl GenericParamData {
-    pub fn name(&self) -> Option<&Name> {
-        match self {
-            GenericParamData::TypeParamData(it) => it.name.as_ref(),
-            GenericParamData::ConstParamData(it) => Some(&it.name),
-            GenericParamData::LifetimeParamData(it) => Some(&it.name),
-        }
-    }
-
-    pub fn type_param(&self) -> Option<&TypeParamData> {
-        match self {
-            GenericParamData::TypeParamData(it) => Some(it),
-            _ => None,
-        }
-    }
-
-    pub fn const_param(&self) -> Option<&ConstParamData> {
-        match self {
-            GenericParamData::ConstParamData(it) => Some(it),
-            _ => None,
-        }
-    }
-
-    pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
-        match self {
-            GenericParamData::LifetimeParamData(it) => Some(it),
-            _ => None,
-        }
-    }
-}
-
-impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
-
-pub enum GenericParamDataRef<'a> {
-    TypeParamData(&'a TypeParamData),
-    ConstParamData(&'a ConstParamData),
-    LifetimeParamData(&'a LifetimeParamData),
-}
-
 /// Data about the generic parameters of a function, struct, impl, etc.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct GenericParams {
@@ -404,15 +358,6 @@ impl GenericParamsCollector {
 }
 
 impl GenericParams {
-    /// Number of Generic parameters (type_or_consts + lifetimes)
-    pub fn len(&self) -> usize {
-        self.type_or_consts.len() + self.lifetimes.len()
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
     /// Iterator of type_or_consts field
     pub fn iter(
         &self,
@@ -420,13 +365,6 @@ impl GenericParams {
         self.type_or_consts.iter()
     }
 
-    /// Iterator of lifetimes field
-    pub fn iter_lt(
-        &self,
-    ) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
-        self.lifetimes.iter()
-    }
-
     pub(crate) fn generic_params_query(
         db: &dyn DefDatabase,
         def: GenericDefId,
@@ -569,18 +507,4 @@ impl GenericParams {
             .then(|| id)
         })
     }
-
-    pub fn find_lifetime_by_name(
-        &self,
-        name: &Name,
-        parent: GenericDefId,
-    ) -> Option<LifetimeParamId> {
-        self.lifetimes.iter().find_map(|(id, p)| {
-            if &p.name == name {
-                Some(LifetimeParamId { local_id: id, parent })
-            } else {
-                None
-            }
-        })
-    }
 }
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 0c84057950..953bf6b85d 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -526,7 +526,7 @@ impl Printer<'_> {
     }
 
     fn print_generic_params(&mut self, params: &GenericParams) {
-        if params.is_empty() {
+        if params.type_or_consts.is_empty() && params.lifetimes.is_empty() {
             return;
         }
 
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index fadab858aa..226d6f513f 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -24,7 +24,6 @@ use crate::{
     nameres::{DefMap, MacroSubNs},
     path::{ModPath, Path, PathKind},
     per_ns::PerNs,
-    type_ref::LifetimeRef,
     visibility::{RawVisibility, Visibility},
     AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
     ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
@@ -121,12 +120,6 @@ pub enum ValueNs {
     GenericParam(ConstParamId),
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LifetimeNs {
-    Static,
-    LifetimeParam(LifetimeParamId),
-}
-
 impl Resolver {
     /// Resolve known trait from std, like `std::futures::Future`
     pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
@@ -425,19 +418,6 @@ impl Resolver {
         self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
     }
 
-    pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
-        if lifetime.name == name::known::STATIC_LIFETIME {
-            return Some(LifetimeNs::Static);
-        }
-
-        self.scopes().find_map(|scope| match scope {
-            Scope::GenericParams { def, params } => {
-                params.find_lifetime_by_name(&lifetime.name, *def).map(LifetimeNs::LifetimeParam)
-            }
-            _ => None,
-        })
-    }
-
     /// Returns a set of names available in the current scope.
     ///
     /// Note that this is a somewhat fuzzy concept -- internally, the compiler
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index cb118a3684..c485c9b2e8 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -9,21 +9,21 @@ use chalk_ir::{
     AdtId, DebruijnIndex, Scalar,
 };
 use hir_def::{
-    builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
+    builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
+    GenericDefId, TraitId, TypeAliasId,
 };
 use smallvec::SmallVec;
 
 use crate::{
-    consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
-    infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
-    Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
-    Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
+    consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
+    to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
+    GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
+    TyKind,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum ParamKind {
     Type,
-    Lifetime,
     Const(Ty),
 }
 
@@ -107,9 +107,6 @@ impl<D> TyBuilder<D> {
             ParamKind::Const(ty) => {
                 BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
             }
-            ParamKind::Lifetime => {
-                BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
-            }
         });
         this.vec.extend(filler.take(this.remaining()).casted(Interner));
         assert_eq!(this.remaining(), 0);
@@ -122,7 +119,6 @@ impl<D> TyBuilder<D> {
         let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
             ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-            ParamKind::Lifetime => error_lifetime().cast(Interner),
         });
         this.vec.extend(filler.casted(Interner));
         assert_eq!(this.remaining(), 0);
@@ -134,7 +130,6 @@ impl<D> TyBuilder<D> {
         self.fill(|x| match x {
             ParamKind::Type => table.new_type_var().cast(Interner),
             ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
-            ParamKind::Lifetime => table.new_lifetime_var().cast(Interner),
         })
     }
 
@@ -147,8 +142,7 @@ impl<D> TyBuilder<D> {
     fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
         match (a.data(Interner), e) {
             (GenericArgData::Ty(_), ParamKind::Type)
-            | (GenericArgData::Const(_), ParamKind::Const(_))
-            | (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (),
+            | (GenericArgData::Const(_), ParamKind::Const(_)) => (),
             _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
         }
     }
@@ -207,11 +201,10 @@ impl TyBuilder<()> {
         Substitution::from_iter(
             Interner,
             params.iter_id().map(|id| match id {
-                GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
-                GenericParamId::ConstParamId(id) => {
+                either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
+                either::Either::Right(id) => {
                     unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
                 }
-                GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
             }),
         )
     }
@@ -226,10 +219,11 @@ impl TyBuilder<()> {
         assert!(generics.parent_generics().is_some() == parent_subst.is_some());
         let params = generics
             .iter_self()
-            .map(|(id, _data)| match id {
-                GenericParamId::TypeParamId(_) => ParamKind::Type,
-                GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
-                GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
+            .map(|(id, data)| match data {
+                TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
+                TypeOrConstParamData::ConstParamData(_) => {
+                    ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
+                }
             })
             .collect();
         TyBuilder::new((), params, parent_subst)
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 0b24fe7227..f45beb4c92 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -3,7 +3,7 @@
 use std::fmt;
 use tracing::debug;
 
-use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
+use hir_def::{DefWithBodyId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
 use rustc_hash::FxHashMap;
 use rustc_pattern_analysis::{
     constructor::{Constructor, ConstructorSet, VariantVisibility},
@@ -36,24 +36,6 @@ pub(crate) type WitnessPat<'p> = rustc_pattern_analysis::pat::WitnessPat<MatchCh
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub(crate) enum Void {}
 
-/// An index type for enum variants. This ranges from 0 to `variants.len()`, whereas `EnumVariantId`
-/// can take arbitrary large values (and hence mustn't be used with `IndexVec`/`BitSet`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub(crate) struct EnumVariantContiguousIndex(usize);
-
-impl EnumVariantContiguousIndex {
-    fn from_enum_variant_id(db: &dyn HirDatabase, target_evid: EnumVariantId) -> Self {
-        // Find the index of this variant in the list of variants.
-        use hir_def::Lookup;
-        let i = target_evid.lookup(db.upcast()).index as usize;
-        EnumVariantContiguousIndex(i)
-    }
-
-    fn to_enum_variant_id(self, db: &dyn HirDatabase, eid: EnumId) -> EnumVariantId {
-        db.enum_data(eid).variants[self.0].0
-    }
-}
-
 #[derive(Clone)]
 pub(crate) struct MatchCheckCtx<'p> {
     module: ModuleId,
@@ -107,18 +89,9 @@ impl<'p> MatchCheckCtx<'p> {
         }
     }
 
-    fn variant_id_for_adt(
-        db: &'p dyn HirDatabase,
-        ctor: &Constructor<Self>,
-        adt: hir_def::AdtId,
-    ) -> Option<VariantId> {
+    fn variant_id_for_adt(ctor: &Constructor<Self>, adt: hir_def::AdtId) -> Option<VariantId> {
         match ctor {
-            Variant(id) => {
-                let hir_def::AdtId::EnumId(eid) = adt else {
-                    panic!("bad constructor {ctor:?} for adt {adt:?}")
-                };
-                Some(id.to_enum_variant_id(db, eid).into())
-            }
+            &Variant(id) => Some(id.into()),
             Struct | UnionField => match adt {
                 hir_def::AdtId::EnumId(_) => None,
                 hir_def::AdtId::StructId(id) => Some(id.into()),
@@ -202,24 +175,19 @@ impl<'p> MatchCheckCtx<'p> {
                         ctor = Struct;
                         arity = 1;
                     }
-                    &TyKind::Adt(AdtId(adt), _) => {
+                    &TyKind::Adt(adt, _) => {
                         ctor = match pat.kind.as_ref() {
-                            PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
+                            PatKind::Leaf { .. } if matches!(adt.0, hir_def::AdtId::UnionId(_)) => {
                                 UnionField
                             }
                             PatKind::Leaf { .. } => Struct,
-                            PatKind::Variant { enum_variant, .. } => {
-                                Variant(EnumVariantContiguousIndex::from_enum_variant_id(
-                                    self.db,
-                                    *enum_variant,
-                                ))
-                            }
+                            PatKind::Variant { enum_variant, .. } => Variant(*enum_variant),
                             _ => {
                                 never!();
                                 Wildcard
                             }
                         };
-                        let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap();
+                        let variant = Self::variant_id_for_adt(&ctor, adt.0).unwrap();
                         arity = variant.variant_data(self.db.upcast()).fields().len();
                     }
                     _ => {
@@ -271,7 +239,7 @@ impl<'p> MatchCheckCtx<'p> {
                     PatKind::Deref { subpattern: subpatterns.next().unwrap() }
                 }
                 TyKind::Adt(adt, substs) => {
-                    let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
+                    let variant = Self::variant_id_for_adt(pat.ctor(), adt.0).unwrap();
                     let subpatterns = self
                         .list_variant_fields(pat.ty(), variant)
                         .zip(subpatterns)
@@ -309,7 +277,7 @@ impl<'p> MatchCheckCtx<'p> {
 impl<'p> PatCx for MatchCheckCtx<'p> {
     type Error = ();
     type Ty = Ty;
-    type VariantIdx = EnumVariantContiguousIndex;
+    type VariantIdx = EnumVariantId;
     type StrLit = Void;
     type ArmData = ();
     type PatData = PatData<'p>;
@@ -335,7 +303,7 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
                         // patterns. If we're here we can assume this is a box pattern.
                         1
                     } else {
-                        let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
+                        let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
                         variant.variant_data(self.db.upcast()).fields().len()
                     }
                 }
@@ -375,7 +343,7 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
                         let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
                         single(subst_ty)
                     } else {
-                        let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
+                        let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
                         let (adt, _) = ty.as_adt().unwrap();
 
                         let adt_is_local =
@@ -453,7 +421,7 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
                     ConstructorSet::NoConstructors
                 } else {
                     let mut variants = FxHashMap::default();
-                    for (i, &(variant, _)) in enum_data.variants.iter().enumerate() {
+                    for &(variant, _) in enum_data.variants.iter() {
                         let is_uninhabited =
                             is_enum_variant_uninhabited_from(variant, subst, cx.module, cx.db);
                         let visibility = if is_uninhabited {
@@ -461,7 +429,7 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
                         } else {
                             VariantVisibility::Visible
                         };
-                        variants.insert(EnumVariantContiguousIndex(i), visibility);
+                        variants.insert(variant, visibility);
                     }
 
                     ConstructorSet::Variants {
@@ -485,10 +453,10 @@ impl<'p> PatCx for MatchCheckCtx<'p> {
         f: &mut fmt::Formatter<'_>,
         pat: &rustc_pattern_analysis::pat::DeconstructedPat<Self>,
     ) -> fmt::Result {
-        let db = pat.data().db;
         let variant =
-            pat.ty().as_adt().and_then(|(adt, _)| Self::variant_id_for_adt(db, pat.ctor(), adt));
+            pat.ty().as_adt().and_then(|(adt, _)| Self::variant_id_for_adt(pat.ctor(), adt));
 
+        let db = pat.data().db;
         if let Some(variant) = variant {
             match variant {
                 VariantId::EnumVariantId(v) => {
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 8740ae6797..269db57bc3 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -938,32 +938,18 @@ impl HirDisplay for Ty {
                 f.end_location_link();
                 if parameters.len(Interner) > 0 {
                     let generics = generics(db.upcast(), def.into());
-                    let (
-                        parent_params,
-                        self_param,
-                        type_params,
-                        const_params,
-                        _impl_trait_params,
-                        lifetime_params,
-                    ) = generics.provenance_split();
-                    let total_len =
-                        parent_params + self_param + type_params + const_params + lifetime_params;
+                    let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
+                        generics.provenance_split();
+                    let total_len = parent_params + self_param + type_params + const_params;
                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
                     if total_len > 0 {
-                        // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
+                        // `parameters` are in the order of fn's params (including impl traits),
                         // parent's params (those from enclosing impl or trait, if any).
                         let parameters = parameters.as_slice(Interner);
                         let fn_params_len = self_param + type_params + const_params;
-                        // This will give slice till last type or const
                         let fn_params = parameters.get(..fn_params_len);
-                        let fn_lt_params =
-                            parameters.get(fn_params_len..(fn_params_len + lifetime_params));
                         let parent_params = parameters.get(parameters.len() - parent_params..);
-                        let params = parent_params
-                            .into_iter()
-                            .chain(fn_lt_params)
-                            .chain(fn_params)
-                            .flatten();
+                        let params = parent_params.into_iter().chain(fn_params).flatten();
                         write!(f, "<")?;
                         f.write_joined(params, ", ")?;
                         write!(f, ">")?;
@@ -1322,17 +1308,8 @@ fn hir_fmt_generics(
     generic_def: Option<hir_def::GenericDefId>,
 ) -> Result<(), HirDisplayError> {
     let db = f.db;
-    if parameters.len(Interner) > 0 {
-        use std::cmp::Ordering;
-        let param_compare =
-            |a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) {
-                (crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => {
-                    Ordering::Equal
-                }
-                (crate::GenericArgData::Lifetime(_), _) => Ordering::Less,
-                (_, crate::GenericArgData::Lifetime(_)) => Ordering::Less,
-                (_, _) => Ordering::Equal,
-            };
+    let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
+    if parameters.len(Interner) + lifetime_args_count > 0 {
         let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
             match generic_def
                 .map(|generic_def_id| db.generic_defaults(generic_def_id))
@@ -1358,11 +1335,6 @@ fn hir_fmt_generics(
                                 return true;
                             }
                         }
-                        if parameter.lifetime(Interner).map(|it| it.data(Interner))
-                            == Some(&crate::LifetimeData::Static)
-                        {
-                            return true;
-                        }
                         let default_parameter = match default_parameters.get(i) {
                             Some(it) => it,
                             None => return true,
@@ -1383,12 +1355,16 @@ fn hir_fmt_generics(
         } else {
             parameters.as_slice(Interner)
         };
-        //FIXME: Should handle the ordering of lifetimes when creating substitutions
-        let mut parameters_to_write = parameters_to_write.to_vec();
-        parameters_to_write.sort_by(param_compare);
-        if !parameters_to_write.is_empty() {
+        if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
             write!(f, "<")?;
             let mut first = true;
+            for _ in 0..lifetime_args_count {
+                if !first {
+                    write!(f, ", ")?;
+                }
+                first = false;
+                write!(f, "'_")?;
+            }
             for generic_arg in parameters_to_write {
                 if !first {
                     write!(f, ", ")?;
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index be3b50e141..29e1279945 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -42,7 +42,7 @@ use hir_def::{
     layout::Integer,
     path::{ModPath, Path},
     resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
-    type_ref::{LifetimeRef, TypeRef},
+    type_ref::TypeRef,
     AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
     TupleFieldId, TupleId, TypeAliasId, VariantId,
 };
@@ -1037,12 +1037,6 @@ impl<'a> InferenceContext<'a> {
         self.result.standard_types.unknown.clone()
     }
 
-    fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
-        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
-        let lt = ctx.lower_lifetime(lifetime_ref);
-        self.insert_type_vars(lt)
-    }
-
     /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
     fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
         self.table.insert_type_vars_shallow(ty)
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 35d5967935..a3dab1fd9d 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -8,12 +8,13 @@ use std::{
 use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
 use either::Either;
 use hir_def::{
+    generics::TypeOrConstParamData,
     hir::{
         ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
     },
     lang_item::{LangItem, LangItemTarget},
-    path::{GenericArgs, Path},
-    BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+    path::{GenericArg, GenericArgs, Path},
+    BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
 };
 use hir_expand::name::{name, Name};
 use stdx::always;
@@ -1815,17 +1816,10 @@ impl InferenceContext<'_> {
         def_generics: Generics,
         generic_args: Option<&GenericArgs>,
     ) -> Substitution {
-        let (
-            parent_params,
-            self_params,
-            type_params,
-            const_params,
-            impl_trait_params,
-            lifetime_params,
-        ) = def_generics.provenance_split();
+        let (parent_params, self_params, type_params, const_params, impl_trait_params) =
+            def_generics.provenance_split();
         assert_eq!(self_params, 0); // method shouldn't have another Self param
-        let total_len =
-            parent_params + type_params + const_params + impl_trait_params + lifetime_params;
+        let total_len = parent_params + type_params + const_params + impl_trait_params;
         let mut substs = Vec::with_capacity(total_len);
 
         // handle provided arguments
@@ -1834,7 +1828,8 @@ impl InferenceContext<'_> {
             for (arg, kind_id) in generic_args
                 .args
                 .iter()
-                .take(type_params + const_params + lifetime_params)
+                .filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
+                .take(type_params + const_params)
                 .zip(def_generics.iter_id())
             {
                 if let Some(g) = generic_arg_to_chalk(
@@ -1855,7 +1850,6 @@ impl InferenceContext<'_> {
                             DebruijnIndex::INNERMOST,
                         )
                     },
-                    |this, lt_ref| this.make_lifetime(lt_ref),
                 ) {
                     substs.push(g);
                 }
@@ -1864,17 +1858,16 @@ impl InferenceContext<'_> {
 
         // Handle everything else as unknown. This also handles generic arguments for the method's
         // parent (impl or trait), which should come after those for the method.
-        for (id, _data) in def_generics.iter().skip(substs.len()) {
-            match id {
-                GenericParamId::TypeParamId(_) => {
+        for (id, data) in def_generics.iter().skip(substs.len()) {
+            match data {
+                TypeOrConstParamData::TypeParamData(_) => {
                     substs.push(self.table.new_type_var().cast(Interner))
                 }
-                GenericParamId::ConstParamId(id) => {
-                    substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
-                }
-                GenericParamId::LifetimeParamId(_) => {
-                    substs.push(self.table.new_lifetime_var().cast(Interner))
-                }
+                TypeOrConstParamData::ConstParamData(_) => substs.push(
+                    self.table
+                        .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
+                        .cast(Interner),
+                ),
             }
         }
         assert_eq!(substs.len(), total_len);
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index 09a4d998ee..30005a2551 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -149,7 +149,7 @@ impl InferenceContext<'_> {
         expected: &Ty,
         default_bm: T::BindingMode,
         id: T,
-        subs: impl Iterator<Item = (Name, T)> + ExactSizeIterator,
+        subs: impl ExactSizeIterator<Item = (Name, T)>,
     ) -> Ty {
         let (ty, def) = self.resolve_variant(path, false);
         if let Some(variant) = def {
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 9a1835b625..44b35b2ebb 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -11,7 +11,7 @@ use stdx::never;
 
 use crate::{
     builder::ParamKind,
-    consteval, error_lifetime,
+    consteval,
     method_resolution::{self, VisibleFromModule},
     to_chalk_trait_id,
     utils::generics,
@@ -111,7 +111,6 @@ impl InferenceContext<'_> {
                 it.next().unwrap_or_else(|| match x {
                     ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
                     ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
-                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 })
             })
             .build();
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index afb89fe1e5..93fd54455b 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -16,12 +16,12 @@ use triomphe::Arc;
 
 use super::{InferOk, InferResult, InferenceContext, TypeError};
 use crate::{
-    consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts,
-    static_lifetime, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical,
-    Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData,
-    Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy,
-    ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
-    TyKind, VariableKind, WhereClause,
+    consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
+    to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
+    DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
+    InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar,
+    Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
+    WhereClause,
 };
 
 impl InferenceContext<'_> {
@@ -807,7 +807,6 @@ impl<'a> InferenceTable<'a> {
             .fill(|it| {
                 let arg = match it {
                     ParamKind::Type => self.new_type_var(),
-                    ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
                     ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
                 };
                 arg_tys.push(arg.clone());
@@ -862,16 +861,11 @@ impl<'a> InferenceTable<'a> {
     where
         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
     {
-        fold_generic_args(
+        fold_tys_and_consts(
             ty,
-            |arg, _| match arg {
-                GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)),
-                // FIXME: insert lifetime vars once LifetimeData::InferenceVar
-                // and specific error variant for lifetimes start being constructed
-                GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt),
-                GenericArgData::Const(c) => {
-                    GenericArgData::Const(self.insert_const_vars_shallow(c))
-                }
+            |it, _| match it {
+                Either::Left(ty) => Either::Left(self.insert_type_vars_shallow(ty)),
+                Either::Right(c) => Either::Right(self.insert_const_vars_shallow(c)),
             },
             DebruijnIndex::INNERMOST,
         )
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index ba64f5c8d7..d6d5c16ae7 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -15,8 +15,10 @@ extern crate rustc_abi;
 #[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_abi as rustc_abi;
 
-// Use the crates.io version unconditionally until the API settles enough that we can switch to
-// using the in-tree one.
+#[cfg(feature = "in-rust-tree")]
+extern crate rustc_pattern_analysis;
+
+#[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
 
 mod builder;
@@ -90,8 +92,8 @@ pub use lower::{
 };
 pub use mapping::{
     from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
-    lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
-    to_foreign_def_id, to_placeholder_idx,
+    lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
+    to_placeholder_idx,
 };
 pub use method_resolution::check_orphan_rules;
 pub use traits::TraitEnvironment;
@@ -335,23 +337,11 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
     generics: &Generics,
     value: T,
 ) -> Binders<T> {
-    let it = generics.iter_id().take(count);
-
-    Binders::new(
-        VariableKinds::from_iter(
-            Interner,
-            it.map(|x| match x {
-                hir_def::GenericParamId::ConstParamId(id) => {
-                    chalk_ir::VariableKind::Const(db.const_param_ty(id))
-                }
-                hir_def::GenericParamId::TypeParamId(_) => {
-                    chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
-                }
-                hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
-            }),
-        ),
-        value,
-    )
+    let it = generics.iter_id().take(count).map(|id| match id {
+        Either::Left(_) => None,
+        Either::Right(id) => Some(db.const_param_ty(id)),
+    });
+    crate::make_type_and_const_binders(it, value)
 }
 
 pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
@@ -621,10 +611,6 @@ pub fn static_lifetime() -> Lifetime {
     LifetimeData::Static.intern(Interner)
 }
 
-pub fn error_lifetime() -> Lifetime {
-    static_lifetime()
-}
-
 pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
     t: T,
     for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
@@ -714,55 +700,6 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
     t.fold_with(&mut TyFolder(f), binders)
 }
 
-pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
-    t: T,
-    f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData,
-    binders: DebruijnIndex,
-) -> T {
-    use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
-    #[derive(chalk_derive::FallibleTypeFolder)]
-    #[has_interner(Interner)]
-    struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F);
-    impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner>
-        for TyFolder<F>
-    {
-        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
-            self
-        }
-
-        fn interner(&self) -> Interner {
-            Interner
-        }
-
-        fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
-            let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
-            self.0(GenericArgData::Ty(ty), outer_binder)
-                .intern(Interner)
-                .ty(Interner)
-                .unwrap()
-                .clone()
-        }
-
-        fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
-            self.0(GenericArgData::Const(c), outer_binder)
-                .intern(Interner)
-                .constant(Interner)
-                .unwrap()
-                .clone()
-        }
-
-        fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime {
-            let lt = lt.super_fold_with(self.as_dyn(), outer_binder);
-            self.0(GenericArgData::Lifetime(lt), outer_binder)
-                .intern(Interner)
-                .lifetime(Interner)
-                .unwrap()
-                .clone()
-        }
-    }
-    t.fold_with(&mut TyFolder(f), binders)
-}
-
 /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
 /// ensures there are no unbound variables or inference variables anywhere in
 /// the `t`.
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 25ccc84c13..0bc739e696 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -24,20 +24,17 @@ use hir_def::{
     data::adt::StructKind,
     expander::Expander,
     generics::{
-        GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
-        WherePredicateTypeTarget,
+        TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     nameres::MacroSubNs,
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
-    resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
-    type_ref::{
-        ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
-    },
+    resolver::{HasResolver, Resolver, TypeNs},
+    type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
     AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
-    GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId,
-    Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
-    UnionId, VariantId,
+    GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
+    ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
+    TypeParamId, UnionId, VariantId,
 };
 use hir_expand::{name::Name, ExpandResult};
 use intern::Interned;
@@ -55,18 +52,18 @@ use crate::{
         unknown_const_as_generic,
     },
     db::HirDatabase,
-    error_lifetime, make_binders,
-    mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
+    make_binders,
+    mapping::{from_chalk_trait_id, ToChalk},
     static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
+    utils::Generics,
     utils::{
-        all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
+        all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
         InTypeConstIdMetadata,
     },
     AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
-    FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
-    LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
-    QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
-    TyKind, WhereClause,
+    FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
+    PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
+    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
 };
 
 #[derive(Debug)]
@@ -278,11 +275,9 @@ impl<'a> TyLoweringContext<'a> {
                 let inner_ty = self.lower_ty(inner);
                 TyKind::Slice(inner_ty).intern(Interner)
             }
-            TypeRef::Reference(inner, lifetime, mutability) => {
+            TypeRef::Reference(inner, _, mutability) => {
                 let inner_ty = self.lower_ty(inner);
-                // FIXME: It should infer the eldided lifetimes instead of stubbing with static
-                let lifetime =
-                    lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
+                let lifetime = static_lifetime();
                 TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
                     .intern(Interner)
             }
@@ -356,18 +351,13 @@ impl<'a> TyLoweringContext<'a> {
                                 .filter(|(_, data)| {
                                     matches!(
                                         data,
-                                        GenericParamDataRef::TypeParamData(data)
+                                        TypeOrConstParamData::TypeParamData(data)
                                         if data.provenance == TypeParamProvenance::ArgumentImplTrait
                                     )
                                 })
                                 .nth(idx as usize)
                                 .map_or(TyKind::Error, |(id, _)| {
-                                    if let GenericParamId::TypeParamId(id) = id {
-                                        TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
-                                    } else {
-                                        // we just filtered them out
-                                        unreachable!("Unexpected lifetime or const argument");
-                                    }
+                                    TyKind::Placeholder(to_placeholder_idx(self.db, id))
                                 });
                             param.intern(Interner)
                         } else {
@@ -384,12 +374,11 @@ impl<'a> TyLoweringContext<'a> {
                             list_params,
                             const_params,
                             _impl_trait_params,
-                            _lifetime_params,
                         ) = if let Some(def) = self.resolver.generic_def() {
                             let generics = generics(self.db.upcast(), def);
                             generics.provenance_split()
                         } else {
-                            (0, 0, 0, 0, 0, 0)
+                            (0, 0, 0, 0, 0)
                         };
                         TyKind::BoundVar(BoundVar::new(
                             self.in_binders,
@@ -826,16 +815,9 @@ impl<'a> TyLoweringContext<'a> {
             return Substitution::empty(Interner);
         };
         let def_generics = generics(self.db.upcast(), def);
-        let (
-            parent_params,
-            self_params,
-            type_params,
-            const_params,
-            impl_trait_params,
-            lifetime_params,
-        ) = def_generics.provenance_split();
-        let item_len =
-            self_params + type_params + const_params + impl_trait_params + lifetime_params;
+        let (parent_params, self_params, type_params, const_params, impl_trait_params) =
+            def_generics.provenance_split();
+        let item_len = self_params + type_params + const_params + impl_trait_params;
         let total_len = parent_params + item_len;
 
         let ty_error = TyKind::Error.intern(Interner).cast(Interner);
@@ -850,10 +832,7 @@ impl<'a> TyLoweringContext<'a> {
                 .take(self_params)
             {
                 if let Some(id) = def_generic_iter.next() {
-                    assert!(matches!(
-                        id,
-                        GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
-                    ));
+                    assert!(id.is_left());
                     substs.push(x);
                 }
             }
@@ -886,7 +865,6 @@ impl<'a> TyLoweringContext<'a> {
                         &mut (),
                         |_, type_ref| self.lower_ty(type_ref),
                         |_, const_ref, ty| self.lower_const(const_ref, ty),
-                        |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
                     ) {
                         had_explicit_args = true;
                         substs.push(x);
@@ -896,45 +874,15 @@ impl<'a> TyLoweringContext<'a> {
                     }
                 }
             }
-
-            for arg in generic_args
-                .args
-                .iter()
-                .filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
-                .take(lifetime_params)
-            {
-                // Taking into the fact that def_generic_iter will always have lifetimes at the end
-                // Should have some test cases tho to test this behaviour more properly
-                if let Some(id) = def_generic_iter.next() {
-                    if let Some(x) = generic_arg_to_chalk(
-                        self.db,
-                        id,
-                        arg,
-                        &mut (),
-                        |_, type_ref| self.lower_ty(type_ref),
-                        |_, const_ref, ty| self.lower_const(const_ref, ty),
-                        |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
-                    ) {
-                        had_explicit_args = true;
-                        substs.push(x);
-                    } else {
-                        // Never return a None explicitly
-                        never!("Unexpected None by generic_arg_to_chalk");
-                    }
-                }
-            }
         } else {
             fill_self_params();
         }
 
         // These params include those of parent.
         let remaining_params: SmallVec<[_; 2]> = def_generic_iter
-            .map(|id| match id {
-                GenericParamId::ConstParamId(x) => {
-                    unknown_const_as_generic(self.db.const_param_ty(x))
-                }
-                GenericParamId::TypeParamId(_) => ty_error.clone(),
-                GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
+            .map(|eid| match eid {
+                Either::Left(_) => ty_error.clone(),
+                Either::Right(x) => unknown_const_as_generic(self.db.const_param_ty(x)),
             })
             .collect();
         assert_eq!(remaining_params.len() + substs.len(), total_len);
@@ -1361,33 +1309,6 @@ impl<'a> TyLoweringContext<'a> {
         });
         ImplTrait { bounds: crate::make_single_type_binders(predicates) }
     }
-
-    pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
-        match self.resolver.resolve_lifetime(lifetime) {
-            Some(resolution) => match resolution {
-                LifetimeNs::Static => static_lifetime(),
-                LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
-                    ParamLoweringMode::Placeholder => {
-                        LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
-                    }
-                    ParamLoweringMode::Variable => {
-                        let generics = generics(
-                            self.db.upcast(),
-                            self.resolver.generic_def().expect("generics in scope"),
-                        );
-                        let idx = match generics.lifetime_idx(id) {
-                            None => return error_lifetime(),
-                            Some(idx) => idx,
-                        };
-
-                        LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
-                    }
-                }
-                .intern(Interner),
-            },
-            None => error_lifetime(),
-        }
-    }
 }
 
 fn count_impl_traits(type_ref: &TypeRef) -> usize {
@@ -1770,7 +1691,7 @@ pub(crate) fn generic_defaults_query(
 
     let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
         match p {
-            GenericParamDataRef::TypeParamData(p) => {
+            TypeOrConstParamData::TypeParamData(p) => {
                 let mut ty =
                     p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
                 // Each default can only refer to previous parameters.
@@ -1779,13 +1700,13 @@ pub(crate) fn generic_defaults_query(
                 ty = fallback_bound_vars(ty, idx, parent_start_idx);
                 crate::make_binders(db, &generic_params, ty.cast(Interner))
             }
-            GenericParamDataRef::ConstParamData(p) => {
-                let GenericParamId::ConstParamId(id) = id else {
-                    unreachable!("Unexpected lifetime or type argument")
-                };
-
+            TypeOrConstParamData::ConstParamData(p) => {
                 let mut val = p.default.as_ref().map_or_else(
-                    || unknown_const_as_generic(db.const_param_ty(id)),
+                    || {
+                        unknown_const_as_generic(
+                            db.const_param_ty(ConstParamId::from_unchecked(id)),
+                        )
+                    },
                     |c| {
                         let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
                         c.cast(Interner)
@@ -1795,10 +1716,6 @@ pub(crate) fn generic_defaults_query(
                 val = fallback_bound_vars(val, idx, parent_start_idx);
                 make_binders(db, &generic_params, val)
             }
-            GenericParamDataRef::LifetimeParamData(_) => {
-                // using static because it requires defaults
-                make_binders(db, &generic_params, static_lifetime().cast(Interner))
-            }
         }
     }));
 
@@ -1815,9 +1732,8 @@ pub(crate) fn generic_defaults_recover(
     // we still need one default per parameter
     let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
         let val = match id {
-            GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
-            GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
-            GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
+            Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
+            Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
         };
         crate::make_binders(db, &generic_params, val)
     }));
@@ -2181,29 +2097,23 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
 /// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
 pub(crate) fn generic_arg_to_chalk<'a, T>(
     db: &dyn HirDatabase,
-    kind_id: GenericParamId,
+    kind_id: Either<TypeParamId, ConstParamId>,
     arg: &'a GenericArg,
     this: &mut T,
     for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
     for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
-    for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
 ) -> Option<crate::GenericArg> {
     let kind = match kind_id {
-        GenericParamId::TypeParamId(_) => ParamKind::Type,
-        GenericParamId::ConstParamId(id) => {
+        Either::Left(_) => ParamKind::Type,
+        Either::Right(id) => {
             let ty = db.const_param_ty(id);
             ParamKind::Const(ty)
         }
-        GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
     };
     Some(match (arg, kind) {
         (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
         (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
-        (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
-            for_lifetime(this, lifetime_ref).cast(Interner)
-        }
         (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
-        (GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
         (GenericArg::Type(t), ParamKind::Const(c_ty)) => {
             // We want to recover simple idents, which parser detects them
             // as types. Maybe here is not the best place to do it, but
@@ -2219,9 +2129,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
             }
             unknown_const_as_generic(c_ty)
         }
-        (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
-        (GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
-        (GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
+        (GenericArg::Lifetime(_), _) => return None,
     })
 }
 
diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs
index c61d827714..fba760974f 100644
--- a/crates/hir-ty/src/mapping.rs
+++ b/crates/hir-ty/src/mapping.rs
@@ -151,14 +151,6 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
     db.lookup_intern_lifetime_param_id(interned_id)
 }
 
-pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
-    let interned_id = db.intern_lifetime_param_id(id);
-    PlaceholderIndex {
-        ui: chalk_ir::UniverseIndex::ROOT,
-        idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
-    }
-}
-
 pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
     chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
 }
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 73b07df56f..064d317835 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -644,7 +644,7 @@ pub fn is_dyn_method(
     let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
         return None;
     };
-    let trait_params = db.generic_params(trait_id.into()).len();
+    let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
     let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
@@ -686,7 +686,7 @@ pub(crate) fn lookup_impl_method_query(
     let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
         return (func, fn_subst);
     };
-    let trait_params = db.generic_params(trait_id.into()).len();
+    let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
     let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 045ffb418c..fd98141af6 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -1931,11 +1931,7 @@ impl Evaluator<'_> {
             ty: &Ty,
             locals: &Locals,
             mm: &mut ComplexMemoryMap,
-            stack_depth_limit: usize,
         ) -> Result<()> {
-            if stack_depth_limit.checked_sub(1).is_none() {
-                return Err(MirEvalError::StackOverflow);
-            }
             match ty.kind(Interner) {
                 TyKind::Ref(_, _, t) => {
                     let size = this.size_align_of(t, locals)?;
@@ -1974,14 +1970,7 @@ impl Evaluator<'_> {
                             if let Some(ty) = check_inner {
                                 for i in 0..count {
                                     let offset = element_size * i;
-                                    rec(
-                                        this,
-                                        &b[offset..offset + element_size],
-                                        ty,
-                                        locals,
-                                        mm,
-                                        stack_depth_limit - 1,
-                                    )?;
+                                    rec(this, &b[offset..offset + element_size], ty, locals, mm)?;
                                 }
                             }
                         }
@@ -1995,14 +1984,7 @@ impl Evaluator<'_> {
                     let size = this.size_of_sized(inner, locals, "inner of array")?;
                     for i in 0..len {
                         let offset = i * size;
-                        rec(
-                            this,
-                            &bytes[offset..offset + size],
-                            inner,
-                            locals,
-                            mm,
-                            stack_depth_limit - 1,
-                        )?;
+                        rec(this, &bytes[offset..offset + size], inner, locals, mm)?;
                     }
                 }
                 chalk_ir::TyKind::Tuple(_, subst) => {
@@ -2011,14 +1993,7 @@ impl Evaluator<'_> {
                         let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
                         let offset = layout.fields.offset(id).bytes_usize();
                         let size = this.layout(ty)?.size.bytes_usize();
-                        rec(
-                            this,
-                            &bytes[offset..offset + size],
-                            ty,
-                            locals,
-                            mm,
-                            stack_depth_limit - 1,
-                        )?;
+                        rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
                     }
                 }
                 chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
@@ -2033,14 +2008,7 @@ impl Evaluator<'_> {
                                 .bytes_usize();
                             let ty = &field_types[f].clone().substitute(Interner, subst);
                             let size = this.layout(ty)?.size.bytes_usize();
-                            rec(
-                                this,
-                                &bytes[offset..offset + size],
-                                ty,
-                                locals,
-                                mm,
-                                stack_depth_limit - 1,
-                            )?;
+                            rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
                         }
                     }
                     AdtId::EnumId(e) => {
@@ -2059,14 +2027,7 @@ impl Evaluator<'_> {
                                     l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
                                 let ty = &field_types[f].clone().substitute(Interner, subst);
                                 let size = this.layout(ty)?.size.bytes_usize();
-                                rec(
-                                    this,
-                                    &bytes[offset..offset + size],
-                                    ty,
-                                    locals,
-                                    mm,
-                                    stack_depth_limit - 1,
-                                )?;
+                                rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
                             }
                         }
                     }
@@ -2077,7 +2038,7 @@ impl Evaluator<'_> {
             Ok(())
         }
         let mut mm = ComplexMemoryMap::default();
-        rec(self, bytes, ty, locals, &mut mm, self.stack_depth_limit - 1)?;
+        rec(self, bytes, ty, locals, &mut mm)?;
         Ok(mm)
     }
 
@@ -2356,7 +2317,7 @@ impl Evaluator<'_> {
 
     fn exec_fn_with_args(
         &mut self,
-        mut def: FunctionId,
+        def: FunctionId,
         args: &[IntervalAndTy],
         generic_args: Substitution,
         locals: &Locals,
@@ -2374,9 +2335,6 @@ impl Evaluator<'_> {
         )? {
             return Ok(None);
         }
-        if let Some(redirect_def) = self.detect_and_redirect_special_function(def)? {
-            def = redirect_def;
-        }
         let arg_bytes = args.iter().map(|it| IntervalOrOwned::Borrowed(it.interval));
         match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? {
             MirOrDynIndex::Dyn(self_ty_idx) => {
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index d4d669182f..628a1fe2d2 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -13,7 +13,7 @@ use crate::mir::eval::{
     name, pad16, static_lifetime, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId,
     HasModule, HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy,
     IntervalOrOwned, ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan,
-    Mutability, Result, Substitution, Ty, TyBuilder, TyExt,
+    ModPath, Mutability, Result, Substitution, Ty, TyBuilder, TyExt,
 };
 
 mod simd;
@@ -158,25 +158,6 @@ impl Evaluator<'_> {
         Ok(false)
     }
 
-    pub(super) fn detect_and_redirect_special_function(
-        &mut self,
-        def: FunctionId,
-    ) -> Result<Option<FunctionId>> {
-        // `PanicFmt` is redirected to `ConstPanicFmt`
-        if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
-            let resolver =
-                self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db.upcast());
-
-            let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) =
-                self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt)
-            else {
-                not_supported!("const_panic_fmt lang item not found or not a function");
-            };
-            return Ok(Some(const_panic_fmt));
-        }
-        Ok(None)
-    }
-
     /// Clone has special impls for tuples and function pointers
     fn exec_clone(
         &mut self,
@@ -310,14 +291,9 @@ impl Evaluator<'_> {
         use LangItem::*;
         let candidate = self.db.lang_attr(def.into())?;
         // We want to execute these functions with special logic
-        // `PanicFmt` is not detected here as it's redirected later.
-        if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
+        if [PanicFmt, BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
             return Some(candidate);
         }
-        if self.db.attrs(def.into()).by_key("rustc_const_panic_str").exists() {
-            // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
-            return Some(LangItem::BeginPanic);
-        }
         None
     }
 
@@ -333,6 +309,43 @@ impl Evaluator<'_> {
         let mut args = args.iter();
         match it {
             BeginPanic => Err(MirEvalError::Panic("<unknown-panic-payload>".to_owned())),
+            PanicFmt => {
+                let message = (|| {
+                    let resolver = self
+                        .db
+                        .crate_def_map(self.crate_id)
+                        .crate_root()
+                        .resolver(self.db.upcast());
+                    let Some(format_fn) = resolver.resolve_path_in_value_ns_fully(
+                        self.db.upcast(),
+                        &hir_def::path::Path::from_known_path_with_no_generic(
+                            ModPath::from_segments(
+                                hir_expand::mod_path::PathKind::Abs,
+                                [name![std], name![fmt], name![format]],
+                            ),
+                        ),
+                    ) else {
+                        not_supported!("std::fmt::format not found");
+                    };
+                    let hir_def::resolver::ValueNs::FunctionId(format_fn) = format_fn else {
+                        not_supported!("std::fmt::format is not a function")
+                    };
+                    let interval = self.interpret_mir(
+                        self.db
+                            .mir_body(format_fn.into())
+                            .map_err(|e| MirEvalError::MirLowerError(format_fn, e))?,
+                        args.map(|x| IntervalOrOwned::Owned(x.clone())),
+                    )?;
+                    let message_string = interval.get(self)?;
+                    let addr =
+                        Address::from_bytes(&message_string[self.ptr_size()..2 * self.ptr_size()])?;
+                    let size = from_bytes!(usize, message_string[2 * self.ptr_size()..]);
+                    Ok(std::string::String::from_utf8_lossy(self.read_memory(addr, size)?)
+                        .into_owned())
+                })()
+                .unwrap_or_else(|e| format!("Failed to render panic format args: {e:?}"));
+                Err(MirEvalError::Panic(message))
+            }
             SliceLen => {
                 let arg = args.next().ok_or(MirEvalError::InternalError(
                     "argument of <[T]>::len() is not provided".into(),
diff --git a/crates/hir-ty/src/mir/monomorphization.rs b/crates/hir-ty/src/mir/monomorphization.rs
index d6557c3a81..12ad67cdc4 100644
--- a/crates/hir-ty/src/mir/monomorphization.rs
+++ b/crates/hir-ty/src/mir/monomorphization.rs
@@ -184,16 +184,8 @@ impl Filler<'_> {
                                     self.generics
                                         .as_ref()
                                         .and_then(|it| it.iter().nth(b.index))
-                                        .and_then(|(id, _)| match id {
-                                            hir_def::GenericParamId::ConstParamId(id) => {
-                                                Some(hir_def::TypeOrConstParamId::from(id))
-                                            }
-                                            hir_def::GenericParamId::TypeParamId(id) => {
-                                                Some(hir_def::TypeOrConstParamId::from(id))
-                                            }
-                                            _ => None,
-                                        })
-                                        .unwrap(),
+                                        .unwrap()
+                                        .0,
                                     self.subst.clone(),
                                 )
                             })?
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index afd4d1f271..8bd57820d2 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -9,18 +9,18 @@ use chalk_ir::{
     fold::{FallibleTypeFolder, Shift},
     BoundVar, DebruijnIndex,
 };
+use either::Either;
 use hir_def::{
     db::DefDatabase,
     generics::{
-        GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
-        TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+        GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+        WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
     type_ref::{TraitBoundModifier, TypeRef},
-    ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
-    LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
-    TypeParamId,
+    ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
+    OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
 };
 use hir_expand::name::Name;
 use intern::Interned;
@@ -270,130 +270,64 @@ pub(crate) struct Generics {
 }
 
 impl Generics {
-    pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
-        self.iter().map(|(id, _)| id)
+    pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
+        self.iter().map(|(id, data)| match data {
+            TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
+            TypeOrConstParamData::ConstParamData(_) => {
+                Either::Right(ConstParamId::from_unchecked(id))
+            }
+        })
     }
 
     /// Iterator over types and const params of self, then parent.
     pub(crate) fn iter<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
-        let from_toc_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            }
+    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
+        let to_toc_id = |it: &'a Generics| {
+            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
         };
-
-        let from_lt_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a LifetimeParamData)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            }
-        };
-
-        let lt_iter = self.params.iter_lt().map(from_lt_id(self));
-        self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent())
+        self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
     }
 
     /// Iterate over types and const params without parent params.
     pub(crate) fn iter_self<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
-        let from_toc_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            }
-        };
-
-        let from_lt_id = |it: &'a Generics| {
-            move |(local_id, p): (_, &'a LifetimeParamData)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            }
+    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
+        let to_toc_id = |it: &'a Generics| {
+            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
         };
-
-        self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
+        self.params.iter().map(to_toc_id(self))
     }
 
     /// Iterator over types and const params of parent.
-    #[allow(clippy::needless_lifetimes)]
-    pub(crate) fn iter_parent<'a>(
-        &'a self,
-    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
+    pub(crate) fn iter_parent(
+        &self,
+    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
         self.parent_generics().into_iter().flat_map(|it| {
-            let from_toc_id = move |(local_id, p): (_, &'a TypeOrConstParamData)| {
-                let id = TypeOrConstParamId { parent: it.def, local_id };
-                match p {
-                    TypeOrConstParamData::TypeParamData(p) => (
-                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
-                        GenericParamDataRef::TypeParamData(p),
-                    ),
-                    TypeOrConstParamData::ConstParamData(p) => (
-                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
-                        GenericParamDataRef::ConstParamData(p),
-                    ),
-                }
-            };
-
-            let from_lt_id = move |(local_id, p): (_, &'a LifetimeParamData)| {
-                (
-                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
-                    GenericParamDataRef::LifetimeParamData(p),
-                )
-            };
-            let lt_iter = it.params.iter_lt().map(from_lt_id);
-            it.params.iter().map(from_toc_id).chain(lt_iter)
+            let to_toc_id =
+                move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
+            it.params.iter().map(to_toc_id)
         })
     }
 
     /// Returns total number of generic parameters in scope, including those from parent.
     pub(crate) fn len(&self) -> usize {
         let parent = self.parent_generics().map_or(0, Generics::len);
-        let child = self.params.len();
+        let child = self.params.type_or_consts.len();
         parent + child
     }
 
-    /// Returns numbers of generic parameters and lifetimes excluding those from parent.
+    /// Returns numbers of generic parameters excluding those from parent.
     pub(crate) fn len_self(&self) -> usize {
-        self.params.len()
-    }
-
-    /// Returns number of generic parameter excluding those from parent
-    fn len_params(&self) -> usize {
         self.params.type_or_consts.len()
     }
 
-    /// (parent total, self param, type params, const params, impl trait list, lifetimes)
-    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
+    /// (parent total, self param, type param list, const param list, impl trait)
+    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
         let mut self_params = 0;
         let mut type_params = 0;
         let mut impl_trait_params = 0;
         let mut const_params = 0;
-        let mut lifetime_params = 0;
         self.params.iter().for_each(|(_, data)| match data {
             TypeOrConstParamData::TypeParamData(p) => match p.provenance {
                 TypeParamProvenance::TypeParamList => type_params += 1,
@@ -403,10 +337,8 @@ impl Generics {
             TypeOrConstParamData::ConstParamData(_) => const_params += 1,
         });
 
-        self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
-
         let parent_len = self.parent_generics().map_or(0, Generics::len);
-        (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
+        (parent_len, self_params, type_params, const_params, impl_trait_params)
     }
 
     pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
@@ -426,26 +358,6 @@ impl Generics {
         }
     }
 
-    pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
-        Some(self.find_lifetime(lifetime)?.0)
-    }
-
-    fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
-        if lifetime.parent == self.def {
-            let (idx, (_local_id, data)) = self
-                .params
-                .iter_lt()
-                .enumerate()
-                .find(|(_, (idx, _))| *idx == lifetime.local_id)?;
-
-            Some((self.len_params() + idx, data))
-        } else {
-            self.parent_generics()
-                .and_then(|g| g.find_lifetime(lifetime))
-                .map(|(idx, data)| (self.len_self() + idx, data))
-        }
-    }
-
     pub(crate) fn parent_generics(&self) -> Option<&Generics> {
         self.parent_generics.as_deref()
     }
@@ -459,15 +371,10 @@ impl Generics {
         Substitution::from_iter(
             Interner,
             self.iter_id().enumerate().map(|(idx, id)| match id {
-                GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
+                Either::Left(_) => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
+                Either::Right(id) => BoundVar::new(debruijn, idx)
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
-                GenericParamId::TypeParamId(_) => {
-                    BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
-                }
-                GenericParamId::LifetimeParamId(_) => {
-                    BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
-                }
             }),
         )
     }
@@ -477,15 +384,12 @@ impl Generics {
         Substitution::from_iter(
             Interner,
             self.iter_id().map(|id| match id {
-                GenericParamId::TypeParamId(id) => {
+                Either::Left(id) => {
                     crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
                 }
-                GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
+                Either::Right(id) => crate::to_placeholder_idx(db, id.into())
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
-                GenericParamId::LifetimeParamId(id) => {
-                    crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
-                }
             }),
         )
     }
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 23c6b078b9..c5d44c11f2 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -186,29 +186,18 @@ impl HirDisplay for Struct {
             }
             StructKind::Record => {
                 let has_where_clause = write_where_clause(def_id, f)?;
-                if let Some(limit) = f.entity_limit {
-                    let fields = self.fields(f.db);
-                    let count = fields.len().min(limit);
-                    f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
-                    if count == 0 {
-                        if fields.is_empty() {
-                            f.write_str("{}")?;
-                        } else {
-                            f.write_str("{ /* … */ }")?;
-                        }
-                    } else {
-                        f.write_str(" {\n")?;
-                        for field in &fields[..count] {
-                            f.write_str("    ")?;
-                            field.hir_fmt(f)?;
-                            f.write_str(",\n")?;
-                        }
-
-                        if fields.len() > count {
-                            f.write_str("    /* … */\n")?;
-                        }
-                        f.write_str("}")?;
+                let fields = self.fields(f.db);
+                f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
+                if fields.is_empty() {
+                    f.write_str("{}")?;
+                } else {
+                    f.write_str("{\n")?;
+                    for field in self.fields(f.db) {
+                        f.write_str("    ")?;
+                        field.hir_fmt(f)?;
+                        f.write_str(",\n")?;
                     }
+                    f.write_str("}")?;
                 }
             }
             StructKind::Unit => _ = write_where_clause(def_id, f)?,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 106056c2fc..8f147004c6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -65,7 +65,7 @@ use hir_ty::{
     consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
     db::InternedClosure,
     diagnostics::BodyValidationDiagnostic,
-    error_lifetime, known_const_to_ast,
+    known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
     method_resolution::{self, TyFingerprint},
     mir::{interpret_mir, MutBorrowKind},
@@ -1107,7 +1107,6 @@ impl Field {
                     generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
                 }
                 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-                ParamKind::Lifetime => error_lifetime().cast(Interner),
             })
             .build();
         let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
@@ -1418,7 +1417,7 @@ impl Adt {
     }
 
     pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
-        if !db.generic_params(self.into()).is_empty() {
+        if db.generic_params(self.into()).iter().count() != 0 {
             return Err(LayoutError::HasPlaceholder);
         }
         let krate = self.krate(db).id;
@@ -1449,7 +1448,6 @@ impl Adt {
                 match x {
                     ParamKind::Type => r.cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
@@ -1868,7 +1866,6 @@ impl Function {
                 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
             }
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-            ParamKind::Lifetime => error_lifetime().cast(Interner),
         };
 
         let parent_substs =
@@ -1967,7 +1964,6 @@ impl Function {
                         .unwrap_or_else(|| TyKind::Error.intern(Interner))
                         .cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 })
                 .build()
         });
@@ -2225,7 +2221,6 @@ impl SelfParam {
                 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
             }
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-            ParamKind::Lifetime => error_lifetime().cast(Interner),
         };
 
         let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build();
@@ -4144,7 +4139,6 @@ impl Type {
                         // FIXME: this code is not covered in tests.
                         unknown_const_as_generic(ty.clone())
                     }
-                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
@@ -4175,7 +4169,6 @@ impl Type {
                 match it {
                     ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
-                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index 65ce3e822c..d111005c2e 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -5617,7 +5617,7 @@ fn func<T: Debug>(i: Struct<'_, T>) {
     fun_name(i);
 }
 
-fn $0fun_name(i: Struct<'static, T>) {
+fn $0fun_name(i: Struct<'_, T>) {
     foo(i);
 }
 "#,
diff --git a/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index 2150003bc1..38f40b8d58 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -614,7 +614,7 @@ struct Foo<'a, T> {
 }
 
 impl<'a, T> Foo<'a, T> {
-    $0fn bar(self, mut b: Vec<&'a Bar<'a, T>>) -> &'a Bar<'a, T> {
+    $0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> {
         self.field.bar(b)
     }
 }
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 822751c0e4..8f4c629b58 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -33,7 +33,6 @@ pub struct HoverConfig {
     pub keywords: bool,
     pub format: HoverDocFormat,
     pub max_trait_assoc_items_count: Option<usize>,
-    pub max_struct_field_count: Option<usize>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index abedbff831..ae630d7ab0 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -101,7 +101,7 @@ pub(super) fn try_expr(
                 if let Some((inner, body)) = error_type_args {
                     inner_ty = inner;
                     body_ty = body;
-                    s = "Try Error".to_owned();
+                    "Try Error".clone_into(&mut s);
                 }
             }
         }
@@ -410,9 +410,6 @@ pub(super) fn definition(
         Definition::Trait(trait_) => {
             trait_.display_limited(db, config.max_trait_assoc_items_count).to_string()
         }
-        Definition::Adt(Adt::Struct(struct_)) => {
-            struct_.display_limited(db, config.max_struct_field_count).to_string()
-        }
         _ => def.label(db),
     };
     let docs = def.docs(db, famous_defs);
@@ -637,7 +634,7 @@ fn closure_ty(
         })
         .join("\n");
     if captures_rendered.trim().is_empty() {
-        captures_rendered = "This closure captures nothing".to_owned();
+        "This closure captures nothing".clone_into(&mut captures_rendered);
     }
     let mut targets: Vec<hir::ModuleDef> = Vec::new();
     let mut push_new_def = |item: hir::ModuleDef| {
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index ad48d80389..7a6c6ec41d 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -353,10 +353,6 @@ impl Analysis {
         self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
     }
 
-    pub fn discover_tests_in_file(&self, file_id: FileId) -> Cancellable<Vec<TestItem>> {
-        self.with_db(|db| test_explorer::discover_tests_in_file(db, file_id))
-    }
-
     /// Renders the crate graph to GraphViz "dot" syntax.
     pub fn view_crate_graph(&self, full: bool) -> Cancellable<Result<String, String>> {
         self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index 3fef16df25..fe063081f7 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -167,7 +167,6 @@ impl StaticIndex<'_> {
             keywords: true,
             format: crate::HoverDocFormat::Markdown,
             max_trait_assoc_items_count: None,
-            max_struct_field_count: None,
         };
         let tokens = tokens.filter(|token| {
             matches!(
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 5c7a463ccd..d9225fedea 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -113,7 +113,7 @@ pub enum HlPunct {
     Semi,
     /// ! (only for macro calls)
     MacroBang,
-    ///
+    /// Other punctutations
     Other,
 }
 
@@ -127,7 +127,7 @@ pub enum HlOperator {
     Logical,
     /// >, <, ==, >=, <=, !=
     Comparison,
-    ///
+    /// Other operators
     Other,
 }
 
diff --git a/crates/intern/src/lib.rs b/crates/intern/src/lib.rs
index d784321c7c..40d18b1cf8 100644
--- a/crates/intern/src/lib.rs
+++ b/crates/intern/src/lib.rs
@@ -174,6 +174,7 @@ pub struct InternStorage<T: ?Sized> {
     map: OnceLock<InternMap<T>>,
 }
 
+#[allow(clippy::new_without_default)] // this a const fn, so it can't be default
 impl<T: ?Sized> InternStorage<T> {
     pub const fn new() -> Self {
         Self { map: OnceLock::new() }
diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs
index fd49164464..880d6ec54d 100644
--- a/crates/proc-macro-api/src/lib.rs
+++ b/crates/proc-macro-api/src/lib.rs
@@ -38,7 +38,7 @@ pub enum ProcMacroKind {
     Attr,
     // This used to be called FuncLike, so that's what the server expects currently.
     #[serde(alias = "bang")]
-    #[serde(rename(serialize = "FuncLike", deserialize = "FuncLike"))]
+    #[serde(rename(serialize = "func_like", deserialize = "func_like"))]
     Bang,
 }
 
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index e6379bf902..f813c09e0a 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -86,9 +86,7 @@ impl WorkspaceBuildScripts {
                 // --all-targets includes tests, benches and examples in addition to the
                 // default lib and bins. This is an independent concept from the --target
                 // flag below.
-                if config.all_targets {
-                    cmd.arg("--all-targets");
-                }
+                cmd.arg("--all-targets");
 
                 if let Some(target) = &config.target {
                     cmd.args(["--target", target]);
@@ -237,7 +235,7 @@ impl WorkspaceBuildScripts {
             },
             progress,
         )?;
-        res.iter_mut().for_each(|it| it.error = errors.clone());
+        res.iter_mut().for_each(|it| it.error.clone_from(&errors));
         collisions.into_iter().for_each(|(id, workspace, package)| {
             if let Some(&(p, w)) = by_id.get(id) {
                 res[workspace].outputs[package] = res[w].outputs[p].clone();
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 82fee7112f..51c1b094f7 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -76,8 +76,6 @@ impl Default for CargoFeatures {
 
 #[derive(Default, Clone, Debug, PartialEq, Eq)]
 pub struct CargoConfig {
-    /// Whether to pass `--all-targets` to cargo invocations.
-    pub all_targets: bool,
     /// List of features to activate.
     pub features: CargoFeatures,
     /// rustc target
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index 1872d27c56..512588cc8f 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -49,7 +49,8 @@
 //! user explores them belongs to that extension (it's totally valid to change
 //! rust-project.json over time via configuration request!)
 
-use base_db::{CrateDisplayName, CrateName};
+use base_db::{CrateDisplayName, CrateId, CrateName, Dependency};
+use la_arena::RawIdx;
 use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::{de, Deserialize};
@@ -73,10 +74,10 @@ pub struct ProjectJson {
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct Crate {
     pub(crate) display_name: Option<CrateDisplayName>,
-    pub root_module: AbsPathBuf,
+    pub(crate) root_module: AbsPathBuf,
     pub(crate) edition: Edition,
     pub(crate) version: Option<String>,
-    pub(crate) deps: Vec<Dep>,
+    pub(crate) deps: Vec<Dependency>,
     pub(crate) cfg: Vec<CfgFlag>,
     pub(crate) target: Option<String>,
     pub(crate) env: FxHashMap<String, String>,
@@ -127,7 +128,16 @@ impl ProjectJson {
                         root_module,
                         edition: crate_data.edition.into(),
                         version: crate_data.version.as_ref().map(ToString::to_string),
-                        deps: crate_data.deps,
+                        deps: crate_data
+                            .deps
+                            .into_iter()
+                            .map(|dep_data| {
+                                Dependency::new(
+                                    dep_data.name,
+                                    CrateId::from_raw(RawIdx::from(dep_data.krate as u32)),
+                                )
+                            })
+                            .collect::<Vec<_>>(),
                         cfg: crate_data.cfg,
                         target: crate_data.target,
                         env: crate_data.env,
@@ -151,8 +161,11 @@ impl ProjectJson {
     }
 
     /// Returns an iterator over the crates in the project.
-    pub fn crates(&self) -> impl Iterator<Item = (CrateArrayIdx, &Crate)> {
-        self.crates.iter().enumerate().map(|(idx, krate)| (CrateArrayIdx(idx), krate))
+    pub fn crates(&self) -> impl Iterator<Item = (CrateId, &Crate)> + '_ {
+        self.crates
+            .iter()
+            .enumerate()
+            .map(|(idx, krate)| (CrateId::from_raw(RawIdx::from(idx as u32)), krate))
     }
 
     /// Returns the path to the project's root folder.
@@ -175,7 +188,7 @@ struct CrateData {
     edition: EditionData,
     #[serde(default)]
     version: Option<semver::Version>,
-    deps: Vec<Dep>,
+    deps: Vec<DepData>,
     #[serde(default)]
     cfg: Vec<CfgFlag>,
     target: Option<String>,
@@ -214,21 +227,13 @@ impl From<EditionData> for Edition {
     }
 }
 
-/// Identifies a crate by position in the crates array.
-///
-/// This will differ from `CrateId` when multiple `ProjectJson`
-/// workspaces are loaded.
-#[derive(Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
-#[serde(transparent)]
-pub struct CrateArrayIdx(pub usize);
-
-#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
-pub(crate) struct Dep {
+#[derive(Deserialize, Debug, Clone)]
+struct DepData {
     /// Identifies a crate by position in the crates array.
     #[serde(rename = "crate")]
-    pub(crate) krate: CrateArrayIdx,
+    krate: usize,
     #[serde(deserialize_with = "deserialize_crate_name")]
-    pub(crate) name: CrateName,
+    name: CrateName,
 }
 
 #[derive(Deserialize, Debug, Clone)]
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index d752b2f32e..b8c5885108 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -22,7 +22,7 @@ use crate::{
     build_scripts::BuildScriptOutput,
     cargo_workspace::{DepKind, PackageData, RustLibSource},
     cfg_flag::CfgFlag,
-    project_json::{Crate, CrateArrayIdx},
+    project_json::Crate,
     rustc_cfg::{self, RustcCfgConfig},
     sysroot::{SysrootCrate, SysrootMode},
     target_data_layout::{self, RustcDataLayoutConfig},
@@ -878,13 +878,12 @@ fn project_json_to_crate_graph(
 
     let r_a_cfg_flag = CfgFlag::Atom("rust_analyzer".to_owned());
     let mut cfg_cache: FxHashMap<&str, Vec<CfgFlag>> = FxHashMap::default();
-
-    let idx_to_crate_id: FxHashMap<CrateArrayIdx, CrateId> = project
+    let crates: FxHashMap<CrateId, CrateId> = project
         .crates()
-        .filter_map(|(idx, krate)| Some((idx, krate, load(&krate.root_module)?)))
+        .filter_map(|(crate_id, krate)| Some((crate_id, krate, load(&krate.root_module)?)))
         .map(
             |(
-                idx,
+                crate_id,
                 Crate {
                     display_name,
                     edition,
@@ -940,13 +939,13 @@ fn project_json_to_crate_graph(
                         proc_macros.insert(crate_graph_crate_id, node);
                     }
                 }
-                (idx, crate_graph_crate_id)
+                (crate_id, crate_graph_crate_id)
             },
         )
         .collect();
 
-    for (from_idx, krate) in project.crates() {
-        if let Some(&from) = idx_to_crate_id.get(&from_idx) {
+    for (from, krate) in project.crates() {
+        if let Some(&from) = crates.get(&from) {
             if let Some((public_deps, libproc_macro)) = &sysroot_deps {
                 public_deps.add_to_crate_graph(crate_graph, from);
                 if let Some(proc_macro) = libproc_macro {
@@ -955,8 +954,8 @@ fn project_json_to_crate_graph(
             }
 
             for dep in &krate.deps {
-                if let Some(&to) = idx_to_crate_id.get(&dep.krate) {
-                    add_dep(crate_graph, from, dep.name.clone(), to);
+                if let Some(&to) = crates.get(&dep.crate_id) {
+                    add_dep(crate_graph, from, dep.name.clone(), to)
                 }
             }
         }
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index fdd77199aa..c636f7494a 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -279,8 +279,7 @@ impl flags::AnalysisStats {
         let mut all = 0;
         let mut fail = 0;
         for &a in adts {
-            let generic_params = db.generic_params(a.into());
-            if generic_params.iter().next().is_some() || generic_params.iter_lt().next().is_some() {
+            if db.generic_params(a.into()).iter().next().is_some() {
                 // Data types with generics don't have layout.
                 continue;
             }
diff --git a/crates/rust-analyzer/src/cli/flags.rs b/crates/rust-analyzer/src/cli/flags.rs
index b3b8ab9a40..3f68c5d053 100644
--- a/crates/rust-analyzer/src/cli/flags.rs
+++ b/crates/rust-analyzer/src/cli/flags.rs
@@ -235,7 +235,6 @@ pub struct RunTests {
 #[derive(Debug)]
 pub struct RustcTests {
     pub rustc_repo: PathBuf,
-
     pub filter: Option<String>,
 }
 
diff --git a/crates/rust-analyzer/src/cli/progress_report.rs b/crates/rust-analyzer/src/cli/progress_report.rs
index b233730099..6964977840 100644
--- a/crates/rust-analyzer/src/cli/progress_report.rs
+++ b/crates/rust-analyzer/src/cli/progress_report.rs
@@ -92,7 +92,7 @@ impl<'a> ProgressReport<'a> {
 
         let _ = io::stdout().write(output.as_bytes());
         let _ = io::stdout().flush();
-        self.text = text.to_owned();
+        text.clone_into(&mut self.text);
     }
 
     fn set_value(&mut self, value: f32) {
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 80f024184a..e6b60f6906 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -71,8 +71,6 @@ config_data! {
         /// How many worker threads to handle priming caches. The default `0` means to pick automatically.
         cachePriming_numThreads: ParallelCachePrimingNumThreads = "0",
 
-        /// Pass `--all-targets` to cargo invocation.
-        cargo_allTargets: bool           = "true",
         /// Automatically refresh project info via `cargo metadata` on
         /// `Cargo.toml` or `.cargo/config.toml` changes.
         cargo_autoreload: bool           = "true",
@@ -165,9 +163,8 @@ config_data! {
         /// Run the check command for diagnostics on save.
         checkOnSave | checkOnSave_enable: bool                         = "true",
 
-        /// Check all targets and tests (`--all-targets`). Defaults to
-        /// `#rust-analyzer.cargo.allTargets#`.
-        check_allTargets | checkOnSave_allTargets: Option<bool>          = "null",
+        /// Check all targets and tests (`--all-targets`).
+        check_allTargets | checkOnSave_allTargets: bool                  = "true",
         /// Cargo command to use for `cargo check`.
         check_command | checkOnSave_command: String                      = "\"check\"",
         /// Extra arguments for `cargo check`.
@@ -378,8 +375,6 @@ config_data! {
         /// How to render the size information in a memory layout hover.
         hover_memoryLayout_size: Option<MemoryLayoutHoverRenderKindDef> = "\"both\"",
 
-        /// How many fields of a struct to display when hovering a struct.
-        hover_show_structFields: Option<usize> = "null",
         /// How many associated items of a trait to display when hovering a trait.
         hover_show_traitAssocItems: Option<usize> = "null",
 
@@ -1016,17 +1011,6 @@ impl Config {
         )
     }
 
-    pub fn did_change_watched_files_relative_pattern_support(&self) -> bool {
-        try_or_def!(
-            self.caps
-                .workspace
-                .as_ref()?
-                .did_change_watched_files
-                .as_ref()?
-                .relative_pattern_support?
-        )
-    }
-
     pub fn prefill_caches(&self) -> bool {
         self.data.cachePriming_enable
     }
@@ -1287,7 +1271,6 @@ impl Config {
         let sysroot_query_metadata = self.data.cargo_sysrootQueryMetadata;
 
         CargoConfig {
-            all_targets: self.data.cargo_allTargets,
             features: match &self.data.cargo_features {
                 CargoFeaturesDef::All => CargoFeatures::All,
                 CargoFeaturesDef::Selected(features) => CargoFeatures::Selected {
@@ -1398,7 +1381,7 @@ impl Config {
                         targets => Some(targets.into()),
                     })
                     .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()),
-                all_targets: self.data.check_allTargets.unwrap_or(self.data.cargo_allTargets),
+                all_targets: self.data.check_allTargets,
                 no_default_features: self
                     .data
                     .check_noDefaultFeatures
@@ -1707,7 +1690,6 @@ impl Config {
             },
             keywords: self.data.hover_documentation_keywords_enable,
             max_trait_assoc_items_count: self.data.hover_show_traitAssocItems,
-            max_struct_field_count: self.data.hover_show_structFields,
         }
     }
 
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index 3b23257818..de546c7c96 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -105,7 +105,7 @@ pub(crate) fn handle_did_change_text_document(
         )
         .into_bytes();
         if *data != new_contents {
-            *data = new_contents.clone();
+            data.clone_from(&new_contents);
             state.vfs.write().0.set_file_contents(path, Some(new_contents));
         }
     }
@@ -296,9 +296,10 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                         })
                     }
                     project_model::ProjectWorkspace::Json { project, .. } => {
-                        if !project.crates().any(|(_, krate)| {
-                            crate_root_paths.contains(&krate.root_module.as_path())
-                        }) {
+                        if !project
+                            .crates()
+                            .any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c))
+                        {
                             return None;
                         }
                         None
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 77692ed3ae..4d4103a7ad 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -238,12 +238,9 @@ pub(crate) fn handle_discover_test(
     let (tests, scope) = match params.test_id {
         Some(id) => {
             let crate_id = id.split_once("::").map(|it| it.0).unwrap_or(&id);
-            (
-                snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?,
-                Some(vec![crate_id.to_owned()]),
-            )
+            (snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?, vec![crate_id.to_owned()])
         }
-        None => (snap.analysis.discover_test_roots()?, None),
+        None => (snap.analysis.discover_test_roots()?, vec![]),
     };
     for t in &tests {
         hack_recover_crate_name::insert_name(t.id.clone());
@@ -257,7 +254,6 @@ pub(crate) fn handle_discover_test(
             })
             .collect(),
         scope,
-        scope_file: None,
     })
 }
 
diff --git a/crates/rust-analyzer/src/lsp/ext.rs b/crates/rust-analyzer/src/lsp/ext.rs
index eac982f1b2..5d3d75efcb 100644
--- a/crates/rust-analyzer/src/lsp/ext.rs
+++ b/crates/rust-analyzer/src/lsp/ext.rs
@@ -194,8 +194,7 @@ pub struct TestItem {
 #[serde(rename_all = "camelCase")]
 pub struct DiscoverTestResults {
     pub tests: Vec<TestItem>,
-    pub scope: Option<Vec<String>>,
-    pub scope_file: Option<Vec<TextDocumentIdentifier>>,
+    pub scope: Vec<String>,
 }
 
 pub enum DiscoverTest {}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 38df323512..2e39c99a39 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -9,8 +9,9 @@ use std::{
 use always_assert::always;
 use crossbeam_channel::{never, select, Receiver};
 use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath};
+use itertools::Itertools;
 use lsp_server::{Connection, Notification, Request};
-use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
+use lsp_types::notification::Notification as _;
 use stdx::thread::ThreadIntent;
 use vfs::FileId;
 
@@ -411,7 +412,7 @@ impl GlobalState {
                 // See https://github.com/rust-lang/rust-analyzer/issues/13130
                 let patch_empty = |message: &mut String| {
                     if message.is_empty() {
-                        *message = " ".to_owned();
+                        " ".clone_into(message);
                     }
                 };
 
@@ -532,14 +533,22 @@ impl GlobalState {
             let snapshot = self.snapshot();
             move || {
                 let tests = subscriptions
-                    .iter()
-                    .copied()
-                    .filter_map(|f| snapshot.analysis.discover_tests_in_file(f).ok())
+                    .into_iter()
+                    .filter_map(|f| snapshot.analysis.crates_for(f).ok())
+                    .flatten()
+                    .unique()
+                    .filter_map(|c| snapshot.analysis.discover_tests_in_crate(c).ok())
                     .flatten()
                     .collect::<Vec<_>>();
                 for t in &tests {
                     hack_recover_crate_name::insert_name(t.id.clone());
                 }
+                let scope = tests
+                    .iter()
+                    .filter_map(|t| Some(t.id.split_once("::")?.0))
+                    .unique()
+                    .map(|it| it.to_owned())
+                    .collect();
                 Task::DiscoverTest(lsp_ext::DiscoverTestResults {
                     tests: tests
                         .into_iter()
@@ -548,13 +557,7 @@ impl GlobalState {
                             to_proto::test_item(&snapshot, t, line_index.as_ref())
                         })
                         .collect(),
-                    scope: None,
-                    scope_file: Some(
-                        subscriptions
-                            .into_iter()
-                            .map(|f| TextDocumentIdentifier { uri: to_proto::url(&snapshot, f) })
-                            .collect(),
-                    ),
+                    scope,
                 })
             }
         });
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 771a5599f6..d0462d5733 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -428,16 +428,16 @@ impl GlobalState {
         }
 
         if let FilesWatcher::Client = self.config.files().watcher {
-            let filter =
-                self.workspaces.iter().flat_map(|ws| ws.to_roots()).filter(|it| it.is_local);
-
-            let watchers = if self.config.did_change_watched_files_relative_pattern_support() {
-                // When relative patterns are supported by the client, prefer using them
-                filter
+            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
+                watchers: self
+                    .workspaces
+                    .iter()
+                    .flat_map(|ws| ws.to_roots())
+                    .filter(|it| it.is_local)
                     .flat_map(|root| {
-                        root.include.into_iter().flat_map(|base| {
-                            [(base.clone(), "**/*.rs"), (base, "**/Cargo.{lock,toml}")]
-                        })
+                        root.include
+                            .into_iter()
+                            .flat_map(|it| [(it.clone(), "**/*.rs"), (it, "**/Cargo.{lock,toml}")])
                     })
                     .map(|(base, pat)| lsp_types::FileSystemWatcher {
                         glob_pattern: lsp_types::GlobPattern::Relative(
@@ -450,24 +450,8 @@ impl GlobalState {
                         ),
                         kind: None,
                     })
-                    .collect()
-            } else {
-                // When they're not, integrate the base to make them into absolute patterns
-                filter
-                    .flat_map(|root| {
-                        root.include.into_iter().flat_map(|base| {
-                            [format!("{base}/**/*.rs"), format!("{base}/**/Cargo.{{lock,toml}}")]
-                        })
-                    })
-                    .map(|glob_pattern| lsp_types::FileSystemWatcher {
-                        glob_pattern: lsp_types::GlobPattern::String(glob_pattern),
-                        kind: None,
-                    })
-                    .collect()
+                    .collect(),
             };
-
-            let registration_options =
-                lsp_types::DidChangeWatchedFilesRegistrationOptions { watchers };
             let registration = lsp_types::Registration {
                 id: "workspace/didChangeWatchedFiles".to_owned(),
                 method: "workspace/didChangeWatchedFiles".to_owned(),
@@ -741,13 +725,13 @@ pub fn ws_to_crate_graph(
                 if layouts.len() <= idx {
                     layouts.resize(idx + 1, e.clone());
                 }
-                layouts[idx] = layout.clone();
+                layouts[idx].clone_from(&layout);
             }
             if idx >= num_toolchains {
                 if toolchains.len() <= idx {
                     toolchains.resize(idx + 1, None);
                 }
-                toolchains[idx] = toolchain.clone();
+                toolchains[idx].clone_from(&toolchain);
             }
         });
         proc_macro_paths.push(crate_proc_macros);
diff --git a/crates/salsa/salsa-macros/src/database_storage.rs b/crates/salsa/salsa-macros/src/database_storage.rs
index 223da9b529..14238e2fed 100644
--- a/crates/salsa/salsa-macros/src/database_storage.rs
+++ b/crates/salsa/salsa-macros/src/database_storage.rs
@@ -1,4 +1,5 @@
-//!
+//! Implementation for `[salsa::database]` decorator.
+
 use heck::ToSnakeCase;
 use proc_macro::TokenStream;
 use syn::parse::{Parse, ParseStream};
diff --git a/crates/salsa/salsa-macros/src/parenthesized.rs b/crates/salsa/salsa-macros/src/parenthesized.rs
index 9df41e03c1..5ecd1b8a05 100644
--- a/crates/salsa/salsa-macros/src/parenthesized.rs
+++ b/crates/salsa/salsa-macros/src/parenthesized.rs
@@ -1,4 +1,4 @@
-//!
+//! Parenthesis helper
 pub(crate) struct Parenthesized<T>(pub(crate) T);
 
 impl<T> syn::parse::Parse for Parenthesized<T>
diff --git a/crates/salsa/salsa-macros/src/query_group.rs b/crates/salsa/salsa-macros/src/query_group.rs
index 5983765eec..659797d6d4 100644
--- a/crates/salsa/salsa-macros/src/query_group.rs
+++ b/crates/salsa/salsa-macros/src/query_group.rs
@@ -1,4 +1,4 @@
-//!
+//! Implementation for `[salsa::query_group]` decorator.
 
 use crate::parenthesized::Parenthesized;
 use heck::ToUpperCamelCase;
diff --git a/crates/salsa/src/derived.rs b/crates/salsa/src/derived.rs
index 3b5bd7f9e3..fd31ab2041 100644
--- a/crates/salsa/src/derived.rs
+++ b/crates/salsa/src/derived.rs
@@ -1,4 +1,3 @@
-//!
 use crate::debug::TableEntry;
 use crate::durability::Durability;
 use crate::hash::FxIndexMap;
diff --git a/crates/salsa/src/derived/slot.rs b/crates/salsa/src/derived/slot.rs
index 75204c8ff6..cfafa40ce3 100644
--- a/crates/salsa/src/derived/slot.rs
+++ b/crates/salsa/src/derived/slot.rs
@@ -1,4 +1,3 @@
-//!
 use crate::debug::TableEntry;
 use crate::derived::MemoizationPolicy;
 use crate::durability::Durability;
diff --git a/crates/salsa/src/durability.rs b/crates/salsa/src/durability.rs
index 44abae3170..7b8e6840fc 100644
--- a/crates/salsa/src/durability.rs
+++ b/crates/salsa/src/durability.rs
@@ -1,4 +1,3 @@
-//!
 /// Describes how likely a value is to change -- how "durable" it is.
 /// By default, inputs have `Durability::LOW` and interned values have
 /// `Durability::HIGH`. But inputs can be explicitly set with other
diff --git a/crates/salsa/src/hash.rs b/crates/salsa/src/hash.rs
index 47a2dd1ce0..3b2d7df3fb 100644
--- a/crates/salsa/src/hash.rs
+++ b/crates/salsa/src/hash.rs
@@ -1,4 +1,3 @@
-//!
 pub(crate) type FxHasher = std::hash::BuildHasherDefault<rustc_hash::FxHasher>;
 pub(crate) type FxIndexSet<K> = indexmap::IndexSet<K, FxHasher>;
 pub(crate) type FxIndexMap<K, V> = indexmap::IndexMap<K, V, FxHasher>;
diff --git a/crates/salsa/src/input.rs b/crates/salsa/src/input.rs
index 922ec5a775..f04f48e3ba 100644
--- a/crates/salsa/src/input.rs
+++ b/crates/salsa/src/input.rs
@@ -1,4 +1,3 @@
-//!
 use crate::debug::TableEntry;
 use crate::durability::Durability;
 use crate::hash::FxIndexMap;
diff --git a/crates/salsa/src/intern_id.rs b/crates/salsa/src/intern_id.rs
index a7bbc088f9..b060d8aab6 100644
--- a/crates/salsa/src/intern_id.rs
+++ b/crates/salsa/src/intern_id.rs
@@ -1,4 +1,3 @@
-//!
 use std::fmt;
 use std::num::NonZeroU32;
 
diff --git a/crates/salsa/src/interned.rs b/crates/salsa/src/interned.rs
index c065e7e2bd..bfa9cc0591 100644
--- a/crates/salsa/src/interned.rs
+++ b/crates/salsa/src/interned.rs
@@ -1,4 +1,3 @@
-//!
 use crate::debug::TableEntry;
 use crate::durability::Durability;
 use crate::intern_id::InternId;
diff --git a/crates/salsa/src/lib.rs b/crates/salsa/src/lib.rs
index fe80759887..f86683ee77 100644
--- a/crates/salsa/src/lib.rs
+++ b/crates/salsa/src/lib.rs
@@ -1,8 +1,7 @@
-//!
 #![allow(clippy::type_complexity)]
 #![allow(clippy::question_mark)]
+#![allow(missing_docs)]
 #![warn(rust_2018_idioms)]
-#![warn(missing_docs)]
 
 //! The salsa crate is a crate for incremental recomputation.  It
 //! permits you to define a "database" of queries with both inputs and
@@ -124,9 +123,9 @@ pub struct Event {
 impl Event {
     /// Returns a type that gives a user-readable debug output.
     /// Use like `println!("{:?}", index.debug(db))`.
-    pub fn debug<'me, D: ?Sized>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me
+    pub fn debug<'me, D>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me
     where
-        D: plumbing::DatabaseOps,
+        D: ?Sized + plumbing::DatabaseOps,
     {
         EventDebug { event: self, db }
     }
@@ -206,9 +205,9 @@ pub enum EventKind {
 impl EventKind {
     /// Returns a type that gives a user-readable debug output.
     /// Use like `println!("{:?}", index.debug(db))`.
-    pub fn debug<'me, D: ?Sized>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me
+    pub fn debug<'me, D>(&'me self, db: &'me D) -> impl std::fmt::Debug + 'me
     where
-        D: plumbing::DatabaseOps,
+        D: ?Sized + plumbing::DatabaseOps,
     {
         EventKindDebug { kind: self, db }
     }
@@ -400,9 +399,9 @@ impl DatabaseKeyIndex {
 
     /// Returns a type that gives a user-readable debug output.
     /// Use like `println!("{:?}", index.debug(db))`.
-    pub fn debug<D: ?Sized>(self, db: &D) -> impl std::fmt::Debug + '_
+    pub fn debug<D>(self, db: &D) -> impl std::fmt::Debug + '_
     where
-        D: plumbing::DatabaseOps,
+        D: ?Sized + plumbing::DatabaseOps,
     {
         DatabaseKeyIndexDebug { index: self, db }
     }
diff --git a/crates/salsa/src/lru.rs b/crates/salsa/src/lru.rs
index 1ff85a3ea4..edad551842 100644
--- a/crates/salsa/src/lru.rs
+++ b/crates/salsa/src/lru.rs
@@ -1,4 +1,3 @@
-//!
 use oorandom::Rand64;
 use parking_lot::Mutex;
 use std::fmt::Debug;
diff --git a/crates/salsa/src/plumbing.rs b/crates/salsa/src/plumbing.rs
index 1a8ff33b2e..1dfde63986 100644
--- a/crates/salsa/src/plumbing.rs
+++ b/crates/salsa/src/plumbing.rs
@@ -1,4 +1,3 @@
-//!
 #![allow(missing_docs)]
 
 use crate::debug::TableEntry;
diff --git a/crates/salsa/src/revision.rs b/crates/salsa/src/revision.rs
index 559b033860..204c0883b8 100644
--- a/crates/salsa/src/revision.rs
+++ b/crates/salsa/src/revision.rs
@@ -1,4 +1,3 @@
-//!
 use std::num::NonZeroU32;
 use std::sync::atomic::{AtomicU32, Ordering};
 
diff --git a/crates/salsa/src/runtime.rs b/crates/salsa/src/runtime.rs
index e11cabfe11..4f3341f515 100644
--- a/crates/salsa/src/runtime.rs
+++ b/crates/salsa/src/runtime.rs
@@ -1,4 +1,3 @@
-//!
 use crate::durability::Durability;
 use crate::hash::FxIndexSet;
 use crate::plumbing::CycleRecoveryStrategy;
@@ -605,7 +604,7 @@ impl ActiveQuery {
     pub(crate) fn take_inputs_from(&mut self, cycle_query: &ActiveQuery) {
         self.changed_at = cycle_query.changed_at;
         self.durability = cycle_query.durability;
-        self.dependencies = cycle_query.dependencies.clone();
+        self.dependencies.clone_from(&cycle_query.dependencies);
     }
 }
 
diff --git a/crates/salsa/src/runtime/dependency_graph.rs b/crates/salsa/src/runtime/dependency_graph.rs
index dd223eeeba..ed1d499f63 100644
--- a/crates/salsa/src/runtime/dependency_graph.rs
+++ b/crates/salsa/src/runtime/dependency_graph.rs
@@ -1,4 +1,3 @@
-//!
 use triomphe::Arc;
 
 use crate::{DatabaseKeyIndex, RuntimeId};
diff --git a/crates/salsa/src/runtime/local_state.rs b/crates/salsa/src/runtime/local_state.rs
index 7ac21dec1a..0dbea1d563 100644
--- a/crates/salsa/src/runtime/local_state.rs
+++ b/crates/salsa/src/runtime/local_state.rs
@@ -1,4 +1,3 @@
-//!
 use tracing::debug;
 use triomphe::ThinArc;
 
diff --git a/crates/salsa/src/storage.rs b/crates/salsa/src/storage.rs
index c0e6416f4a..e0acf44041 100644
--- a/crates/salsa/src/storage.rs
+++ b/crates/salsa/src/storage.rs
@@ -1,4 +1,3 @@
-//!
 use crate::{plumbing::DatabaseStorageTypes, Runtime};
 use triomphe::Arc;
 
diff --git a/crates/sourcegen/src/lib.rs b/crates/sourcegen/src/lib.rs
index 295b716b4e..829b4d5b0f 100644
--- a/crates/sourcegen/src/lib.rs
+++ b/crates/sourcegen/src/lib.rs
@@ -69,7 +69,7 @@ impl CommentBlock {
                 panic!("Use plain (non-doc) comments with tags like {tag}:\n    {first}");
             }
 
-            block.id = id.trim().to_owned();
+            id.trim().clone_into(&mut block.id);
             true
         });
         blocks
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 939b1819c7..8db66687aa 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 223f48a89a5126a0
+lsp/ext.rs hash: d5febcbf63650753
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -440,11 +440,7 @@ interface DiscoverTestResults {
     // For each test which its id is in this list, the response
     // contains all tests that are children of this test, and
     // client should remove old tests not included in the response.
-    scope: string[] | undefined;
-    // For each file which its uri is in this list, the response
-    // contains all tests that are located in this file, and
-    // client should remove old tests not included in the response.
-    scopeFile: lc.TextDocumentIdentifier[] | undefined;    
+    scope: string[];
 }
 ```
 
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 8f69895b2e..5e782b7831 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -19,11 +19,6 @@ Warm up caches on project load.
 --
 How many worker threads to handle priming caches. The default `0` means to pick automatically.
 --
-[[rust-analyzer.cargo.allTargets]]rust-analyzer.cargo.allTargets (default: `true`)::
-+
---
-Pass `--all-targets` to cargo invocation.
---
 [[rust-analyzer.cargo.autoreload]]rust-analyzer.cargo.autoreload (default: `true`)::
 +
 --
@@ -169,11 +164,10 @@ Unsets the implicit `#[cfg(test)]` for the specified crates.
 --
 Run the check command for diagnostics on save.
 --
-[[rust-analyzer.check.allTargets]]rust-analyzer.check.allTargets (default: `null`)::
+[[rust-analyzer.check.allTargets]]rust-analyzer.check.allTargets (default: `true`)::
 +
 --
-Check all targets and tests (`--all-targets`). Defaults to
-`#rust-analyzer.cargo.allTargets#`.
+Check all targets and tests (`--all-targets`).
 --
 [[rust-analyzer.check.command]]rust-analyzer.check.command (default: `"check"`)::
 +
@@ -526,11 +520,6 @@ How to render the offset information in a memory layout hover.
 --
 How to render the size information in a memory layout hover.
 --
-[[rust-analyzer.hover.show.structFields]]rust-analyzer.hover.show.structFields (default: `null`)::
-+
---
-How many fields of a struct to display when hovering a struct.
---
 [[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index 3fb001cb44..c34b8e25de 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -546,11 +546,6 @@
                     "minimum": 0,
                     "maximum": 255
                 },
-                "rust-analyzer.cargo.allTargets": {
-                    "markdownDescription": "Pass `--all-targets` to cargo invocation.",
-                    "default": true,
-                    "type": "boolean"
-                },
                 "rust-analyzer.cargo.autoreload": {
                     "markdownDescription": "Automatically refresh project info via `cargo metadata` on\n`Cargo.toml` or `.cargo/config.toml` changes.",
                     "default": true,
@@ -712,12 +707,9 @@
                     "type": "boolean"
                 },
                 "rust-analyzer.check.allTargets": {
-                    "markdownDescription": "Check all targets and tests (`--all-targets`). Defaults to\n`#rust-analyzer.cargo.allTargets#`.",
-                    "default": null,
-                    "type": [
-                        "null",
-                        "boolean"
-                    ]
+                    "markdownDescription": "Check all targets and tests (`--all-targets`).",
+                    "default": true,
+                    "type": "boolean"
                 },
                 "rust-analyzer.check.command": {
                     "markdownDescription": "Cargo command to use for `cargo check`.",
@@ -1152,15 +1144,6 @@
                         }
                     ]
                 },
-                "rust-analyzer.hover.show.structFields": {
-                    "markdownDescription": "How many fields of a struct to display when hovering a struct.",
-                    "default": null,
-                    "type": [
-                        "null",
-                        "integer"
-                    ],
-                    "minimum": 0
-                },
                 "rust-analyzer.hover.show.traitAssocItems": {
                     "markdownDescription": "How many associated items of a trait to display when hovering a trait.",
                     "default": null,
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index e676bc0826..92a816bfbc 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -19,7 +19,7 @@ export class Config {
     configureLang: vscode.Disposable | undefined;
 
     readonly rootSection = "rust-analyzer";
-    private readonly requiresServerReloadOpts = [
+    private readonly requiresReloadOpts = [
         "cargo",
         "procMacro",
         "serverPath",
@@ -27,10 +27,6 @@ export class Config {
         "files",
     ].map((opt) => `${this.rootSection}.${opt}`);
 
-    private readonly requiresWindowReloadOpts = ["testExplorer"].map(
-        (opt) => `${this.rootSection}.${opt}`,
-    );
-
     readonly package: {
         version: string;
         releaseTag: string | null;
@@ -70,31 +66,18 @@ export class Config {
 
         this.configureLanguage();
 
-        const requiresWindowReloadOpt = this.requiresWindowReloadOpts.find((opt) =>
-            event.affectsConfiguration(opt),
-        );
-
-        if (requiresWindowReloadOpt) {
-            const message = `Changing "${requiresWindowReloadOpt}" requires a window reload`;
-            const userResponse = await vscode.window.showInformationMessage(message, "Reload now");
-
-            if (userResponse) {
-                await vscode.commands.executeCommand("workbench.action.reloadWindow");
-            }
-        }
-
-        const requiresServerReloadOpt = this.requiresServerReloadOpts.find((opt) =>
+        const requiresReloadOpt = this.requiresReloadOpts.find((opt) =>
             event.affectsConfiguration(opt),
         );
 
-        if (!requiresServerReloadOpt) return;
+        if (!requiresReloadOpt) return;
 
         if (this.restartServerOnConfigChange) {
             await vscode.commands.executeCommand("rust-analyzer.restartServer");
             return;
         }
 
-        const message = `Changing "${requiresServerReloadOpt}" requires a server restart`;
+        const message = `Changing "${requiresReloadOpt}" requires a server restart`;
         const userResponse = await vscode.window.showInformationMessage(message, "Restart now");
 
         if (userResponse) {
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index bad1f48de8..3fc63fc7d8 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -81,8 +81,8 @@ async function getDebugConfiguration(
     if (!editor) return;
 
     const knownEngines: Record<string, DebugConfigProvider> = {
-        "vadimcn.vscode-lldb": getCodeLldbDebugConfig,
         "ms-vscode.cpptools": getCCppDebugConfig,
+        "vadimcn.vscode-lldb": getCodeLldbDebugConfig,
         "webfreak.debug": getNativeDebugConfig,
     };
     const debugOptions = ctx.config.debug;
@@ -203,10 +203,6 @@ function getCCppDebugConfig(
         cwd: cargoWorkspace || runnable.args.workspaceRoot,
         sourceFileMap,
         env,
-        // See https://github.com/rust-lang/rust-analyzer/issues/16901#issuecomment-2024486941
-        osx: {
-            MIMode: "lldb",
-        },
     };
 }
 
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 9a7a4aae95..ca8106371b 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -83,11 +83,7 @@ export type TestItem = {
     range?: lc.Range | undefined;
     runnable?: Runnable | undefined;
 };
-export type DiscoverTestResults = {
-    tests: TestItem[];
-    scope: string[] | undefined;
-    scopeFile: lc.TextDocumentIdentifier[] | undefined;
-};
+export type DiscoverTestResults = { tests: TestItem[]; scope: string[] };
 export type TestState =
     | { tag: "failed"; message: string }
     | { tag: "passed" }
diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts
index 4470689cd8..02ccbb6956 100644
--- a/editors/code/src/run.ts
+++ b/editors/code/src/run.ts
@@ -2,6 +2,7 @@ import * as vscode from "vscode";
 import type * as lc from "vscode-languageclient";
 import * as ra from "./lsp_ext";
 import * as tasks from "./tasks";
+import * as toolchain from "./toolchain";
 
 import type { CtxInit } from "./ctx";
 import { makeDebugConfig } from "./debug";
@@ -111,12 +112,22 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
         throw `Unexpected runnable kind: ${runnable.kind}`;
     }
 
-    const args = createArgs(runnable);
+    let program: string;
+    let args = createArgs(runnable);
+    if (runnable.args.overrideCargo) {
+        // Split on spaces to allow overrides like "wrapper cargo".
+        const cargoParts = runnable.args.overrideCargo.split(" ");
 
-    const definition: tasks.CargoTaskDefinition = {
+        program = unwrapUndefinable(cargoParts[0]);
+        args = [...cargoParts.slice(1), ...args];
+    } else {
+        program = await toolchain.cargoPath();
+    }
+
+    const definition: tasks.RustTargetDefinition = {
         type: tasks.TASK_TYPE,
-        command: unwrapUndefinable(args[0]), // run, test, etc...
-        args: args.slice(1),
+        program,
+        args,
         cwd: runnable.args.workspaceRoot || ".",
         env: prepareEnv(runnable, config.runnablesExtraEnv),
         overrideCargo: runnable.args.overrideCargo,
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts
index 2b3abc5d65..89abb37b0e 100644
--- a/editors/code/src/tasks.ts
+++ b/editors/code/src/tasks.ts
@@ -2,26 +2,17 @@ import * as vscode from "vscode";
 import * as toolchain from "./toolchain";
 import type { Config } from "./config";
 import { log } from "./util";
-import { unwrapUndefinable } from "./undefinable";
 
 // This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
 // our configuration should be compatible with it so use the same key.
 export const TASK_TYPE = "cargo";
-
 export const TASK_SOURCE = "rust";
 
-export interface CargoTaskDefinition extends vscode.TaskDefinition {
-    // The cargo command, such as "run" or "check".
-    command: string;
-    // Additional arguments passed to the cargo command.
-    args?: string[];
-    // The working directory to run the cargo command in.
+export interface RustTargetDefinition extends vscode.TaskDefinition {
+    program: string;
+    args: string[];
     cwd?: string;
-    // The shell environment.
     env?: { [key: string]: string };
-    // Override the cargo executable name, such as
-    // "my_custom_cargo_bin".
-    overrideCargo?: string;
 }
 
 class RustTaskProvider implements vscode.TaskProvider {
@@ -46,12 +37,14 @@ class RustTaskProvider implements vscode.TaskProvider {
             { command: "run", group: undefined },
         ];
 
+        const cargoPath = await toolchain.cargoPath();
+
         const tasks: vscode.Task[] = [];
         for (const workspaceTarget of vscode.workspace.workspaceFolders || []) {
             for (const def of defs) {
                 const vscodeTask = await buildRustTask(
                     workspaceTarget,
-                    { type: TASK_TYPE, command: def.command },
+                    { type: TASK_TYPE, program: cargoPath, args: [def.command] },
                     `cargo ${def.command}`,
                     this.config.problemMatcher,
                     this.config.cargoRunner,
@@ -69,7 +62,7 @@ class RustTaskProvider implements vscode.TaskProvider {
         // we need to inform VSCode how to execute that command by creating
         // a ShellExecution for it.
 
-        const definition = task.definition as CargoTaskDefinition;
+        const definition = task.definition as RustTargetDefinition;
 
         if (definition.type === TASK_TYPE) {
             return await buildRustTask(
@@ -87,34 +80,16 @@ class RustTaskProvider implements vscode.TaskProvider {
 
 export async function buildRustTask(
     scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined,
-    definition: CargoTaskDefinition,
+    definition: RustTargetDefinition,
     name: string,
     problemMatcher: string[],
     customRunner?: string,
     throwOnError: boolean = false,
 ): Promise<vscode.Task> {
-    const exec = await cargoToExecution(definition, customRunner, throwOnError);
-
-    return new vscode.Task(
-        definition,
-        // scope can sometimes be undefined. in these situations we default to the workspace taskscope as
-        // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider)
-        scope ?? vscode.TaskScope.Workspace,
-        name,
-        TASK_SOURCE,
-        exec,
-        problemMatcher,
-    );
-}
+    let exec: vscode.ProcessExecution | vscode.ShellExecution | undefined = undefined;
 
-async function cargoToExecution(
-    definition: CargoTaskDefinition,
-    customRunner: string | undefined,
-    throwOnError: boolean,
-): Promise<vscode.ProcessExecution | vscode.ShellExecution> {
     if (customRunner) {
         const runnerCommand = `${customRunner}.buildShellExecution`;
-
         try {
             const runnerArgs = {
                 kind: TASK_TYPE,
@@ -125,7 +100,7 @@ async function cargoToExecution(
             const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs);
             if (customExec) {
                 if (customExec instanceof vscode.ShellExecution) {
-                    return customExec;
+                    exec = customExec;
                 } else {
                     log.debug("Invalid cargo ShellExecution", customExec);
                     throw "Invalid cargo ShellExecution.";
@@ -138,20 +113,20 @@ async function cargoToExecution(
         }
     }
 
-    // Check whether we must use a user-defined substitute for cargo.
-    // Split on spaces to allow overrides like "wrapper cargo".
-    const cargoPath = await toolchain.cargoPath();
-    const cargoCommand = definition.overrideCargo?.split(" ") ?? [cargoPath];
-
-    const args = [definition.command].concat(definition.args ?? []);
-    const fullCommand = [...cargoCommand, ...args];
-
-    const processName = unwrapUndefinable(fullCommand[0]);
+    if (!exec) {
+        exec = new vscode.ProcessExecution(definition.program, definition.args, definition);
+    }
 
-    return new vscode.ProcessExecution(processName, fullCommand.slice(1), {
-        cwd: definition.cwd,
-        env: definition.env,
-    });
+    return new vscode.Task(
+        definition,
+        // scope can sometimes be undefined. in these situations we default to the workspace taskscope as
+        // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider)
+        scope ?? vscode.TaskScope.Workspace,
+        name,
+        TASK_SOURCE,
+        exec,
+        problemMatcher,
+    );
 }
 
 export function activateTaskProvider(config: Config): vscode.Disposable {
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 7dc1b40783..b23d700263 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -84,7 +84,7 @@ impl CommentBlock {
                 panic!("Use plain (non-doc) comments with tags like {tag}:\n    {first}");
             }
 
-            block.id = id.trim().to_owned();
+            id.trim().clone_into(&mut block.id);
             true
         });
         blocks
diff --git a/xtask/src/codegen/lints.rs b/xtask/src/codegen/lints.rs
index 63abcfc090..6975f9328e 100644
--- a/xtask/src/codegen/lints.rs
+++ b/xtask/src/codegen/lints.rs
@@ -280,7 +280,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) {
             let line = &line[..up_to];
 
             let clippy_lint = clippy_lints.last_mut().expect("clippy lint must already exist");
-            clippy_lint.help = unescape(line).trim().to_owned();
+            unescape(line).trim().clone_into(&mut clippy_lint.help);
         }
     }
     clippy_lints.sort_by(|lint, lint2| lint.id.cmp(&lint2.id));
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index 2fe9db98cf..7e54d19fe4 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -10,11 +10,7 @@ use time::OffsetDateTime;
 use xshell::{cmd, Shell};
 use zip::{write::FileOptions, DateTime, ZipWriter};
 
-use crate::{
-    date_iso,
-    flags::{self, Malloc},
-    project_root,
-};
+use crate::{date_iso, flags, project_root};
 
 const VERSION_STABLE: &str = "0.3";
 const VERSION_NIGHTLY: &str = "0.4";
@@ -26,7 +22,6 @@ impl flags::Dist {
 
         let project_root = project_root();
         let target = Target::get(&project_root);
-        let allocator = self.allocator();
         let dist = project_root.join("dist");
         sh.remove_path(&dist)?;
         sh.create_dir(&dist)?;
@@ -38,11 +33,11 @@ impl flags::Dist {
                 // A hack to make VS Code prefer nightly over stable.
                 format!("{VERSION_NIGHTLY}.{patch_version}")
             };
-            dist_server(sh, &format!("{version}-standalone"), &target, allocator)?;
+            dist_server(sh, &format!("{version}-standalone"), &target)?;
             let release_tag = if stable { date_iso(sh)? } else { "nightly".to_owned() };
             dist_client(sh, &version, &release_tag, &target)?;
         } else {
-            dist_server(sh, "0.0.0-standalone", &target, allocator)?;
+            dist_server(sh, "0.0.0-standalone", &target)?;
         }
         Ok(())
     }
@@ -78,12 +73,7 @@ fn dist_client(
     Ok(())
 }
 
-fn dist_server(
-    sh: &Shell,
-    release: &str,
-    target: &Target,
-    allocator: Malloc,
-) -> anyhow::Result<()> {
+fn dist_server(sh: &Shell, release: &str, target: &Target) -> anyhow::Result<()> {
     let _e = sh.push_env("CFG_RELEASE", release);
     let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin");
 
@@ -97,8 +87,7 @@ fn dist_server(
     }
 
     let target_name = &target.name;
-    let features = allocator.to_features();
-    cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release").run()?;
+    cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} --release").run()?;
 
     let dst = Path::new("dist").join(&target.artifact_name);
     gzip(&target.server_path, &dst.with_extension("gz"))?;
diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs
index 9066545920..f7ae0eb1b4 100644
--- a/xtask/src/flags.rs
+++ b/xtask/src/flags.rs
@@ -2,7 +2,7 @@
 
 use std::str::FromStr;
 
-use crate::install::{ClientOpt, ServerOpt};
+use crate::install::{ClientOpt, Malloc, ServerOpt};
 
 xflags::xflags! {
     src "./src/flags.rs"
@@ -36,10 +36,6 @@ xflags::xflags! {
             optional --dry-run
         }
         cmd dist {
-            /// Use mimalloc allocator for server
-            optional --mimalloc
-            /// Use jemalloc allocator for server
-            optional --jemalloc
             optional --client-patch-version version: String
         }
         /// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
@@ -85,6 +81,35 @@ pub enum XtaskCmd {
     Codegen(Codegen),
 }
 
+#[derive(Debug)]
+pub struct Codegen {
+    pub check: bool,
+    pub codegen_type: Option<CodegenType>,
+}
+
+#[derive(Debug, Default)]
+pub enum CodegenType {
+    #[default]
+    All,
+    Grammar,
+    AssistsDocTests,
+    DiagnosticsDocs,
+    LintDefinitions,
+}
+
+impl FromStr for CodegenType {
+    type Err = String;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "all" => Ok(Self::All),
+            "grammar" => Ok(Self::Grammar),
+            "assists-doc-tests" => Ok(Self::AssistsDocTests),
+            "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
+            "lints-definitions" => Ok(Self::LintDefinitions),
+            _ => Err("Invalid option".to_owned()),
+        }
+    }
+}
 #[derive(Debug)]
 pub struct Install {
     pub client: bool,
@@ -110,8 +135,6 @@ pub struct Promote {
 
 #[derive(Debug)]
 pub struct Dist {
-    pub mimalloc: bool,
-    pub jemalloc: bool,
     pub client_patch_version: Option<String>,
 }
 
@@ -122,65 +145,6 @@ pub struct PublishReleaseNotes {
     pub dry_run: bool,
 }
 
-#[derive(Debug)]
-pub struct Metrics {
-    pub measurement_type: Option<MeasurementType>,
-}
-
-#[derive(Debug)]
-pub struct Bb {
-    pub suffix: String,
-}
-
-#[derive(Debug)]
-pub struct Codegen {
-    pub codegen_type: Option<CodegenType>,
-
-    pub check: bool,
-}
-
-impl Xtask {
-    #[allow(dead_code)]
-    pub fn from_env_or_exit() -> Self {
-        Self::from_env_or_exit_()
-    }
-
-    #[allow(dead_code)]
-    pub fn from_env() -> xflags::Result<Self> {
-        Self::from_env_()
-    }
-
-    #[allow(dead_code)]
-    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
-        Self::from_vec_(args)
-    }
-}
-// generated end
-
-#[derive(Debug, Default)]
-pub enum CodegenType {
-    #[default]
-    All,
-    Grammar,
-    AssistsDocTests,
-    DiagnosticsDocs,
-    LintDefinitions,
-}
-
-impl FromStr for CodegenType {
-    type Err = String;
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "all" => Ok(Self::All),
-            "grammar" => Ok(Self::Grammar),
-            "assists-doc-tests" => Ok(Self::AssistsDocTests),
-            "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
-            "lints-definitions" => Ok(Self::LintDefinitions),
-            _ => Err("Invalid option".to_owned()),
-        }
-    }
-}
-
 #[derive(Debug)]
 pub enum MeasurementType {
     Build,
@@ -221,22 +185,33 @@ impl AsRef<str> for MeasurementType {
     }
 }
 
-#[derive(Clone, Copy, Debug)]
-pub(crate) enum Malloc {
-    System,
-    Mimalloc,
-    Jemalloc,
+#[derive(Debug)]
+pub struct Metrics {
+    pub measurement_type: Option<MeasurementType>,
+}
+
+#[derive(Debug)]
+pub struct Bb {
+    pub suffix: String,
 }
 
-impl Malloc {
-    pub(crate) fn to_features(self) -> &'static [&'static str] {
-        match self {
-            Malloc::System => &[][..],
-            Malloc::Mimalloc => &["--features", "mimalloc"],
-            Malloc::Jemalloc => &["--features", "jemalloc"],
-        }
+impl Xtask {
+    #[allow(dead_code)]
+    pub fn from_env_or_exit() -> Self {
+        Self::from_env_or_exit_()
+    }
+
+    #[allow(dead_code)]
+    pub fn from_env() -> xflags::Result<Self> {
+        Self::from_env_()
+    }
+
+    #[allow(dead_code)]
+    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
+        Self::from_vec_(args)
     }
 }
+// generated end
 
 impl Install {
     pub(crate) fn server(&self) -> Option<ServerOpt> {
@@ -259,15 +234,3 @@ impl Install {
         Some(ClientOpt { code_bin: self.code_bin.clone() })
     }
 }
-
-impl Dist {
-    pub(crate) fn allocator(&self) -> Malloc {
-        if self.mimalloc {
-            Malloc::Mimalloc
-        } else if self.jemalloc {
-            Malloc::Jemalloc
-        } else {
-            Malloc::System
-        }
-    }
-}
diff --git a/xtask/src/install.rs b/xtask/src/install.rs
index 72e612f9e1..dc932da80c 100644
--- a/xtask/src/install.rs
+++ b/xtask/src/install.rs
@@ -5,7 +5,7 @@ use std::{env, path::PathBuf, str};
 use anyhow::{bail, format_err, Context};
 use xshell::{cmd, Shell};
 
-use crate::flags::{self, Malloc};
+use crate::flags;
 
 impl flags::Install {
     pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
@@ -34,6 +34,12 @@ pub(crate) struct ServerOpt {
     pub(crate) dev_rel: bool,
 }
 
+pub(crate) enum Malloc {
+    System,
+    Mimalloc,
+    Jemalloc,
+}
+
 fn fix_path_for_mac(sh: &Shell) -> anyhow::Result<()> {
     let mut vscode_path: Vec<PathBuf> = {
         const COMMON_APP_PATH: &str =
@@ -116,7 +122,7 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> anyhow::Result<()> {
     if !installed_extensions.contains("rust-analyzer") {
         bail!(
             "Could not install the Visual Studio Code extension. \
-            Please make sure you have at least NodeJS 16.x together with the latest version of VS Code installed and try again. \
+            Please make sure you have at least NodeJS 12.x together with the latest version of VS Code installed and try again. \
             Note that installing via xtask install does not work for VS Code Remote, instead you’ll need to install the .vsix manually."
         );
     }
@@ -125,7 +131,11 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> anyhow::Result<()> {
 }
 
 fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> {
-    let features = opts.malloc.to_features();
+    let features = match opts.malloc {
+        Malloc::System => &[][..],
+        Malloc::Mimalloc => &["--features", "mimalloc"],
+        Malloc::Jemalloc => &["--features", "jemalloc"],
+    };
     let profile = if opts.dev_rel { "dev-rel" } else { "release" };
 
     let cmd = cmd!(sh, "cargo install --path crates/rust-analyzer --profile={profile} --locked --force --features force-always-assert {features...}");


Test patch:
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index d1ffd5046c..98384c4749 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -2825,30 +2825,3 @@ fn unsized_local() {
         |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))),
     );
 }
-
-#[test]
-fn recursive_adt() {
-    check_fail(
-        r#"
-        //- minicore: coerce_unsized, index, slice
-        pub enum TagTree {
-            Leaf,
-            Choice(&'static [TagTree]),
-        }
-        const GOAL: TagTree = {
-            const TAG_TREE: TagTree = TagTree::Choice(&[
-                {
-                    const VARIANT_TAG_TREE: TagTree = TagTree::Choice(
-                        &[
-                            TagTree::Leaf,
-                        ],
-                    );
-                    VARIANT_TAG_TREE
-                },
-            ]);
-            TAG_TREE
-        };
-    "#,
-        |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
-    );
-}
diff --git a/crates/hir-ty/src/tests/display_source_code.rs b/crates/hir-ty/src/tests/display_source_code.rs
index 5069267499..e75b037e38 100644
--- a/crates/hir-ty/src/tests/display_source_code.rs
+++ b/crates/hir-ty/src/tests/display_source_code.rs
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
 trait Foo<'a> {}
 
 fn foo(foo: &dyn for<'a> Foo<'a>) {}
-    // ^^^ &dyn Foo<'static>
+    // ^^^ &dyn Foo
 "#,
     );
 }
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 80d5a0ae00..963b4a2aba 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -1109,7 +1109,7 @@ fn var_args() {
 #[lang = "va_list"]
 pub struct VaListImpl<'f>;
 fn my_fn(foo: ...) {}
-       //^^^ VaListImpl<'static>
+       //^^^ VaListImpl<'_>
 "#,
     );
 }
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 8565b60210..9a8ebd07d0 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -896,13 +896,13 @@ fn flush(&self) {
 "#,
         expect![[r#"
             123..127 'self': &Mutex<T>
-            150..152 '{}': MutexGuard<'static, T>
+            150..152 '{}': MutexGuard<'_, T>
             234..238 'self': &{unknown}
             240..290 '{     ...()); }': ()
             250..251 'w': &Mutex<BufWriter>
             276..287 '*(w.lock())': BufWriter
             278..279 'w': &Mutex<BufWriter>
-            278..286 'w.lock()': MutexGuard<'static, BufWriter>
+            278..286 'w.lock()': MutexGuard<'_, BufWriter>
         "#]],
     );
 }
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index f39404593e..917e9f4408 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -3092,7 +3092,7 @@ fn main() {
             389..394 'boxed': Box<Foo<i32>>
             389..406 'boxed....nner()': &i32
             416..421 'good1': &i32
-            424..438 'Foo::get_inner': fn get_inner<i32, 'static>(&Box<Foo<i32>>) -> &i32
+            424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
             424..446 'Foo::g...boxed)': &i32
             439..445 '&boxed': &Box<Foo<i32>>
             440..445 'boxed': Box<Foo<i32>>
@@ -3100,7 +3100,7 @@ fn main() {
             464..469 'boxed': Box<Foo<i32>>
             464..480 'boxed....self()': &Foo<i32>
             490..495 'good2': &Foo<i32>
-            498..511 'Foo::get_self': fn get_self<i32, 'static>(&Box<Foo<i32>>) -> &Foo<i32>
+            498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
             498..519 'Foo::g...boxed)': &Foo<i32>
             512..518 '&boxed': &Box<Foo<i32>>
             513..518 'boxed': Box<Foo<i32>>
@@ -3659,7 +3659,7 @@ fn main() {
     let are = "are";
     let count = 10;
     builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'static>
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'_>
 }
 "#,
     );
diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs
index 3718dff56e..46a3e97d3e 100644
--- a/crates/ide-completion/src/tests/predicate.rs
+++ b/crates/ide-completion/src/tests/predicate.rs
@@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            st Foo<…>    Foo<'static, {unknown}, _>
+            st Foo<…>    Foo<'_, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
@@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            st Foo<…>    Foo<'static, {unknown}, _>
+            st Foo<…>    Foo<'_, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index 9770972865..db4ac9381c 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> {
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            sp Self      Foo<'static, {unknown}, _>
-            st Foo<…>    Foo<'static, {unknown}, _>
+            sp Self      Foo<'_, {unknown}, _>
+            st Foo<…>    Foo<'_, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
@@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
             en Enum       Enum
             ma makro!(…)  macro_rules! makro
             md module
-            sp Self       Foo<'static, {unknown}, _>
-            st Foo<…>     Foo<'static, {unknown}, _>
+            sp Self       Foo<'_, {unknown}, _>
+            st Foo<…>     Foo<'_, {unknown}, _>
             st Record     Record
             st Tuple      Tuple
             st Unit       Unit
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 08925fcdff..4451e31870 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -18,7 +18,6 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     format: HoverDocFormat::Markdown,
     keywords: true,
     max_trait_assoc_items_count: None,
-    max_struct_field_count: None,
 };
 
 fn check_hover_no_result(ra_fixture: &str) {
@@ -50,28 +49,6 @@ fn check(ra_fixture: &str, expect: Expect) {
     expect.assert_eq(&actual)
 }
 
-#[track_caller]
-fn check_hover_struct_limit(count: usize, ra_fixture: &str, expect: Expect) {
-    let (analysis, position) = fixture::position(ra_fixture);
-    let hover = analysis
-        .hover(
-            &HoverConfig {
-                links_in_hover: true,
-                max_struct_field_count: Some(count),
-                ..HOVER_BASE_CONFIG
-            },
-            FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
-        )
-        .unwrap()
-        .unwrap();
-
-    let content = analysis.db.file_text(position.file_id);
-    let hovered_element = &content[hover.range];
-
-    let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup);
-    expect.assert_eq(&actual)
-}
-
 #[track_caller]
 fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) {
     let (analysis, position) = fixture::position(ra_fixture);
@@ -876,7 +853,9 @@ struct Foo$0 { field: u32 }
 
             ```rust
             // size = 4, align = 4
-            struct Foo
+            struct Foo {
+                field: u32,
+            }
             ```
         "#]],
     );
@@ -896,74 +875,8 @@ struct Foo$0 where u32: Copy { field: u32 }
             struct Foo
             where
                 u32: Copy,
-            ```
-        "#]],
-    );
-}
-
-#[test]
-fn hover_record_struct_limit() {
-    check_hover_struct_limit(
-        3,
-        r#"
-    struct Foo$0 { a: u32, b: i32, c: i32 }
-    "#,
-        expect![[r#"
-            *Foo*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            // size = 12 (0xC), align = 4
-            struct Foo  {
-                a: u32,
-                b: i32,
-                c: i32,
-            }
-            ```
-        "#]],
-    );
-    check_hover_struct_limit(
-        3,
-        r#"
-    struct Foo$0 { a: u32 }
-    "#,
-        expect![[r#"
-            *Foo*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            // size = 4, align = 4
-            struct Foo  {
-                a: u32,
-            }
-            ```
-        "#]],
-    );
-    check_hover_struct_limit(
-        3,
-        r#"
-    struct Foo$0 { a: u32, b: i32, c: i32, d: u32 }
-    "#,
-        expect![[r#"
-            *Foo*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            // size = 16 (0x10), align = 4
-            struct Foo  {
-                a: u32,
-                b: i32,
-                c: i32,
-                /* … */
+            {
+                field: u32,
             }
             ```
         "#]],
@@ -1431,7 +1344,9 @@ impl Thing {
                 ```
 
                 ```rust
-                struct Thing
+                struct Thing {
+                    x: u32,
+                }
                 ```
             "#]],
     );
@@ -1450,7 +1365,9 @@ impl Thing {
                 ```
 
                 ```rust
-                struct Thing
+                struct Thing {
+                    x: u32,
+                }
                 ```
             "#]],
     );
@@ -2682,7 +2599,7 @@ fn main() { let s$0t = S{ f1:0 }; }
                                     focus_range: 7..8,
                                     name: "S",
                                     kind: Struct,
-                                    description: "struct S",
+                                    description: "struct S {\n    f1: u32,\n}",
                                 },
                             },
                         ],
@@ -2728,7 +2645,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
                                 focus_range: 24..25,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S<T>",
+                                description: "struct S<T> {\n    f1: T,\n}",
                             },
                         },
                     ],
@@ -2787,7 +2704,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
                                 focus_range: 24..25,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S<T>",
+                                description: "struct S<T> {\n    f1: T,\n}",
                             },
                         },
                     ],
@@ -3040,7 +2957,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 39..41,
                                 name: "S1",
                                 kind: Struct,
-                                description: "struct S1",
+                                description: "struct S1 {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3053,7 +2970,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 52..54,
                                 name: "S2",
                                 kind: Struct,
-                                description: "struct S2",
+                                description: "struct S2 {}",
                             },
                         },
                     ],
@@ -3144,7 +3061,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                                 focus_range: 36..37,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S",
+                                description: "struct S {}",
                             },
                         },
                     ],
@@ -3244,7 +3161,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
                                 focus_range: 23..24,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S",
+                                description: "struct S {}",
                             },
                         },
                     ],
@@ -3281,7 +3198,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 49..50,
                                 name: "B",
                                 kind: Struct,
-                                description: "struct B<T>",
+                                description: "struct B<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3370,7 +3287,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
                                 focus_range: 23..24,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S",
+                                description: "struct S {}",
                             },
                         },
                     ],
@@ -3405,7 +3322,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 50..51,
                                 name: "B",
                                 kind: Struct,
-                                description: "struct B<T>",
+                                description: "struct B<T> {}",
                             },
                         },
                         HoverGotoTypeData {
@@ -3444,7 +3361,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 65..66,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S",
+                                description: "struct S {}",
                             },
                         },
                     ],
@@ -5188,32 +5105,6 @@ fn foo(e: E) {
     );
 }
 
-#[test]
-fn hover_const_value() {
-    check(
-        r#"
-pub enum AA {
-    BB,
-}
-const CONST: AA = AA::BB;
-pub fn the_function() -> AA {
-    CON$0ST
-}
-"#,
-        expect![[r#"
-            *CONST*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            const CONST: AA = BB
-            ```
-        "#]],
-    );
-}
-
 #[test]
 fn array_repeat_exp() {
     check(
@@ -7856,25 +7747,3 @@ impl Iterator for S {
         "#]],
     );
 }
-
-#[test]
-fn hover_lifetime_regression_16963() {
-    check(
-        r#"
-struct Pedro$0<'a> {
-    hola: &'a str
-}
-"#,
-        expect![[r#"
-            *Pedro*
-
-            ```rust
-            test
-            ```
-
-            ```rust
-            struct Pedro<'a>
-            ```
-        "#]],
-    )
-}
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index c2990fd76e..74d3e663d6 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -1229,20 +1229,3 @@ fn benchmark_syntax_highlighting_parser() {
     };
     assert_eq!(hash, 1169);
 }
-
-#[test]
-fn highlight_trait_with_lifetimes_regression_16958() {
-    let (analysis, file_id) = fixture::file(
-        r#"
-pub trait Deserialize<'de> {
-    fn deserialize();
-}
-
-fn f<'de, T: Deserialize<'de>>() {
-    T::deserialize();
-}
-"#
-        .trim(),
-    );
-    let _ = analysis.highlight(HL_CONFIG, file_id).unwrap();
-}
diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs
index 99e2430860..ca47139970 100644
--- a/crates/ide/src/test_explorer.rs
+++ b/crates/ide/src/test_explorer.rs
@@ -7,7 +7,7 @@ use ide_db::{
 };
 use syntax::TextRange;
 
-use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav};
+use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav};
 
 #[derive(Debug)]
 pub enum TestItemKind {
@@ -56,12 +56,7 @@ fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId>
     })
 }
 
-fn discover_tests_in_module(
-    db: &RootDatabase,
-    module: Module,
-    prefix_id: String,
-    only_in_this_file: bool,
-) -> Vec<TestItem> {
+fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec<TestItem> {
     let sema = Semantics::new(db);
 
     let mut r = vec![];
@@ -69,9 +64,9 @@ fn discover_tests_in_module(
         let module_name =
             c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned();
         let module_id = format!("{prefix_id}::{module_name}");
-        let module_children = discover_tests_in_module(db, c, module_id.clone(), only_in_this_file);
+        let module_children = discover_tests_in_module(db, c, module_id.clone());
         if !module_children.is_empty() {
-            let nav = NavigationTarget::from_module_to_decl(sema.db, c).call_site;
+            let nav = c.to_nav(db).call_site;
             r.push(TestItem {
                 id: module_id,
                 kind: TestItemKind::Module,
@@ -81,9 +76,7 @@ fn discover_tests_in_module(
                 text_range: Some(nav.focus_or_full_range()),
                 runnable: None,
             });
-            if !only_in_this_file || c.is_inline(db) {
-                r.extend(module_children);
-            }
+            r.extend(module_children);
         }
     }
     for def in module.declarations(db) {
@@ -119,55 +112,6 @@ pub(crate) fn discover_tests_in_crate_by_test_id(
     discover_tests_in_crate(db, crate_id)
 }
 
-pub(crate) fn discover_tests_in_file(db: &RootDatabase, file_id: FileId) -> Vec<TestItem> {
-    let sema = Semantics::new(db);
-
-    let Some(module) = sema.file_to_module_def(file_id) else { return vec![] };
-    let Some((mut tests, id)) = find_module_id_and_test_parents(&sema, module) else {
-        return vec![];
-    };
-    tests.extend(discover_tests_in_module(db, module, id, true));
-    tests
-}
-
-fn find_module_id_and_test_parents(
-    sema: &Semantics<'_, RootDatabase>,
-    module: Module,
-) -> Option<(Vec<TestItem>, String)> {
-    let Some(parent) = module.parent(sema.db) else {
-        let name = module.krate().display_name(sema.db)?.to_string();
-        return Some((
-            vec![TestItem {
-                id: name.clone(),
-                kind: TestItemKind::Crate(module.krate().into()),
-                label: name.clone(),
-                parent: None,
-                file: None,
-                text_range: None,
-                runnable: None,
-            }],
-            name,
-        ));
-    };
-    let (mut r, mut id) = find_module_id_and_test_parents(sema, parent)?;
-    let parent = Some(id.clone());
-    id += "::";
-    let module_name = &module.name(sema.db);
-    let module_name = module_name.as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]");
-    id += module_name;
-    let nav = NavigationTarget::from_module_to_decl(sema.db, module).call_site;
-    r.push(TestItem {
-        id: id.clone(),
-        kind: TestItemKind::Module,
-        label: module_name.to_owned(),
-        parent,
-        file: Some(nav.file_id),
-        text_range: Some(nav.focus_or_full_range()),
-        runnable: None,
-    });
-    Some((r, id))
-}
-
 pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
     let crate_graph = db.crate_graph();
     if !crate_graph[crate_id].origin.is_local() {
@@ -189,6 +133,6 @@ pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> V
         text_range: None,
         runnable: None,
     }];
-    r.extend(discover_tests_in_module(db, module, crate_test_id, false));
+    r.extend(discover_tests_in_module(db, module, crate_test_id));
     r
 }
diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs
index 78da4487d4..3443939133 100644
--- a/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -243,7 +243,7 @@ struct TidyDocs {
 impl TidyDocs {
     fn visit(&mut self, path: &Path, text: &str) {
         // Tests and diagnostic fixes don't need module level comments.
-        if is_exclude_dir(path, &["tests", "test_data", "fixes", "grammar"]) {
+        if is_exclude_dir(path, &["tests", "test_data", "fixes", "grammar", "salsa"]) {
             return;
         }
 
diff --git a/crates/test-utils/src/fixture.rs b/crates/test-utils/src/fixture.rs
index 7e34c36189..aafe4fb5b1 100644
--- a/crates/test-utils/src/fixture.rs
+++ b/crates/test-utils/src/fixture.rs
@@ -186,7 +186,7 @@ impl FixtureWithProjectMeta {
 
         if let Some(meta) = fixture.strip_prefix("//- target_data_layout:") {
             let (meta, remain) = meta.split_once('\n').unwrap();
-            target_data_layout = meta.trim().to_owned();
+            meta.trim().clone_into(&mut target_data_layout);
             fixture = remain;
         }
 
diff --git a/editors/code/src/test_explorer.ts b/editors/code/src/test_explorer.ts
index de41d2a57e..ae5351a185 100644
--- a/editors/code/src/test_explorer.ts
+++ b/editors/code/src/test_explorer.ts
@@ -12,7 +12,6 @@ export const prepareTestExplorer = (
 ) => {
     let currentTestRun: vscode.TestRun | undefined;
     let idToTestMap: Map<string, vscode.TestItem> = new Map();
-    const fileToTestMap: Map<string, vscode.TestItem[]> = new Map();
     const idToRunnableMap: Map<string, ra.Runnable> = new Map();
 
     testController.createRunProfile(
@@ -60,18 +59,6 @@ export const prepareTestExplorer = (
         false,
     );
 
-    const deleteTest = (item: vscode.TestItem, parentList: vscode.TestItemCollection) => {
-        parentList.delete(item.id);
-        idToTestMap.delete(item.id);
-        idToRunnableMap.delete(item.id);
-        if (item.uri) {
-            fileToTestMap.set(
-                item.uri.toString(),
-                fileToTestMap.get(item.uri.toString())!.filter((t) => t.id !== item.id),
-            );
-        }
-    };
-
     const addTest = (item: ra.TestItem) => {
         const parentList = item.parent
             ? idToTestMap.get(item.parent)!.children
@@ -89,7 +76,7 @@ export const prepareTestExplorer = (
                 oldTest.range = range;
                 return;
             }
-            deleteTest(oldTest, parentList);
+            parentList.delete(item.id);
         }
         const iconToVscodeMap = {
             package: "package",
@@ -104,12 +91,6 @@ export const prepareTestExplorer = (
         test.range = range;
         test.canResolveChildren = item.canResolveChildren;
         idToTestMap.set(item.id, test);
-        if (uri) {
-            if (!fileToTestMap.has(uri.toString())) {
-                fileToTestMap.set(uri.toString(), []);
-            }
-            fileToTestMap.get(uri.toString())!.push(test);
-        }
         if (item.runnable) {
             idToRunnableMap.set(item.id, item.runnable);
         }
@@ -117,7 +98,7 @@ export const prepareTestExplorer = (
     };
 
     const addTestGroup = (testsAndScope: ra.DiscoverTestResults) => {
-        const { tests, scope, scopeFile } = testsAndScope;
+        const { tests, scope } = testsAndScope;
         const testSet: Set<string> = new Set();
         for (const test of tests) {
             addTest(test);
@@ -126,38 +107,25 @@ export const prepareTestExplorer = (
         // FIXME(hack_recover_crate_name): We eagerly resolve every test if we got a lazy top level response (detected
         // by checking that `scope` is empty). This is not a good thing and wastes cpu and memory unnecessarily, so we
         // should remove it.
-        if (!scope && !scopeFile) {
+        if (scope.length === 0) {
             for (const test of tests) {
                 void testController.resolveHandler!(idToTestMap.get(test.id));
             }
         }
-        if (scope) {
-            const recursivelyRemove = (tests: vscode.TestItemCollection) => {
-                for (const [_, test] of tests) {
-                    if (!testSet.has(test.id)) {
-                        deleteTest(test, tests);
-                    } else {
-                        recursivelyRemove(test.children);
-                    }
-                }
-            };
-            for (const root of scope) {
-                recursivelyRemove(idToTestMap.get(root)!.children);
-            }
+        if (!scope) {
+            return;
         }
-        if (scopeFile) {
-            const removeByFile = (file: vscode.Uri) => {
-                const testsToBeRemoved = (fileToTestMap.get(file.toString()) || []).filter(
-                    (t) => !testSet.has(t.id),
-                );
-                for (const test of testsToBeRemoved) {
-                    const parentList = test.parent?.children || testController.items;
-                    deleteTest(test, parentList);
+        const recursivelyRemove = (tests: vscode.TestItemCollection) => {
+            for (const [testId, _] of tests) {
+                if (!testSet.has(testId)) {
+                    tests.delete(testId);
+                } else {
+                    recursivelyRemove(tests.get(testId)!.children);
                 }
-            };
-            for (const file of scopeFile) {
-                removeByFile(vscode.Uri.parse(file.uri));
             }
+        };
+        for (const root of scope) {
+            recursivelyRemove(idToTestMap.get(root)!.children);
         }
     };