Repository: rust-lang/rust-analyzer
Pull request #17030 (2024-04-08 08:46:26)

internal: Bump chalk
And make use of the new error lifetime


Patch:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 11014338d7..3ad7a37ec1 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -95,7 +95,7 @@ jobs:
         run: sudo apt-get install gcc-arm-linux-gnueabihf
 
       - name: Dist
-        run: cargo xtask dist --client-patch-version ${{ github.run_number }}
+        run: cargo xtask dist --jemalloc --client-patch-version ${{ github.run_number }}
 
       - run: npm ci
         working-directory: editors/code
@@ -159,7 +159,7 @@ jobs:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
       - name: Dist
-        run: cargo xtask dist --client-patch-version ${{ github.run_number }}
+        run: cargo xtask dist --jemalloc --client-patch-version ${{ github.run_number }}
 
       - run: npm ci
         working-directory: editors/code
diff --git a/Cargo.lock b/Cargo.lock
index c7cf4479b3..1209cee03c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -161,9 +161,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chalk-derive"
-version = "0.96.0"
+version = "0.97.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a"
+checksum = "92a0aedc4ac2adc5c0b7dc9ec38c5c816284ad28da6d4ecd01873b9683f54972"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -173,20 +173,19 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.96.0"
+version = "0.97.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d"
+checksum = "db18493569b190f7266a04901e520fc3a5c00564475154287906f8a27302c119"
 dependencies = [
  "bitflags 2.4.2",
  "chalk-derive",
- "lazy_static",
 ]
 
 [[package]]
 name = "chalk-recursive"
-version = "0.96.0"
+version = "0.97.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4559e5c9b200240453b07d893f9c3c74413b53b0d33cbe272c68b0b77aa1c3"
+checksum = "ae4ba8ce5bd2e1b59f1f79495bc8704db09a8285e51cc5ddf01d9baee1bf447d"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -197,9 +196,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.96.0"
+version = "0.97.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0882e68ce9eb5a0a2413806538494d19df6ee520ab17d1faf489e952f32e98b8"
+checksum = "b2ec1b3b7f7b1ec38f099ef39c2bc3ea29335be1b8316d114baff46d96d131e9"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
diff --git a/Cargo.toml b/Cargo.toml
index 99338d9d97..06b092a449 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -106,10 +106,10 @@ arrayvec = "0.7.4"
 bitflags = "2.4.1"
 cargo_metadata = "0.18.1"
 camino = "1.1.6"
-chalk-solve = { version = "0.96.0", default-features = false }
-chalk-ir = "0.96.0"
-chalk-recursive = { version = "0.96.0", default-features = false }
-chalk-derive = "0.96.0"
+chalk-solve = { version = "0.97.0", default-features = false }
+chalk-ir = "0.97.0"
+chalk-recursive = { version = "0.97.0", default-features = false }
+chalk-derive = "0.97.0"
 command-group = "2.0.1"
 crossbeam-channel = "0.5.8"
 dissimilar = "1.0.7"
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index fe8e882bf6..4ee86954ac 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -41,50 +41,19 @@ pub enum InvocationLocation {
     Workspace,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct CargoOptions {
-    pub target_triples: Vec<String>,
-    pub all_targets: bool,
-    pub no_default_features: bool,
-    pub all_features: bool,
-    pub features: Vec<String>,
-    pub extra_args: Vec<String>,
-    pub extra_env: FxHashMap<String, String>,
-    pub target_dir: Option<Utf8PathBuf>,
-}
-
-impl CargoOptions {
-    fn apply_on_command(&self, cmd: &mut Command) {
-        for target in &self.target_triples {
-            cmd.args(["--target", target.as_str()]);
-        }
-        if self.all_targets {
-            cmd.arg("--all-targets");
-        }
-        if self.all_features {
-            cmd.arg("--all-features");
-        } else {
-            if self.no_default_features {
-                cmd.arg("--no-default-features");
-            }
-            if !self.features.is_empty() {
-                cmd.arg("--features");
-                cmd.arg(self.features.join(" "));
-            }
-        }
-        if let Some(target_dir) = &self.target_dir {
-            cmd.arg("--target-dir").arg(target_dir);
-        }
-        cmd.envs(&self.extra_env);
-    }
-}
-
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum FlycheckConfig {
     CargoCommand {
         command: String,
-        options: CargoOptions,
+        target_triples: Vec<String>,
+        all_targets: bool,
+        no_default_features: bool,
+        all_features: bool,
+        features: Vec<String>,
+        extra_args: Vec<String>,
+        extra_env: FxHashMap<String, String>,
         ansi_color_output: bool,
+        target_dir: Option<Utf8PathBuf>,
     },
     CustomCommand {
         command: String,
@@ -363,7 +332,18 @@ impl FlycheckActor {
         saved_file: Option<&AbsPath>,
     ) -> Option<Command> {
         let (mut cmd, args) = match &self.config {
-            FlycheckConfig::CargoCommand { command, options, ansi_color_output } => {
+            FlycheckConfig::CargoCommand {
+                command,
+                target_triples,
+                no_default_features,
+                all_targets,
+                all_features,
+                extra_args,
+                features,
+                extra_env,
+                ansi_color_output,
+                target_dir,
+            } => {
                 let mut cmd = Command::new(Tool::Cargo.path());
                 if let Some(sysroot_root) = &self.sysroot_root {
                     cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root));
@@ -385,8 +365,28 @@ impl FlycheckActor {
                 cmd.arg("--manifest-path");
                 cmd.arg(self.root.join("Cargo.toml"));
 
-                options.apply_on_command(&mut cmd);
-                (cmd, options.extra_args.clone())
+                for target in target_triples {
+                    cmd.args(["--target", target.as_str()]);
+                }
+                if *all_targets {
+                    cmd.arg("--all-targets");
+                }
+                if *all_features {
+                    cmd.arg("--all-features");
+                } else {
+                    if *no_default_features {
+                        cmd.arg("--no-default-features");
+                    }
+                    if !features.is_empty() {
+                        cmd.arg("--features");
+                        cmd.arg(features.join(" "));
+                    }
+                }
+                if let Some(target_dir) = target_dir {
+                    cmd.arg("--target-dir").arg(target_dir);
+                }
+                cmd.envs(extra_env);
+                (cmd, extra_args.clone())
             }
             FlycheckConfig::CustomCommand {
                 command,
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 22a52e6a23..42e33a9853 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -42,9 +42,10 @@ use crate::{
     primitive, to_assoc_type_id,
     utils::{self, detect_variant_from_bytes, generics, ClosureSubst},
     AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstScalar, ConstValue,
-    DomainGoal, FnAbi, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives,
-    MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar,
-    Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyExt, WhereClause,
+    DomainGoal, FnAbi, GenericArg, GenericArgData, ImplTraitId, Interner, Lifetime, LifetimeData,
+    LifetimeOutlives, MemoryMap, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
+    QuantifiedWhereClause, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty,
+    TyExt, WhereClause,
 };
 
 pub trait HirWrite: fmt::Write {
@@ -1367,8 +1368,8 @@ fn hir_fmt_generics(
                                 return true;
                             }
                         }
-                        if parameter.lifetime(Interner).map(|it| it.data(Interner))
-                            == Some(&crate::LifetimeData::Static)
+                        if let Some(crate::LifetimeData::Static | crate::LifetimeData::Error) =
+                            parameter.lifetime(Interner).map(|it| it.data(Interner))
                         {
                             return true;
                         }
@@ -1403,10 +1404,18 @@ fn hir_fmt_generics(
                     write!(f, ", ")?;
                 }
                 first = false;
-                if f.display_target.is_source_code()
-                    && generic_arg.ty(Interner).map(|ty| ty.kind(Interner)) == Some(&TyKind::Error)
-                {
-                    write!(f, "_")?;
+                if f.display_target.is_source_code() {
+                    match generic_arg.data(Interner) {
+                        GenericArgData::Lifetime(l)
+                            if matches!(l.data(Interner), LifetimeData::Error) =>
+                        {
+                            write!(f, "'_")
+                        }
+                        GenericArgData::Ty(t) if matches!(t.kind(Interner), TyKind::Error) => {
+                            write!(f, "_")
+                        }
+                        _ => generic_arg.hir_fmt(f),
+                    }?
                 } else {
                     generic_arg.hir_fmt(f)?;
                 }
@@ -1729,6 +1738,7 @@ impl HirDisplay for LifetimeData {
                 Ok(())
             }
             LifetimeData::Static => write!(f, "'static"),
+            LifetimeData::Error => write!(f, "'{{error}}"),
             LifetimeData::Erased => Ok(()),
             LifetimeData::Phantom(_, _) => Ok(()),
         }
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index b12ccf7c83..b9f4c57366 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -612,8 +612,6 @@ has_interner!(ImplTraits);
 
 #[derive(PartialEq, Eq, Debug, Hash)]
 pub struct ImplTrait {
-    // FIXME: Should be Arc<[QuantifiedWhereClause]>, but the HasInterner impl for Arc is missing a
-    // ?Sized bound
     pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
 }
 
@@ -624,7 +622,7 @@ pub fn static_lifetime() -> Lifetime {
 }
 
 pub fn error_lifetime() -> Lifetime {
-    LifetimeData::Static.intern(Interner)
+    LifetimeData::Error.intern(Interner)
 }
 
 pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index bfc84ee5e3..4d0516ead6 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -67,9 +67,9 @@ use crate::{
     },
     AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
     FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
-    LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
-    QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
-    TyKind, WhereClause,
+    LifetimeData, LifetimeOutlives, ParamKind, PolyFnSig, ProgramClause, ProjectionTy,
+    QuantifiedWhereClause, QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef,
+    TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
 };
 
 #[derive(Debug)]
@@ -1052,11 +1052,11 @@ impl<'a> TyLoweringContext<'a> {
         self_ty: Ty,
         ignore_bindings: bool,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
-        let mut bindings = None;
-        let trait_ref = match bound.as_ref() {
+        let mut trait_ref = None;
+        let clause = match bound.as_ref() {
             TypeBound::Path(path, TraitBoundModifier::None) => {
-                bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
-                bindings
+                trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty));
+                trait_ref
                     .clone()
                     .filter(|tr| {
                         // ignore `T: Drop` or `T: Destruct` bounds.
@@ -1092,8 +1092,8 @@ impl<'a> TyLoweringContext<'a> {
             }
             TypeBound::ForLifetime(_, path) => {
                 // FIXME Don't silently drop the hrtb lifetimes here
-                bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
-                bindings.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
+                trait_ref = self.lower_trait_ref_from_path(path, Some(self_ty));
+                trait_ref.clone().map(WhereClause::Implemented).map(crate::wrap_empty_binders)
             }
             TypeBound::Lifetime(l) => {
                 let lifetime = self.lower_lifetime(l);
@@ -1104,8 +1104,8 @@ impl<'a> TyLoweringContext<'a> {
             }
             TypeBound::Error => None,
         };
-        trait_ref.into_iter().chain(
-            bindings
+        clause.into_iter().chain(
+            trait_ref
                 .into_iter()
                 .filter(move |_| !ignore_bindings)
                 .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)),
@@ -1624,10 +1624,14 @@ pub(crate) fn generic_predicates_for_param_query(
 
     let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
     let explicitly_unsized_tys = ctx.unsized_types.into_inner();
-    let implicitly_sized_predicates =
+    if let Some(implicitly_sized_predicates) =
         implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &subst, &resolver)
-            .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p)));
-    predicates.extend(implicitly_sized_predicates);
+    {
+        predicates.extend(
+            implicitly_sized_predicates
+                .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
+        );
+    }
     predicates.into()
 }
 
@@ -1685,24 +1689,23 @@ pub(crate) fn trait_environment_query(
         let substs = TyBuilder::placeholder_subst(db, trait_id);
         let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
         let pred = WhereClause::Implemented(trait_ref);
-        let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(Interner);
-        clauses.push(program_clause.into_from_env_clause(Interner));
+        clauses.push(pred.cast::<ProgramClause>(Interner).into_from_env_clause(Interner));
     }
 
     let subst = generics(db.upcast(), def).placeholder_subst(db);
     let explicitly_unsized_tys = ctx.unsized_types.into_inner();
-    let implicitly_sized_clauses =
-        implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver).map(|pred| {
-            let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(Interner);
-            program_clause.into_from_env_clause(Interner)
-        });
-    clauses.extend(implicitly_sized_clauses);
-
-    let krate = def.module(db.upcast()).krate();
+    if let Some(implicitly_sized_clauses) =
+        implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
+    {
+        clauses.extend(
+            implicitly_sized_clauses
+                .map(|pred| pred.cast::<ProgramClause>(Interner).into_from_env_clause(Interner)),
+        );
+    }
 
     let env = chalk_ir::Environment::new(Interner).add_clauses(Interner, clauses);
 
-    TraitEnvironment::new(krate, None, traits_in_scope.into_boxed_slice(), env)
+    TraitEnvironment::new(resolver.krate(), None, traits_in_scope.into_boxed_slice(), env)
 }
 
 /// Resolve the where clause(s) of an item with generics.
@@ -1730,10 +1733,14 @@ pub(crate) fn generic_predicates_query(
 
     let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
     let explicitly_unsized_tys = ctx.unsized_types.into_inner();
-    let implicitly_sized_predicates =
+    if let Some(implicitly_sized_predicates) =
         implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
-            .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p)));
-    predicates.extend(implicitly_sized_predicates);
+    {
+        predicates.extend(
+            implicitly_sized_predicates
+                .map(|p| make_binders(db, &generics, crate::wrap_empty_binders(p))),
+        );
+    }
     predicates.into()
 }
 
@@ -1745,24 +1752,24 @@ fn implicitly_sized_clauses<'a>(
     explicitly_unsized_tys: &'a FxHashSet<Ty>,
     substitution: &'a Substitution,
     resolver: &Resolver,
-) -> impl Iterator<Item = WhereClause> + 'a {
+) -> Option<impl Iterator<Item = WhereClause> + 'a> {
     let is_trait_def = matches!(def, GenericDefId::TraitId(..));
     let generic_args = &substitution.as_slice(Interner)[is_trait_def as usize..];
     let sized_trait = db
         .lang_item(resolver.krate(), LangItem::Sized)
         .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
 
-    sized_trait.into_iter().flat_map(move |sized_trait| {
-        let implicitly_sized_tys = generic_args
+    sized_trait.map(move |sized_trait| {
+        generic_args
             .iter()
             .filter_map(|generic_arg| generic_arg.ty(Interner))
-            .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty));
-        implicitly_sized_tys.map(move |self_ty| {
-            WhereClause::Implemented(TraitRef {
-                trait_id: sized_trait,
-                substitution: Substitution::from1(Interner, self_ty.clone()),
+            .filter(move |&self_ty| !explicitly_unsized_tys.contains(self_ty))
+            .map(move |self_ty| {
+                WhereClause::Implemented(TraitRef {
+                    trait_id: sized_trait,
+                    substitution: Substitution::from1(Interner, self_ty.clone()),
+                })
             })
-        })
     })
 }
 
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/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index a90fe83857..44307ffd75 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -49,13 +49,13 @@ use crate::{
 //
 // fn bar() {
 //     {
-//         let word = "안녕하세요";
+//         let word: &str = "안녕하세요";
 //         if !word.is_empty() {
 //             print(word);
 //         }
 //     };
 //     {
-//         let word = "여러분";
+//         let word: &str = "여러분";
 //         if !word.is_empty() {
 //             print(word);
 //         }
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 5890af17eb..80f024184a 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -10,7 +10,7 @@
 use std::{fmt, iter, ops::Not};
 
 use cfg::{CfgAtom, CfgDiff};
-use flycheck::{CargoOptions, FlycheckConfig};
+use flycheck::FlycheckConfig;
 use ide::{
     AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
     HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
@@ -1364,22 +1364,6 @@ impl Config {
         self.data.check_workspace
     }
 
-    pub fn cargo_test_options(&self) -> CargoOptions {
-        CargoOptions {
-            target_triples: self.data.cargo_target.clone().into_iter().collect(),
-            all_targets: false,
-            no_default_features: self.data.cargo_noDefaultFeatures,
-            all_features: matches!(self.data.cargo_features, CargoFeaturesDef::All),
-            features: match self.data.cargo_features.clone() {
-                CargoFeaturesDef::All => vec![],
-                CargoFeaturesDef::Selected(it) => it,
-            },
-            extra_args: self.extra_args().clone(),
-            extra_env: self.extra_env().clone(),
-            target_dir: self.target_dir_from_config(),
-        }
-    }
-
     pub fn flycheck(&self) -> FlycheckConfig {
         match &self.data.check_overrideCommand {
             Some(args) if !args.is_empty() => {
@@ -1405,39 +1389,37 @@ impl Config {
             }
             Some(_) | None => FlycheckConfig::CargoCommand {
                 command: self.data.check_command.clone(),
-                options: CargoOptions {
-                    target_triples: self
-                        .data
-                        .check_targets
-                        .clone()
-                        .and_then(|targets| match &targets.0[..] {
-                            [] => None,
-                            targets => Some(targets.into()),
-                        })
-                        .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()),
-                    all_targets: self.data.check_allTargets.unwrap_or(self.data.cargo_allTargets),
-                    no_default_features: self
-                        .data
-                        .check_noDefaultFeatures
-                        .unwrap_or(self.data.cargo_noDefaultFeatures),
-                    all_features: matches!(
-                        self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features),
-                        CargoFeaturesDef::All
-                    ),
-                    features: match self
-                        .data
-                        .check_features
-                        .clone()
-                        .unwrap_or_else(|| self.data.cargo_features.clone())
-                    {
-                        CargoFeaturesDef::All => vec![],
-                        CargoFeaturesDef::Selected(it) => it,
-                    },
-                    extra_args: self.check_extra_args(),
-                    extra_env: self.check_extra_env(),
-                    target_dir: self.target_dir_from_config(),
+                target_triples: self
+                    .data
+                    .check_targets
+                    .clone()
+                    .and_then(|targets| match &targets.0[..] {
+                        [] => None,
+                        targets => Some(targets.into()),
+                    })
+                    .unwrap_or_else(|| self.data.cargo_target.clone().into_iter().collect()),
+                all_targets: self.data.check_allTargets.unwrap_or(self.data.cargo_allTargets),
+                no_default_features: self
+                    .data
+                    .check_noDefaultFeatures
+                    .unwrap_or(self.data.cargo_noDefaultFeatures),
+                all_features: matches!(
+                    self.data.check_features.as_ref().unwrap_or(&self.data.cargo_features),
+                    CargoFeaturesDef::All
+                ),
+                features: match self
+                    .data
+                    .check_features
+                    .clone()
+                    .unwrap_or_else(|| self.data.cargo_features.clone())
+                {
+                    CargoFeaturesDef::All => vec![],
+                    CargoFeaturesDef::Selected(it) => it,
                 },
+                extra_args: self.check_extra_args(),
+                extra_env: self.check_extra_env(),
                 ansi_color_output: self.color_diagnostic_output(),
+                target_dir: self.target_dir_from_config(),
             },
         }
     }
@@ -2790,7 +2772,7 @@ mod tests {
             .unwrap();
         assert_eq!(config.data.cargo_targetDir, None);
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir.is_none())
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir.is_none())
         );
     }
 
@@ -2809,7 +2791,7 @@ mod tests {
             .unwrap();
         assert_eq!(config.data.cargo_targetDir, Some(TargetDirectory::UseSubdirectory(true)));
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("target/rust-analyzer")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("target/rust-analyzer")))
         );
     }
 
@@ -2831,7 +2813,7 @@ mod tests {
             Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder")))
         );
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("other_folder")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("other_folder")))
         );
     }
 }
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 77c4ad32cc..77692ed3ae 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -220,11 +220,11 @@ pub(crate) fn handle_run_test(
         None => "".to_owned(),
     };
     let handle = if lca.is_empty() {
-        flycheck::CargoTestHandle::new(None, state.config.cargo_test_options())
+        flycheck::CargoTestHandle::new(None)
     } else if let Some((_, path)) = lca.split_once("::") {
-        flycheck::CargoTestHandle::new(Some(path), state.config.cargo_test_options())
+        flycheck::CargoTestHandle::new(Some(path))
     } else {
-        flycheck::CargoTestHandle::new(None, state.config.cargo_test_options())
+        flycheck::CargoTestHandle::new(None)
     };
     state.test_run_session = Some(handle?);
     Ok(())


Test patch:
diff --git a/crates/flycheck/src/test_runner.rs b/crates/flycheck/src/test_runner.rs
index 94c05ebc74..9f761c9ead 100644
--- a/crates/flycheck/src/test_runner.rs
+++ b/crates/flycheck/src/test_runner.rs
@@ -7,10 +7,7 @@ use crossbeam_channel::Receiver;
 use serde::Deserialize;
 use toolchain::Tool;
 
-use crate::{
-    command::{CommandHandle, ParseFromLine},
-    CargoOptions,
-};
+use crate::command::{CommandHandle, ParseFromLine};
 
 #[derive(Debug, Deserialize)]
 #[serde(tag = "event", rename_all = "camelCase")]
@@ -61,14 +58,13 @@ pub struct CargoTestHandle {
 // cargo test --workspace --no-fail-fast -- module::func -Z unstable-options --format=json
 
 impl CargoTestHandle {
-    pub fn new(path: Option<&str>, options: CargoOptions) -> std::io::Result<Self> {
+    pub fn new(path: Option<&str>) -> std::io::Result<Self> {
         let mut cmd = Command::new(Tool::Cargo.path());
         cmd.env("RUSTC_BOOTSTRAP", "1");
         cmd.arg("test");
         cmd.arg("--workspace");
         // --no-fail-fast is needed to ensure that all requested tests will run
         cmd.arg("--no-fail-fast");
-        options.apply_on_command(&mut cmd);
         cmd.arg("--");
         if let Some(path) = path {
             cmd.arg(path);
diff --git a/crates/hir-ty/src/tests/display_source_code.rs b/crates/hir-ty/src/tests/display_source_code.rs
index 5069267499..e4c5d709da 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<'{error}>
 "#,
     );
 }
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 80d5a0ae00..4355881d72 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<'{error}>
 "#,
     );
 }
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 8565b60210..c2d2047e6f 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<'{error}, 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<'{error}, BufWriter>
         "#]],
     );
 }
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index f39404593e..a9d28ebfef 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, '{error}>(&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, '{error}>(&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<'{error}>
 }
 "#,
     );
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index fac850eeaf..dfcd322a39 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1602,7 +1602,7 @@ fn weird_bounds() {
         r#"
 //- minicore: sized
 trait Trait {}
-fn test(
+fn test<'lifetime>(
     a: impl Trait + 'lifetime,
     b: impl 'lifetime,
     c: impl (Trait),
@@ -1612,13 +1612,13 @@ fn test(
 ) {}
 "#,
         expect![[r#"
-            28..29 'a': impl Trait + 'static
-            59..60 'b': impl 'static
-            82..83 'c': impl Trait
-            103..104 'd': impl 'static
-            128..129 'e': impl ?Sized
-            148..149 'f': impl Trait + ?Sized
-            173..175 '{}': ()
+            39..40 'a': impl Trait + 'lifetime
+            70..71 'b': impl 'lifetime
+            93..94 'c': impl Trait
+            114..115 'd': impl 'lifetime
+            139..140 'e': impl ?Sized
+            159..160 'f': impl Trait + ?Sized
+            184..186 '{}': ()
         "#]],
     );
 }
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index a66e199a75..71dae47f5c 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -1820,13 +1820,13 @@ fn print(_: &str) {}
 
 fn bar() {
     {
-        let word = "안녕하세요";
+        let word: &str = "안녕하세요";
         if !word.is_empty() {
             print(word);
         }
     };
     {
-        let word = "여러분";
+        let word: &str = "여러분";
         if !word.is_empty() {
             print(word);
         }
diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs
index 3718dff56e..64a32dee3d 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<'{error}, {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<'{error}, {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..66f1bff7c1 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<'{error}, {unknown}, _>
+            st Foo<…>    Foo<'{error}, {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<'{error}, {unknown}, _>
+            st Foo<…>     Foo<'{error}, {unknown}, _>
             st Record     Record
             st Tuple      Tuple
             st Unit       Unit