Repository: rust-lang/rust-analyzer
Pull request #17108 (2024-04-19 09:08:25)

internal: Cleanup cfg and env handling in project-model
Fixes https://github.com/rust-lang/rust-analyzer/issues/16122#issuecomment-2065794340

`miri` and `debug_assertions` are now enabled via the `cargo.cfgs` config by default, allowing them to be disabled by overwriting the config.


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index da65b034be..0000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Contributing to rust-analyzer
-
-Thank you for your interest in contributing to rust-analyzer! There are many ways to contribute
-and we appreciate all of them.
-
-To get a quick overview of the crates and structure of the project take a look at the
-[./docs/dev](./docs/dev) folder.
-
-If you have any questions please ask them in the [rust-analyzer zulip stream](
-https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer) or if unsure where
-to start out when working on a concrete issue drop a comment on the related issue for mentoring
-instructions (general discussions are recommended to happen on zulip though).
-
-## Fixing a bug or improving a feature
-
-Generally it's fine to just work on these kinds of things and put a pull-request out for it. If there
-is an issue accompanying it make sure to link it in the pull request description so it can be closed
-afterwards or linked for context.
-
-If you want to find something to fix or work on keep a look out for the `C-bug` and `C-enhancement`
-labels.
-
-## Implementing a new feature
-
-It's advised to first open an issue for any kind of new feature so the team can tell upfront whether
-the feature is desirable or not before any implementation work happens. We want to minimize the
-possibility of someone putting a lot of work into a feature that is then going to waste as we deem
-it out of scope (be it due to generally not fitting in with rust-analyzer, or just not having the
-maintenance capacity). If there already is a feature issue open but it is not clear whether it is
-considered accepted feel free to just drop a comment and ask!
diff --git a/README.md b/README.md
index 552f71f151..8c3f6f8468 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,8 @@ https://rust-analyzer.github.io/manual.html#installation
 
 ## Documentation
 
-If you want to **contribute** to rust-analyzer check out the [CONTRIBUTING.md](./CONTRIBUTING.md) or
-if you are just curious about how things work under the hood, check the [./docs/dev](./docs/dev)
-folder.
+If you want to **contribute** to rust-analyzer or are just curious about how
+things work under the hood, check the [./docs/dev](./docs/dev) folder.
 
 If you want to **use** rust-analyzer's language server with your editor of
 choice, check [the manual](https://rust-analyzer.github.io/manual.html) folder.
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index 6a8ab71624..240af7925c 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -295,11 +295,30 @@ pub struct CrateData {
     pub is_proc_macro: bool,
 }
 
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
+#[derive(Default, Clone, PartialEq, Eq)]
 pub struct Env {
     entries: FxHashMap<String, String>,
 }
 
+impl fmt::Debug for Env {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        struct EnvDebug<'s>(Vec<(&'s String, &'s String)>);
+
+        impl fmt::Debug for EnvDebug<'_> {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                f.debug_map().entries(self.0.iter().copied()).finish()
+            }
+        }
+        f.debug_struct("Env")
+            .field("entries", &{
+                let mut entries: Vec<_> = self.entries.iter().collect();
+                entries.sort();
+                EnvDebug(entries)
+            })
+            .finish()
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Dependency {
     pub crate_id: CrateId,
@@ -331,10 +350,11 @@ impl CrateGraph {
         version: Option<String>,
         cfg_options: Arc<CfgOptions>,
         potential_cfg_options: Option<Arc<CfgOptions>>,
-        env: Env,
+        mut env: Env,
         is_proc_macro: bool,
         origin: CrateOrigin,
     ) -> CrateId {
+        env.entries.shrink_to_fit();
         let data = CrateData {
             root_file_id,
             edition,
@@ -651,16 +671,24 @@ impl FromIterator<(String, String)> for Env {
 }
 
 impl Env {
-    pub fn set(&mut self, env: &str, value: String) {
-        self.entries.insert(env.to_owned(), value);
+    pub fn set(&mut self, env: &str, value: impl Into<String>) {
+        self.entries.insert(env.to_owned(), value.into());
     }
 
     pub fn get(&self, env: &str) -> Option<String> {
         self.entries.get(env).cloned()
     }
 
-    pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
-        self.entries.iter().map(|(k, v)| (k.as_str(), v.as_str()))
+    pub fn extend_from_other(&mut self, other: &Env) {
+        self.entries.extend(other.entries.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
+    }
+}
+
+impl From<Env> for Vec<(String, String)> {
+    fn from(env: Env) -> Vec<(String, String)> {
+        let mut entries: Vec<_> = env.entries.into_iter().collect();
+        entries.sort();
+        entries
     }
 }
 
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index 454d6fc538..9a365889e6 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -58,13 +58,6 @@ impl CfgOptions {
         self.enabled.insert(CfgAtom::KeyValue { key, value });
     }
 
-    pub fn difference<'a>(
-        &'a self,
-        other: &'a CfgOptions,
-    ) -> impl Iterator<Item = &'a CfgAtom> + 'a {
-        self.enabled.difference(&other.enabled)
-    }
-
     pub fn apply_diff(&mut self, diff: CfgDiff) {
         for atom in diff.enable {
             self.enabled.insert(atom);
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index d7233a8923..97fa9cf2cc 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -3,7 +3,7 @@
 use base_db::{salsa, CrateId, FileId, SourceDatabase};
 use either::Either;
 use limit::Limit;
-use mbe::{syntax_node_to_token_tree, MatchedArmIndex};
+use mbe::syntax_node_to_token_tree;
 use rustc_hash::FxHashSet;
 use span::{AstIdMap, Span, SyntaxContextData, SyntaxContextId};
 use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
@@ -313,10 +313,9 @@ fn parse_macro_expansion(
     let loc = db.lookup_intern_macro_call(macro_file.macro_call_id);
     let edition = loc.def.edition;
     let expand_to = loc.expand_to();
-    let mbe::ValueResult { value: (tt, matched_arm), err } =
-        macro_expand(db, macro_file.macro_call_id, loc);
+    let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc);
 
-    let (parse, mut rev_token_map) = token_tree_to_syntax_node(
+    let (parse, rev_token_map) = token_tree_to_syntax_node(
         match &tt {
             CowArc::Arc(it) => it,
             CowArc::Owned(it) => it,
@@ -324,7 +323,6 @@ fn parse_macro_expansion(
         expand_to,
         edition,
     );
-    rev_token_map.matched_arm = matched_arm;
 
     ExpandResult { value: (parse, Arc::new(rev_token_map)), err }
 }
@@ -546,13 +544,11 @@ fn macro_expand(
     db: &dyn ExpandDatabase,
     macro_call_id: MacroCallId,
     loc: MacroCallLoc,
-) -> ExpandResult<(CowArc<tt::Subtree>, MatchedArmIndex)> {
+) -> ExpandResult<CowArc<tt::Subtree>> {
     let _p = tracing::span!(tracing::Level::INFO, "macro_expand").entered();
 
-    let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
-        MacroDefKind::ProcMacro(..) => {
-            return db.expand_proc_macro(macro_call_id).map(CowArc::Arc).zip_val(None)
-        }
+    let (ExpandResult { value: tt, err }, span) = match loc.def.kind {
+        MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
         _ => {
             let (macro_arg, undo_info, span) =
                 db.macro_arg_considering_derives(macro_call_id, &loc.kind);
@@ -564,10 +560,10 @@ fn macro_expand(
                         .decl_macro_expander(loc.def.krate, id)
                         .expand(db, arg.clone(), macro_call_id, span),
                     MacroDefKind::BuiltIn(it, _) => {
-                        it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
+                        it.expand(db, macro_call_id, arg, span).map_err(Into::into)
                     }
                     MacroDefKind::BuiltInDerive(it, _) => {
-                        it.expand(db, macro_call_id, arg, span).map_err(Into::into).zip_val(None)
+                        it.expand(db, macro_call_id, arg, span).map_err(Into::into)
                     }
                     MacroDefKind::BuiltInEager(it, _) => {
                         // This might look a bit odd, but we do not expand the inputs to eager macros here.
@@ -578,8 +574,7 @@ fn macro_expand(
                         // As such we just return the input subtree here.
                         let eager = match &loc.kind {
                             MacroCallKind::FnLike { eager: None, .. } => {
-                                return ExpandResult::ok(CowArc::Arc(macro_arg.clone()))
-                                    .zip_val(None);
+                                return ExpandResult::ok(CowArc::Arc(macro_arg.clone()));
                             }
                             MacroCallKind::FnLike { eager: Some(eager), .. } => Some(&**eager),
                             _ => None,
@@ -591,12 +586,12 @@ fn macro_expand(
                             // FIXME: We should report both errors!
                             res.err = error.clone().or(res.err);
                         }
-                        res.zip_val(None)
+                        res
                     }
                     MacroDefKind::BuiltInAttr(it, _) => {
                         let mut res = it.expand(db, macro_call_id, arg, span);
                         fixup::reverse_fixups(&mut res.value, &undo_info);
-                        res.zip_val(None)
+                        res
                     }
                     _ => unreachable!(),
                 };
@@ -608,18 +603,16 @@ fn macro_expand(
     if !loc.def.is_include() {
         // Set a hard limit for the expanded tt
         if let Err(value) = check_tt_count(&tt) {
-            return value
-                .map(|()| {
-                    CowArc::Owned(tt::Subtree {
-                        delimiter: tt::Delimiter::invisible_spanned(span),
-                        token_trees: Box::new([]),
-                    })
+            return value.map(|()| {
+                CowArc::Owned(tt::Subtree {
+                    delimiter: tt::Delimiter::invisible_spanned(span),
+                    token_trees: Box::new([]),
                 })
-                .zip_val(matched_arm);
+            });
         }
     }
 
-    ExpandResult { value: (CowArc::Owned(tt), matched_arm), err }
+    ExpandResult { value: CowArc::Owned(tt), err }
 }
 
 fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index 66465ce600..f9ea8e2ea5 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -3,7 +3,6 @@ use std::sync::OnceLock;
 
 use base_db::{CrateId, VersionReq};
 use span::{Edition, MacroCallId, Span, SyntaxContextId};
-use stdx::TupleExt;
 use syntax::{ast, AstNode};
 use triomphe::Arc;
 
@@ -31,7 +30,7 @@ impl DeclarativeMacroExpander {
         tt: tt::Subtree,
         call_id: MacroCallId,
         span: Span,
-    ) -> ExpandResult<(tt::Subtree, Option<u32>)> {
+    ) -> ExpandResult<tt::Subtree> {
         let loc = db.lookup_intern_macro_call(call_id);
         let toolchain = db.toolchain(loc.def.krate);
         let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
@@ -47,7 +46,7 @@ impl DeclarativeMacroExpander {
         });
         match self.mac.err() {
             Some(_) => ExpandResult::new(
-                (tt::Subtree::empty(tt::DelimSpan { open: span, close: span }), None),
+                tt::Subtree::empty(tt::DelimSpan { open: span, close: span }),
                 ExpandError::MacroDefinition,
             ),
             None => self
@@ -91,7 +90,6 @@ impl DeclarativeMacroExpander {
             None => self
                 .mac
                 .expand(&tt, |_| (), new_meta_vars, call_site, def_site_edition)
-                .map(TupleExt::head)
                 .map_err(Into::into),
         }
     }
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index e792e159ac..e1516fcdcb 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1246,17 +1246,6 @@ impl<'db> SemanticsImpl<'db> {
             .map_or(false, |m| matches!(m.id, MacroId::ProcMacroId(..)))
     }
 
-    pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> {
-        let sa = self.analyze(macro_call.syntax())?;
-        self.db
-            .parse_macro_expansion(
-                sa.expand(self.db, self.wrap_node_infile(macro_call.clone()).as_ref())?,
-            )
-            .value
-            .1
-            .matched_arm
-    }
-
     pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
         let sa = match self.analyze(macro_call.syntax()) {
             Some(it) => it,
diff --git a/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
deleted file mode 100644
index 5459bd334c..0000000000
--- a/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
+++ /dev/null
@@ -1,250 +0,0 @@
-use ide_db::{famous_defs::FamousDefs, traits::resolve_target_trait};
-use itertools::Itertools;
-use syntax::{
-    ast::{self, make, AstNode, HasName},
-    ted,
-};
-
-use crate::{AssistContext, AssistId, AssistKind, Assists};
-
-// Assist: convert_from_to_tryfrom
-//
-// Converts a From impl to a TryFrom impl, wrapping returns in `Ok`.
-//
-// ```
-// # //- minicore: from
-// impl $0From<usize> for Thing {
-//     fn from(val: usize) -> Self {
-//         Thing {
-//             b: val.to_string(),
-//             a: val
-//         }
-//     }
-// }
-// ```
-// ->
-// ```
-// impl TryFrom<usize> for Thing {
-//     type Error = ${0:()};
-//
-//     fn try_from(val: usize) -> Result<Self, Self::Error> {
-//         Ok(Thing {
-//             b: val.to_string(),
-//             a: val
-//         })
-//     }
-// }
-// ```
-pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let impl_ = ctx.find_node_at_offset::<ast::Impl>()?;
-    let trait_ty = impl_.trait_()?;
-
-    let module = ctx.sema.scope(impl_.syntax())?.module();
-
-    let from_type = match &trait_ty {
-        ast::Type::PathType(path) => {
-            path.path()?.segment()?.generic_arg_list()?.generic_args().next()?
-        }
-        _ => return None,
-    };
-
-    let associated_items = impl_.assoc_item_list()?;
-    let from_fn = associated_items.assoc_items().find_map(|item| {
-        if let ast::AssocItem::Fn(f) = item {
-            if f.name()?.text() == "from" {
-                return Some(f);
-            }
-        };
-        None
-    })?;
-
-    let from_fn_name = from_fn.name()?;
-    let from_fn_return_type = from_fn.ret_type()?.ty()?;
-
-    let return_exprs = from_fn.body()?.syntax().descendants().filter_map(ast::ReturnExpr::cast);
-    let tail_expr = from_fn.body()?.tail_expr()?;
-
-    if resolve_target_trait(&ctx.sema, &impl_)?
-        != FamousDefs(&ctx.sema, module.krate()).core_convert_From()?
-    {
-        return None;
-    }
-
-    acc.add(
-        AssistId("convert_from_to_tryfrom", AssistKind::RefactorRewrite),
-        "Convert From to TryFrom",
-        impl_.syntax().text_range(),
-        |builder| {
-            let trait_ty = builder.make_mut(trait_ty);
-            let from_fn_return_type = builder.make_mut(from_fn_return_type);
-            let from_fn_name = builder.make_mut(from_fn_name);
-            let tail_expr = builder.make_mut(tail_expr);
-            let return_exprs = return_exprs.map(|r| builder.make_mut(r)).collect_vec();
-            let associated_items = builder.make_mut(associated_items).clone();
-
-            ted::replace(
-                trait_ty.syntax(),
-                make::ty(&format!("TryFrom<{from_type}>")).syntax().clone_for_update(),
-            );
-            ted::replace(
-                from_fn_return_type.syntax(),
-                make::ty("Result<Self, Self::Error>").syntax().clone_for_update(),
-            );
-            ted::replace(from_fn_name.syntax(), make::name("try_from").syntax().clone_for_update());
-            ted::replace(
-                tail_expr.syntax(),
-                wrap_ok(tail_expr.clone()).syntax().clone_for_update(),
-            );
-
-            for r in return_exprs {
-                let t = r.expr().unwrap_or_else(make::expr_unit);
-                ted::replace(t.syntax(), wrap_ok(t.clone()).syntax().clone_for_update());
-            }
-
-            let error_type = ast::AssocItem::TypeAlias(make::ty_alias(
-                "Error",
-                None,
-                None,
-                None,
-                Some((make::ty_unit(), None)),
-            ))
-            .clone_for_update();
-
-            if let Some(cap) = ctx.config.snippet_cap {
-                if let ast::AssocItem::TypeAlias(type_alias) = &error_type {
-                    if let Some(ty) = type_alias.ty() {
-                        builder.add_placeholder_snippet(cap, ty);
-                    }
-                }
-            }
-
-            associated_items.add_item_at_start(error_type);
-        },
-    )
-}
-
-fn wrap_ok(expr: ast::Expr) -> ast::Expr {
-    make::expr_call(
-        make::expr_path(make::ext::ident_path("Ok")),
-        make::arg_list(std::iter::once(expr)),
-    )
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
-    #[test]
-    fn converts_from_to_tryfrom() {
-        check_assist(
-            convert_from_to_tryfrom,
-            r#"
-//- minicore: from
-struct Foo(String);
-
-impl $0From<String> for Foo {
-    fn from(val: String) -> Self {
-        if val == "bar" {
-            return Foo(val);
-        }
-        Self(val)
-    }
-}
-            "#,
-            r#"
-struct Foo(String);
-
-impl TryFrom<String> for Foo {
-    type Error = ${0:()};
-
-    fn try_from(val: String) -> Result<Self, Self::Error> {
-        if val == "bar" {
-            return Ok(Foo(val));
-        }
-        Ok(Self(val))
-    }
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn converts_from_to_tryfrom_nested_type() {
-        check_assist(
-            convert_from_to_tryfrom,
-            r#"
-//- minicore: from
-struct Foo(String);
-
-impl $0From<Option<String>> for Foo {
-    fn from(val: Option<String>) -> Self {
-        match val {
-            Some(val) => Foo(val),
-            None => Foo("".to_string())
-        }
-    }
-}
-            "#,
-            r#"
-struct Foo(String);
-
-impl TryFrom<Option<String>> for Foo {
-    type Error = ${0:()};
-
-    fn try_from(val: Option<String>) -> Result<Self, Self::Error> {
-        Ok(match val {
-            Some(val) => Foo(val),
-            None => Foo("".to_string())
-        })
-    }
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn converts_from_to_tryfrom_preserves_lifetimes() {
-        check_assist(
-            convert_from_to_tryfrom,
-            r#"
-//- minicore: from
-struct Foo<'a>(&'a str);
-
-impl<'a> $0From<&'a str> for Foo<'a> {
-    fn from(val: &'a str) -> Self {
-        Self(val)
-    }
-}
-            "#,
-            r#"
-struct Foo<'a>(&'a str);
-
-impl<'a> TryFrom<&'a str> for Foo<'a> {
-    type Error = ${0:()};
-
-    fn try_from(val: &'a str) -> Result<Self, Self::Error> {
-        Ok(Self(val))
-    }
-}
-            "#,
-        );
-    }
-
-    #[test]
-    fn other_trait_not_applicable() {
-        check_assist_not_applicable(
-            convert_from_to_tryfrom,
-            r#"
-struct Foo(String);
-
-impl $0TryFrom<String> for Foo {
-    fn try_from(val: String) -> Result<Self, Self::Error> {
-        Ok(Self(val))
-    }
-}
-            "#,
-        );
-    }
-}
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 0df5e913a5..024448ef1e 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -116,7 +116,6 @@ mod handlers {
     mod change_visibility;
     mod convert_bool_then;
     mod convert_comment_block;
-    mod convert_from_to_tryfrom;
     mod convert_integer_literal;
     mod convert_into_to_from;
     mod convert_iter_for_each_to_for;
@@ -239,7 +238,6 @@ mod handlers {
             convert_bool_then::convert_bool_then_to_if,
             convert_bool_then::convert_if_to_bool_then,
             convert_comment_block::convert_comment_block,
-            convert_from_to_tryfrom::convert_from_to_tryfrom,
             convert_integer_literal::convert_integer_literal,
             convert_into_to_from::convert_into_to_from,
             convert_iter_for_each_to_for::convert_iter_for_each_to_for,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 95de3c88c8..822751c0e4 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -14,7 +14,7 @@ use ide_db::{
     helpers::pick_best_token,
     FxIndexSet, RootDatabase,
 };
-use itertools::{multizip, Itertools};
+use itertools::Itertools;
 use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxNode, T};
 
 use crate::{
@@ -149,7 +149,7 @@ fn hover_simple(
     if let Some(doc_comment) = token_as_doc_comment(&original_token) {
         cov_mark::hit!(no_highlight_on_comment_hover);
         return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
-            let res = hover_for_definition(sema, file_id, def, &node, None, config);
+            let res = hover_for_definition(sema, file_id, def, &node, config);
             Some(RangeInfo::new(range, res))
         });
     }
@@ -162,7 +162,6 @@ fn hover_simple(
             file_id,
             Definition::from(resolution?),
             &original_token.parent()?,
-            None,
             config,
         );
         return Some(RangeInfo::new(range, res));
@@ -197,29 +196,6 @@ fn hover_simple(
             descended()
                 .filter_map(|token| {
                     let node = token.parent()?;
-
-                    // special case macro calls, we wanna render the invoked arm index
-                    if let Some(name) = ast::NameRef::cast(node.clone()) {
-                        if let Some(path_seg) =
-                            name.syntax().parent().and_then(ast::PathSegment::cast)
-                        {
-                            if let Some(macro_call) = path_seg
-                                .parent_path()
-                                .syntax()
-                                .parent()
-                                .and_then(ast::MacroCall::cast)
-                            {
-                                if let Some(macro_) = sema.resolve_macro_call(&macro_call) {
-                                    return Some(vec![(
-                                        Definition::Macro(macro_),
-                                        sema.resolve_macro_call_arm(&macro_call),
-                                        node,
-                                    )]);
-                                }
-                            }
-                        }
-                    }
-
                     match IdentClass::classify_node(sema, &node)? {
                         // It's better for us to fall back to the keyword hover here,
                         // rendering poll is very confusing
@@ -228,19 +204,20 @@ fn hover_simple(
                         IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand {
                             decl,
                             ..
-                        }) => Some(vec![(Definition::ExternCrateDecl(decl), None, node)]),
+                        }) => Some(vec![(Definition::ExternCrateDecl(decl), node)]),
 
                         class => Some(
-                            multizip((class.definitions(), iter::repeat(None), iter::repeat(node)))
+                            class
+                                .definitions()
+                                .into_iter()
+                                .zip(iter::repeat(node))
                                 .collect::<Vec<_>>(),
                         ),
                     }
                 })
                 .flatten()
-                .unique_by(|&(def, _, _)| def)
-                .map(|(def, macro_arm, node)| {
-                    hover_for_definition(sema, file_id, def, &node, macro_arm, config)
-                })
+                .unique_by(|&(def, _)| def)
+                .map(|(def, node)| hover_for_definition(sema, file_id, def, &node, config))
                 .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
                     acc.actions.extend(actions);
                     acc.markup = Markup::from(format!("{}\n---\n{markup}", acc.markup));
@@ -397,7 +374,6 @@ pub(crate) fn hover_for_definition(
     file_id: FileId,
     def: Definition,
     scope_node: &SyntaxNode,
-    macro_arm: Option<u32>,
     config: &HoverConfig,
 ) -> HoverResult {
     let famous_defs = match &def {
@@ -422,8 +398,7 @@ pub(crate) fn hover_for_definition(
     };
     let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
 
-    let markup =
-        render::definition(sema.db, def, famous_defs.as_ref(), &notable_traits, macro_arm, config);
+    let markup = render::definition(sema.db, def, famous_defs.as_ref(), &notable_traits, config);
     HoverResult {
         markup: render::process_markup(sema.db, def, &markup, config),
         actions: [
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 3f0fc85134..7579d4d6d8 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -403,7 +403,6 @@ pub(super) fn definition(
     def: Definition,
     famous_defs: Option<&FamousDefs<'_, '_>>,
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
-    macro_arm: Option<u32>,
     config: &HoverConfig,
 ) -> Markup {
     let mod_path = definition_mod_path(db, &def);
@@ -414,13 +413,6 @@ pub(super) fn definition(
         Definition::Adt(Adt::Struct(struct_)) => {
             struct_.display_limited(db, config.max_struct_field_count).to_string()
         }
-        Definition::Macro(it) => {
-            let mut label = it.display(db).to_string();
-            if let Some(macro_arm) = macro_arm {
-                format_to!(label, " // matched arm #{}", macro_arm);
-            }
-            label
-        }
         _ => def.label(db),
     };
     let docs = def.docs(db, famous_defs);
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index ca013da709..3fef16df25 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -188,14 +188,7 @@ impl StaticIndex<'_> {
             } else {
                 let it = self.tokens.insert(TokenStaticData {
                     documentation: documentation_for_definition(&sema, def, &node),
-                    hover: Some(hover_for_definition(
-                        &sema,
-                        file_id,
-                        def,
-                        &node,
-                        None,
-                        &hover_config,
-                    )),
+                    hover: Some(hover_for_definition(&sema, file_id, def, &node, &hover_config)),
                     definition: def.try_to_nav(self.db).map(UpmappingResult::call_site).map(|it| {
                         FileRange { file_id: it.file_id, range: it.focus_or_full_range() }
                     }),
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 79d6fe36b5..ec37d88e60 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -407,8 +407,7 @@ impl ProcMacroExpander for Expander {
         call_site: Span,
         mixed_site: Span,
     ) -> Result<tt::Subtree<Span>, ProcMacroExpansionError> {
-        let env = env.iter().map(|(k, v)| (k.to_owned(), v.to_owned())).collect();
-        match self.0.expand(subtree, attrs, env, def_site, call_site, mixed_site) {
+        match self.0.expand(subtree, attrs, env.clone(), def_site, call_site, mixed_site) {
             Ok(Ok(subtree)) => Ok(subtree),
             Ok(Err(err)) => Err(ProcMacroExpansionError::Panic(err.0)),
             Err(err) => Err(ProcMacroExpansionError::System(err.to_string())),
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs
index f4bbaef7af..1dca288017 100644
--- a/crates/mbe/src/benchmark.rs
+++ b/crates/mbe/src/benchmark.rs
@@ -48,7 +48,7 @@ fn benchmark_expand_macro_rules() {
             .map(|(id, tt)| {
                 let res = rules[&id].expand(&tt, |_| (), true, DUMMY, Edition::CURRENT);
                 assert!(res.err.is_none());
-                res.value.0.token_trees.len()
+                res.value.token_trees.len()
             })
             .sum()
     };
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs
index cfad8bcc0b..2d495da0db 100644
--- a/crates/mbe/src/expander.rs
+++ b/crates/mbe/src/expander.rs
@@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
 use span::{Edition, Span};
 use syntax::SmolStr;
 
-use crate::{parser::MetaVarKind, ExpandError, ExpandResult, MatchedArmIndex};
+use crate::{parser::MetaVarKind, ExpandError, ExpandResult};
 
 pub(crate) fn expand_rules(
     rules: &[crate::Rule],
@@ -18,9 +18,9 @@ pub(crate) fn expand_rules(
     new_meta_vars: bool,
     call_site: Span,
     def_site_edition: Edition,
-) -> ExpandResult<(tt::Subtree<Span>, MatchedArmIndex)> {
-    let mut match_: Option<(matcher::Match, &crate::Rule, usize)> = None;
-    for (idx, rule) in rules.iter().enumerate() {
+) -> ExpandResult<tt::Subtree<Span>> {
+    let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
+    for rule in rules {
         let new_match = matcher::match_(&rule.lhs, input, def_site_edition);
 
         if new_match.err.is_none() {
@@ -35,34 +35,31 @@ pub(crate) fn expand_rules(
                 call_site,
             );
             if transcribe_err.is_none() {
-                return ExpandResult::ok((value, Some(idx as u32)));
+                return ExpandResult::ok(value);
             }
         }
         // Use the rule if we matched more tokens, or bound variables count
-        if let Some((prev_match, _, _)) = &match_ {
+        if let Some((prev_match, _)) = &match_ {
             if (new_match.unmatched_tts, -(new_match.bound_count as i32))
                 < (prev_match.unmatched_tts, -(prev_match.bound_count as i32))
             {
-                match_ = Some((new_match, rule, idx));
+                match_ = Some((new_match, rule));
             }
         } else {
-            match_ = Some((new_match, rule, idx));
+            match_ = Some((new_match, rule));
         }
     }
-    if let Some((match_, rule, idx)) = match_ {
+    if let Some((match_, rule)) = match_ {
         // if we got here, there was no match without errors
         let ExpandResult { value, err: transcribe_err } =
             transcriber::transcribe(&rule.rhs, &match_.bindings, marker, new_meta_vars, call_site);
-        ExpandResult { value: (value, idx.try_into().ok()), err: match_.err.or(transcribe_err) }
+        ExpandResult { value, err: match_.err.or(transcribe_err) }
     } else {
         ExpandResult::new(
-            (
-                tt::Subtree {
-                    delimiter: tt::Delimiter::invisible_spanned(call_site),
-                    token_trees: Box::default(),
-                },
-                None,
-            ),
+            tt::Subtree {
+                delimiter: tt::Delimiter::invisible_spanned(call_site),
+                token_trees: Box::new([]),
+            },
             ExpandError::NoMatchingRule,
         )
     }
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index d5de56312a..5445f8790f 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -122,9 +122,6 @@ impl fmt::Display for CountError {
     }
 }
 
-/// Index of the matched macro arm on successful expansion.
-pub type MatchedArmIndex = Option<u32>;
-
 /// This struct contains AST for a single `macro_rules` definition. What might
 /// be very confusing is that AST has almost exactly the same shape as
 /// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
@@ -254,7 +251,7 @@ impl DeclarativeMacro {
         new_meta_vars: bool,
         call_site: Span,
         def_site_edition: Edition,
-    ) -> ExpandResult<(tt::Subtree<Span>, MatchedArmIndex)> {
+    ) -> ExpandResult<tt::Subtree<Span>> {
         expander::expand_rules(&self.rules, tt, marker, new_meta_vars, call_site, def_site_edition)
     }
 }
@@ -333,10 +330,6 @@ impl<T, E> ValueResult<T, E> {
         Self { value: Default::default(), err: Some(err) }
     }
 
-    pub fn zip_val<U>(self, other: U) -> ValueResult<(T, U), E> {
-        ValueResult { value: (self.value, other), err: self.err }
-    }
-
     pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ValueResult<U, E> {
         ValueResult { value: f(self.value), err: self.err }
     }
diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs
index 3c0c904bab..0ab16c38c8 100644
--- a/crates/proc-macro-api/src/lib.rs
+++ b/crates/proc-macro-api/src/lib.rs
@@ -11,6 +11,7 @@ pub mod msg;
 mod process;
 mod version;
 
+use base_db::Env;
 use indexmap::IndexSet;
 use paths::AbsPathBuf;
 use rustc_hash::FxHashMap;
@@ -152,16 +153,13 @@ impl ProcMacro {
         &self,
         subtree: &tt::Subtree<Span>,
         attr: Option<&tt::Subtree<Span>>,
-        env: Vec<(String, String)>,
+        env: Env,
         def_site: Span,
         call_site: Span,
         mixed_site: Span,
     ) -> Result<Result<tt::Subtree<Span>, PanicMessage>, ServerError> {
         let version = self.process.lock().unwrap_or_else(|e| e.into_inner()).version();
-        let current_dir = env
-            .iter()
-            .find(|(name, _)| name == "CARGO_MANIFEST_DIR")
-            .map(|(_, value)| value.clone());
+        let current_dir = env.get("CARGO_MANIFEST_DIR");
 
         let mut span_data_table = IndexSet::default();
         let def_site = span_data_table.insert_full(def_site).0;
@@ -172,7 +170,7 @@ impl ProcMacro {
             macro_name: self.name.to_string(),
             attributes: attr.map(|subtree| FlatTree::new(subtree, version, &mut span_data_table)),
             lib: self.dylib_path.to_path_buf().into(),
-            env,
+            env: env.into(),
             current_dir,
             has_global_spans: ExpnGlobals {
                 serialize: version >= HAS_GLOBAL_SPANS,
diff --git a/crates/proc-macro-srv-cli/build.rs b/crates/proc-macro-srv-cli/build.rs
deleted file mode 100644
index 07f914fece..0000000000
--- a/crates/proc-macro-srv-cli/build.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//! This teaches cargo about our cfg(rust_analyzer)
-
-fn main() {
-    println!("cargo:rustc-check-cfg=cfg(rust_analyzer)");
-}
diff --git a/crates/proc-macro-srv/build.rs b/crates/proc-macro-srv/build.rs
index 874d1c6cd3..a8c732f315 100644
--- a/crates/proc-macro-srv/build.rs
+++ b/crates/proc-macro-srv/build.rs
@@ -4,8 +4,6 @@
 use std::{env, fs::File, io::Write, path::PathBuf, process::Command};
 
 fn main() {
-    println!("cargo:rustc-check-cfg=cfg(rust_analyzer)");
-
     let mut path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
     path.push("rustc_version.rs");
     let mut f = File::create(&path).unwrap();
diff --git a/crates/project-model/src/build_scripts.rs b/crates/project-model/src/build_scripts.rs
index 26f8f52bbc..fbd423c9ea 100644
--- a/crates/project-model/src/build_scripts.rs
+++ b/crates/project-model/src/build_scripts.rs
@@ -23,16 +23,18 @@ use serde::Deserialize;
 use toolchain::Tool;
 
 use crate::{
-    cfg_flag::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
+    cfg::CfgFlag, utf8_stdout, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
     InvocationStrategy, Package, Sysroot, TargetKind,
 };
 
+/// Output of the build script and proc-macro building steps for a workspace.
 #[derive(Debug, Default, Clone, PartialEq, Eq)]
 pub struct WorkspaceBuildScripts {
     outputs: ArenaMap<Package, BuildScriptOutput>,
     error: Option<String>,
 }
 
+/// Output of the build script and proc-macro building step for a concrete package.
 #[derive(Debug, Clone, Default, PartialEq, Eq)]
 pub(crate) struct BuildScriptOutput {
     /// List of config flags defined by this package's build script.
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs
index 82fee7112f..fd898ffa5c 100644
--- a/crates/project-model/src/cargo_workspace.rs
+++ b/crates/project-model/src/cargo_workspace.rs
@@ -135,6 +135,20 @@ pub struct PackageData {
     pub active_features: Vec<String>,
     /// String representation of package id
     pub id: String,
+    /// Authors as given in the `Cargo.toml`
+    pub authors: Vec<String>,
+    /// Description as given in the `Cargo.toml`
+    pub description: Option<String>,
+    /// Homepage as given in the `Cargo.toml`
+    pub homepage: Option<String>,
+    /// License as given in the `Cargo.toml`
+    pub license: Option<String>,
+    /// License file as given in the `Cargo.toml`
+    pub license_file: Option<Utf8PathBuf>,
+    /// Readme file as given in the `Cargo.toml`
+    pub readme: Option<Utf8PathBuf>,
+    /// Rust version as given in the `Cargo.toml`
+    pub rust_version: Option<semver::Version>,
     /// The contents of [package.metadata.rust-analyzer]
     pub metadata: RustAnalyzerPackageMetaData,
 }
@@ -225,6 +239,10 @@ impl TargetKind {
         }
         TargetKind::Other
     }
+
+    pub fn is_executable(self) -> bool {
+        matches!(self, TargetKind::Bin | TargetKind::Example)
+    }
 }
 
 // Deserialize helper for the cargo metadata
@@ -330,6 +348,13 @@ impl CargoWorkspace {
                 repository,
                 edition,
                 metadata,
+                authors,
+                description,
+                homepage,
+                license,
+                license_file,
+                readme,
+                rust_version,
                 ..
             } = meta_pkg;
             let meta = from_value::<PackageMetadata>(metadata).unwrap_or_default();
@@ -358,6 +383,13 @@ impl CargoWorkspace {
                 is_member,
                 edition,
                 repository,
+                authors,
+                description,
+                homepage,
+                license,
+                license_file,
+                readme,
+                rust_version,
                 dependencies: Vec::new(),
                 features: features.into_iter().collect(),
                 active_features: Vec::new(),
diff --git a/crates/project-model/src/cfg_flag.rs b/crates/project-model/src/cfg.rs
similarity index 72%
rename from crates/project-model/src/cfg_flag.rs
rename to crates/project-model/src/cfg.rs
index 6192e18da0..b409bc1ce7 100644
--- a/crates/project-model/src/cfg_flag.rs
+++ b/crates/project-model/src/cfg.rs
@@ -3,7 +3,8 @@
 //! rustc main.rs --cfg foo --cfg 'feature="bar"'
 use std::{fmt, str::FromStr};
 
-use cfg::CfgOptions;
+use cfg::{CfgDiff, CfgOptions};
+use rustc_hash::FxHashMap;
 use serde::Serialize;
 
 #[derive(Clone, Eq, PartialEq, Debug, Serialize)]
@@ -70,3 +71,27 @@ impl fmt::Display for CfgFlag {
         }
     }
 }
+
+/// A set of cfg-overrides per crate.
+#[derive(Default, Debug, Clone, Eq, PartialEq)]
+pub struct CfgOverrides {
+    /// A global set of overrides matching all crates.
+    pub global: CfgDiff,
+    /// A set of overrides matching specific crates.
+    pub selective: FxHashMap<String, CfgDiff>,
+}
+
+impl CfgOverrides {
+    pub fn len(&self) -> usize {
+        self.global.len() + self.selective.values().map(|it| it.len()).sum::<usize>()
+    }
+
+    pub fn apply(&self, cfg_options: &mut CfgOptions, name: &str) {
+        if !self.global.is_empty() {
+            cfg_options.apply_diff(self.global.clone());
+        };
+        if let Some(diff) = self.selective.get(name) {
+            cfg_options.apply_diff(diff.clone());
+        };
+    }
+}
diff --git a/crates/project-model/src/env.rs b/crates/project-model/src/env.rs
new file mode 100644
index 0000000000..762e01c917
--- /dev/null
+++ b/crates/project-model/src/env.rs
@@ -0,0 +1,85 @@
+//! Cargo-like environment variables injection.
+use base_db::Env;
+use rustc_hash::FxHashMap;
+use toolchain::Tool;
+
+use crate::{utf8_stdout, ManifestPath, PackageData, Sysroot, TargetKind};
+
+/// Recreates the compile-time environment variables that Cargo sets.
+///
+/// Should be synced with
+/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
+///
+/// FIXME: ask Cargo to provide this data instead of re-deriving.
+pub(crate) fn inject_cargo_package_env(env: &mut Env, package: &PackageData) {
+    // FIXME: Missing variables:
+    // CARGO_BIN_NAME, CARGO_BIN_EXE_<name>
+
+    let manifest_dir = package.manifest.parent();
+    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str());
+
+    env.set("CARGO_PKG_VERSION", package.version.to_string());
+    env.set("CARGO_PKG_VERSION_MAJOR", package.version.major.to_string());
+    env.set("CARGO_PKG_VERSION_MINOR", package.version.minor.to_string());
+    env.set("CARGO_PKG_VERSION_PATCH", package.version.patch.to_string());
+    env.set("CARGO_PKG_VERSION_PRE", package.version.pre.to_string());
+
+    env.set("CARGO_PKG_AUTHORS", package.authors.join(":").clone());
+
+    env.set("CARGO_PKG_NAME", package.name.clone());
+    env.set("CARGO_PKG_DESCRIPTION", package.description.as_deref().unwrap_or_default());
+    env.set("CARGO_PKG_HOMEPAGE", package.homepage.as_deref().unwrap_or_default());
+    env.set("CARGO_PKG_REPOSITORY", package.repository.as_deref().unwrap_or_default());
+    env.set("CARGO_PKG_LICENSE", package.license.as_deref().unwrap_or_default());
+    env.set(
+        "CARGO_PKG_LICENSE_FILE",
+        package.license_file.as_ref().map(ToString::to_string).unwrap_or_default(),
+    );
+    env.set(
+        "CARGO_PKG_README",
+        package.readme.as_ref().map(ToString::to_string).unwrap_or_default(),
+    );
+
+    env.set(
+        "CARGO_PKG_RUST_VERSION",
+        package.rust_version.as_ref().map(ToString::to_string).unwrap_or_default(),
+    );
+}
+
+pub(crate) fn inject_cargo_env(env: &mut Env) {
+    env.set("CARGO", Tool::Cargo.path().to_string());
+}
+
+pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: TargetKind) {
+    _ = kind;
+    // FIXME
+    // if kind.is_executable() {
+    //     env.set("CARGO_BIN_NAME", cargo_name);
+    // }
+    env.set("CARGO_CRATE_NAME", cargo_name.replace('-', "_"));
+}
+
+pub(crate) fn cargo_config_env(
+    cargo_toml: &ManifestPath,
+    extra_env: &FxHashMap<String, String>,
+    sysroot: Option<&Sysroot>,
+) -> FxHashMap<String, String> {
+    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
+    cargo_config.envs(extra_env);
+    cargo_config
+        .current_dir(cargo_toml.parent())
+        .args(["-Z", "unstable-options", "config", "get", "env"])
+        .env("RUSTC_BOOTSTRAP", "1");
+    // if successful we receive `env.key.value = "value" per entry
+    tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
+    utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
+}
+
+fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
+    stdout
+        .lines()
+        .filter_map(|l| l.strip_prefix("env."))
+        .filter_map(|l| l.split_once(".value = "))
+        .map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
+        .collect()
+}
diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs
index 28696aa327..7f3e35ca5d 100644
--- a/crates/project-model/src/lib.rs
+++ b/crates/project-model/src/lib.rs
@@ -19,7 +19,8 @@
 
 mod build_scripts;
 mod cargo_workspace;
-mod cfg_flag;
+mod cfg;
+mod env;
 mod manifest_path;
 mod project_json;
 mod rustc_cfg;
@@ -47,10 +48,11 @@ pub use crate::{
         CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency,
         RustLibSource, Target, TargetData, TargetKind,
     },
+    cfg::CfgOverrides,
     manifest_path::ManifestPath,
     project_json::{ProjectJson, ProjectJsonData},
     sysroot::Sysroot,
-    workspace::{CfgOverrides, PackageRoot, ProjectWorkspace},
+    workspace::{FileLoader, PackageRoot, ProjectWorkspace},
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index a8e30d2267..fac6eb8ad3 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -55,7 +55,7 @@ use rustc_hash::FxHashMap;
 use serde::{de, Deserialize, Serialize};
 use span::Edition;
 
-use crate::cfg_flag::CfgFlag;
+use crate::cfg::CfgFlag;
 
 /// Roots and crates that compose this Rust project.
 #[derive(Clone, Debug, Eq, PartialEq)]
diff --git a/crates/project-model/src/rustc_cfg.rs b/crates/project-model/src/rustc_cfg.rs
index 501b1fdc8c..4f69b2b96f 100644
--- a/crates/project-model/src/rustc_cfg.rs
+++ b/crates/project-model/src/rustc_cfg.rs
@@ -4,7 +4,7 @@ use anyhow::Context;
 use rustc_hash::FxHashMap;
 use toolchain::Tool;
 
-use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
+use crate::{cfg::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
 
 /// Determines how `rustc --print cfg` is discovered and invoked.
 pub(crate) enum RustcCfgConfig<'a> {
@@ -32,9 +32,6 @@ pub(crate) fn get(
         }
     }
 
-    // Add miri cfg, which is useful for mir eval in stdlib
-    res.push(CfgFlag::Atom("miri".into()));
-
     let rustc_cfgs = get_rust_cfgs(target, extra_env, config);
 
     let rustc_cfgs = match rustc_cfgs {
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 6a063905ca..a5e74763d7 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -2,7 +2,7 @@
 //! metadata` or `rust-project.json`) into representation stored in the salsa
 //! database -- `CrateGraph`.
 
-use std::{collections::VecDeque, fmt, fs, iter, str::FromStr, sync};
+use std::{collections::VecDeque, fmt, fs, iter, sync};
 
 use anyhow::{format_err, Context};
 use base_db::{
@@ -21,7 +21,8 @@ use triomphe::Arc;
 use crate::{
     build_scripts::BuildScriptOutput,
     cargo_workspace::{DepKind, PackageData, RustLibSource},
-    cfg_flag::CfgFlag,
+    cfg::{CfgFlag, CfgOverrides},
+    env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
     project_json::{Crate, CrateArrayIdx},
     rustc_cfg::{self, RustcCfgConfig},
     sysroot::{SysrootCrate, SysrootMode},
@@ -30,29 +31,7 @@ use crate::{
     ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
 };
 
-/// A set of cfg-overrides per crate.
-#[derive(Default, Debug, Clone, Eq, PartialEq)]
-pub struct CfgOverrides {
-    /// A global set of overrides matching all crates.
-    pub global: CfgDiff,
-    /// A set of overrides matching specific crates.
-    pub selective: FxHashMap<String, CfgDiff>,
-}
-
-impl CfgOverrides {
-    pub fn len(&self) -> usize {
-        self.global.len() + self.selective.values().map(|it| it.len()).sum::<usize>()
-    }
-
-    fn apply(&self, cfg_options: &mut CfgOptions, name: &str) {
-        if !self.global.is_empty() {
-            cfg_options.apply_diff(self.global.clone());
-        };
-        if let Some(diff) = self.selective.get(name) {
-            cfg_options.apply_diff(diff.clone());
-        };
-    }
-}
+pub type FileLoader<'a> = &'a mut dyn for<'b> FnMut(&'b AbsPath) -> Option<FileId>;
 
 /// `PackageRoot` describes a package root folder.
 /// Which may be an external dependency, or a member of
@@ -69,30 +48,46 @@ pub struct PackageRoot {
 pub enum ProjectWorkspace {
     /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
     Cargo {
+        /// The workspace as returned by `cargo metadata`.
         cargo: CargoWorkspace,
+        /// The build script results for the workspace.
         build_scripts: WorkspaceBuildScripts,
+        /// The sysroot loaded for this workspace.
         sysroot: Result<Sysroot, Option<String>>,
+        /// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been
+        /// disabled or was otherwise not requested.
         rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
         /// Holds cfg flags for the current target. We get those by running
         /// `rustc --print cfg`.
-        ///
-        /// FIXME: make this a per-crate map, as, eg, build.rs might have a
-        /// different target.
+        // FIXME: make this a per-crate map, as, eg, build.rs might have a
+        // different target.
         rustc_cfg: Vec<CfgFlag>,
+        /// A set of cfg overrides for this workspace.
         cfg_overrides: CfgOverrides,
+        /// The toolchain version used by this workspace.
         toolchain: Option<Version>,
+        /// The target data layout queried for workspace.
         target_layout: TargetLayoutLoadResult,
+        /// Environment variables set in the `.cargo/config` file.
         cargo_config_extra_env: FxHashMap<String, String>,
     },
     /// Project workspace was manually specified using a `rust-project.json` file.
     Json {
+        /// The loaded project json file.
         project: ProjectJson,
+        /// The sysroot loaded for this workspace.
         sysroot: Result<Sysroot, Option<String>>,
         /// Holds cfg flags for the current target. We get those by running
         /// `rustc --print cfg`.
+        // FIXME: make this a per-crate map, as, eg, build.rs might have a
+        // different target.
         rustc_cfg: Vec<CfgFlag>,
+        /// The toolchain version used by this workspace.
         toolchain: Option<Version>,
+        /// The target data layout queried for workspace.
         target_layout: TargetLayoutLoadResult,
+        /// A set of cfg overrides for this workspace.
+        cfg_overrides: CfgOverrides,
     },
     // FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning.
     // That's not the end user experience we should strive for.
@@ -105,13 +100,21 @@ pub enum ProjectWorkspace {
     /// Project with a set of disjoint files, not belonging to any particular workspace.
     /// Backed by basic sysroot crates for basic completion and highlighting.
     DetachedFiles {
+        /// The set of detached files.
         files: Vec<AbsPathBuf>,
+        /// The sysroot loaded for this workspace.
         sysroot: Result<Sysroot, Option<String>>,
         /// Holds cfg flags for the current target. We get those by running
         /// `rustc --print cfg`.
+        // FIXME: make this a per-crate map, as, eg, build.rs might have a
+        // different target.
         rustc_cfg: Vec<CfgFlag>,
+        /// The toolchain version used by this workspace.
         toolchain: Option<Version>,
+        /// The target data layout queried for workspace.
         target_layout: TargetLayoutLoadResult,
+        /// A set of cfg overrides for the files.
+        cfg_overrides: CfgOverrides,
     },
 }
 
@@ -150,6 +153,7 @@ impl fmt::Debug for ProjectWorkspace {
                 rustc_cfg,
                 toolchain,
                 target_layout: data_layout,
+                cfg_overrides,
             } => {
                 let mut debug_struct = f.debug_struct("Json");
                 debug_struct.field("n_crates", &project.n_crates());
@@ -159,7 +163,8 @@ impl fmt::Debug for ProjectWorkspace {
                 debug_struct
                     .field("n_rustc_cfg", &rustc_cfg.len())
                     .field("toolchain", &toolchain)
-                    .field("data_layout", &data_layout);
+                    .field("data_layout", &data_layout)
+                    .field("n_cfg_overrides", &cfg_overrides.len());
                 debug_struct.finish()
             }
             ProjectWorkspace::DetachedFiles {
@@ -168,6 +173,7 @@ impl fmt::Debug for ProjectWorkspace {
                 rustc_cfg,
                 toolchain,
                 target_layout,
+                cfg_overrides,
             } => f
                 .debug_struct("DetachedFiles")
                 .field("n_files", &files.len())
@@ -175,6 +181,7 @@ impl fmt::Debug for ProjectWorkspace {
                 .field("n_rustc_cfg", &rustc_cfg.len())
                 .field("toolchain", &toolchain)
                 .field("data_layout", &target_layout)
+                .field("n_cfg_overrides", &cfg_overrides.len())
                 .finish(),
         }
     }
@@ -228,6 +235,7 @@ impl ProjectWorkspace {
                     project_json,
                     config.target.as_deref(),
                     &config.extra_env,
+                    &config.cfg_overrides,
                 )
             }
             ProjectManifest::CargoToml(cargo_toml) => {
@@ -369,6 +377,7 @@ impl ProjectWorkspace {
         project_json: ProjectJson,
         target: Option<&str>,
         extra_env: &FxHashMap<String, String>,
+        cfg_overrides: &CfgOverrides,
     ) -> ProjectWorkspace {
         let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
             (Some(sysroot), Some(sysroot_src)) => {
@@ -415,6 +424,7 @@ impl ProjectWorkspace {
             rustc_cfg,
             toolchain,
             target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            cfg_overrides: cfg_overrides.clone(),
         }
     }
 
@@ -465,6 +475,7 @@ impl ProjectWorkspace {
             rustc_cfg,
             toolchain,
             target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            cfg_overrides: config.cfg_overrides.clone(),
         })
     }
 
@@ -620,6 +631,7 @@ impl ProjectWorkspace {
                 rustc_cfg: _,
                 toolchain: _,
                 target_layout: _,
+                cfg_overrides: _,
             } => project
                 .crates()
                 .map(|(_, krate)| PackageRoot {
@@ -723,7 +735,7 @@ impl ProjectWorkspace {
 
     pub fn to_crate_graph(
         &self,
-        load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+        load: FileLoader<'_>,
         extra_env: &FxHashMap<String, String>,
     ) -> (CrateGraph, ProcMacroPaths) {
         let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
@@ -735,6 +747,7 @@ impl ProjectWorkspace {
                 rustc_cfg,
                 toolchain: _,
                 target_layout: _,
+                cfg_overrides,
             } => (
                 project_json_to_crate_graph(
                     rustc_cfg.clone(),
@@ -742,6 +755,7 @@ impl ProjectWorkspace {
                     project,
                     sysroot.as_ref().ok(),
                     extra_env,
+                    cfg_overrides,
                 ),
                 sysroot,
             ),
@@ -773,12 +787,14 @@ impl ProjectWorkspace {
                 rustc_cfg,
                 toolchain: _,
                 target_layout: _,
+                cfg_overrides,
             } => (
                 detached_files_to_crate_graph(
                     rustc_cfg.clone(),
                     load,
                     files,
                     sysroot.as_ref().ok(),
+                    cfg_overrides,
                 ),
                 sysroot,
             ),
@@ -829,28 +845,45 @@ impl ProjectWorkspace {
                     && cargo_config_extra_env == o_cargo_config_extra_env
             }
             (
-                Self::Json { project, sysroot, rustc_cfg, toolchain, target_layout: _ },
+                Self::Json {
+                    project,
+                    sysroot,
+                    rustc_cfg,
+                    toolchain,
+                    target_layout: _,
+                    cfg_overrides,
+                },
                 Self::Json {
                     project: o_project,
                     sysroot: o_sysroot,
                     rustc_cfg: o_rustc_cfg,
                     toolchain: o_toolchain,
                     target_layout: _,
+                    cfg_overrides: o_cfg_overrides,
                 },
             ) => {
                 project == o_project
                     && rustc_cfg == o_rustc_cfg
                     && sysroot == o_sysroot
                     && toolchain == o_toolchain
+                    && cfg_overrides == o_cfg_overrides
             }
             (
-                Self::DetachedFiles { files, sysroot, rustc_cfg, toolchain, target_layout },
+                Self::DetachedFiles {
+                    files,
+                    sysroot,
+                    rustc_cfg,
+                    toolchain,
+                    target_layout,
+                    cfg_overrides,
+                },
                 Self::DetachedFiles {
                     files: o_files,
                     sysroot: o_sysroot,
                     rustc_cfg: o_rustc_cfg,
                     toolchain: o_toolchain,
                     target_layout: o_target_layout,
+                    cfg_overrides: o_cfg_overrides,
                 },
             ) => {
                 files == o_files
@@ -858,6 +891,7 @@ impl ProjectWorkspace {
                     && rustc_cfg == o_rustc_cfg
                     && toolchain == o_toolchain
                     && target_layout == o_target_layout
+                    && cfg_overrides == o_cfg_overrides
             }
             _ => false,
         }
@@ -874,10 +908,11 @@ impl ProjectWorkspace {
 
 fn project_json_to_crate_graph(
     rustc_cfg: Vec<CfgFlag>,
-    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    load: FileLoader<'_>,
     project: &ProjectJson,
     sysroot: Option<&Sysroot>,
     extra_env: &FxHashMap<String, String>,
+    override_cfg: &CfgOverrides,
 ) -> (CrateGraph, ProcMacroPaths) {
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
     let (crate_graph, proc_macros) = &mut res;
@@ -917,19 +952,22 @@ fn project_json_to_crate_graph(
                     None => &rustc_cfg,
                 };
 
+                let mut cfg_options = target_cfgs
+                    .iter()
+                    .chain(cfg.iter())
+                    .chain(iter::once(&r_a_cfg_flag))
+                    .cloned()
+                    .collect();
+                override_cfg.apply(
+                    &mut cfg_options,
+                    display_name.as_ref().map(|it| it.canonical_name()).unwrap_or_default(),
+                );
                 let crate_graph_crate_id = crate_graph.add_crate_root(
                     file_id,
                     *edition,
                     display_name.clone(),
                     version.clone(),
-                    Arc::new(
-                        target_cfgs
-                            .iter()
-                            .chain(cfg.iter())
-                            .chain(iter::once(&r_a_cfg_flag))
-                            .cloned()
-                            .collect(),
-                    ),
+                    Arc::new(cfg_options),
                     None,
                     env,
                     *is_proc_macro,
@@ -976,7 +1014,7 @@ fn project_json_to_crate_graph(
 }
 
 fn cargo_to_crate_graph(
-    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    load: FileLoader<'_>,
     rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>,
     cargo: &CargoWorkspace,
     sysroot: Option<&Sysroot>,
@@ -993,7 +1031,7 @@ fn cargo_to_crate_graph(
         None => (SysrootPublicDeps::default(), None),
     };
 
-    let cfg_options = create_cfg_options(rustc_cfg);
+    let cfg_options = CfgOptions::from_iter(rustc_cfg);
 
     // Mapping of a package to its library target
     let mut pkg_to_lib_crate = FxHashMap::default();
@@ -1166,9 +1204,10 @@ fn cargo_to_crate_graph(
 
 fn detached_files_to_crate_graph(
     rustc_cfg: Vec<CfgFlag>,
-    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    load: FileLoader<'_>,
     detached_files: &[AbsPathBuf],
     sysroot: Option<&Sysroot>,
+    override_cfg: &CfgOverrides,
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered();
     let mut crate_graph = CrateGraph::default();
@@ -1177,8 +1216,10 @@ fn detached_files_to_crate_graph(
         None => (SysrootPublicDeps::default(), None),
     };
 
-    let mut cfg_options = create_cfg_options(rustc_cfg);
+    let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
+    cfg_options.insert_atom("test".into());
     cfg_options.insert_atom("rust_analyzer".into());
+    override_cfg.apply(&mut cfg_options, "");
     let cfg_options = Arc::new(cfg_options);
 
     for detached_file in detached_files {
@@ -1216,7 +1257,7 @@ fn handle_rustc_crates(
     crate_graph: &mut CrateGraph,
     proc_macros: &mut ProcMacroPaths,
     pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
-    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    load: FileLoader<'_>,
     rustc_workspace: &CargoWorkspace,
     cargo: &CargoWorkspace,
     public_deps: &SysrootPublicDeps,
@@ -1350,23 +1391,19 @@ fn add_target_crate_root(
     };
 
     let mut env = Env::default();
-    inject_cargo_env(pkg, &mut env);
-    if let Ok(cname) = String::from_str(cargo_name) {
-        // CARGO_CRATE_NAME is the name of the Cargo target with - converted to _, such as the name of the library, binary, example, integration test, or benchmark.
-        env.set("CARGO_CRATE_NAME", cname.replace('-', "_"));
-    }
+    inject_cargo_package_env(&mut env, pkg);
+    inject_cargo_env(&mut env);
+    inject_rustc_tool_env(&mut env, cargo_name, kind);
 
     if let Some(envs) = build_data.map(|it| &it.envs) {
         for (k, v) in envs {
             env.set(k, v.clone());
         }
     }
-
-    let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_owned());
     let crate_id = crate_graph.add_crate_root(
         file_id,
         edition,
-        Some(display_name),
+        Some(CrateDisplayName::from_canonical_name(cargo_name.to_owned())),
         Some(pkg.version.to_string()),
         Arc::new(cfg_options),
         potential_cfg_options.map(Arc::new),
@@ -1405,7 +1442,7 @@ fn sysroot_to_crate_graph(
     crate_graph: &mut CrateGraph,
     sysroot: &Sysroot,
     rustc_cfg: Vec<CfgFlag>,
-    load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+    load: FileLoader<'_>,
 ) -> (SysrootPublicDeps, Option<CrateId>) {
     let _p = tracing::span!(tracing::Level::INFO, "sysroot_to_crate_graph").entered();
     match sysroot.mode() {
@@ -1416,7 +1453,17 @@ fn sysroot_to_crate_graph(
                 cargo,
                 None,
                 rustc_cfg,
-                &CfgOverrides::default(),
+                &CfgOverrides {
+                    global: CfgDiff::new(
+                        vec![
+                            CfgAtom::Flag("debug_assertions".into()),
+                            CfgAtom::Flag("miri".into()),
+                        ],
+                        vec![],
+                    )
+                    .unwrap(),
+                    ..Default::default()
+                },
                 &WorkspaceBuildScripts::default(),
             );
 
@@ -1474,13 +1521,18 @@ fn sysroot_to_crate_graph(
             (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
         }
         SysrootMode::Stitched(stitched) => {
-            let cfg_options = Arc::new(create_cfg_options(rustc_cfg));
+            let cfg_options = Arc::new({
+                let mut cfg_options = CfgOptions::default();
+                cfg_options.extend(rustc_cfg);
+                cfg_options.insert_atom("debug_assertions".into());
+                cfg_options.insert_atom("miri".into());
+                cfg_options
+            });
             let sysroot_crates: FxHashMap<SysrootCrate, CrateId> = stitched
                 .crates()
                 .filter_map(|krate| {
                     let file_id = load(&stitched[krate].root)?;
 
-                    let env = Env::default();
                     let display_name =
                         CrateDisplayName::from_canonical_name(stitched[krate].name.clone());
                     let crate_id = crate_graph.add_crate_root(
@@ -1490,7 +1542,7 @@ fn sysroot_to_crate_graph(
                         None,
                         cfg_options.clone(),
                         None,
-                        env,
+                        Env::default(),
                         false,
                         CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
                     );
@@ -1548,71 +1600,3 @@ fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
         tracing::error!("{}", err)
     }
 }
-
-/// Recreates the compile-time environment variables that Cargo sets.
-///
-/// Should be synced with
-/// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates>
-///
-/// FIXME: ask Cargo to provide this data instead of re-deriving.
-fn inject_cargo_env(package: &PackageData, env: &mut Env) {
-    // FIXME: Missing variables:
-    // CARGO_BIN_NAME, CARGO_BIN_EXE_<name>
-
-    let manifest_dir = package.manifest.parent();
-    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str().to_owned());
-
-    // Not always right, but works for common cases.
-    env.set("CARGO", "cargo".into());
-
-    env.set("CARGO_PKG_VERSION", package.version.to_string());
-    env.set("CARGO_PKG_VERSION_MAJOR", package.version.major.to_string());
-    env.set("CARGO_PKG_VERSION_MINOR", package.version.minor.to_string());
-    env.set("CARGO_PKG_VERSION_PATCH", package.version.patch.to_string());
-    env.set("CARGO_PKG_VERSION_PRE", package.version.pre.to_string());
-
-    env.set("CARGO_PKG_AUTHORS", String::new());
-
-    env.set("CARGO_PKG_NAME", package.name.clone());
-    // FIXME: This isn't really correct (a package can have many crates with different names), but
-    // it's better than leaving the variable unset.
-    env.set("CARGO_CRATE_NAME", CrateName::normalize_dashes(&package.name).to_string());
-    env.set("CARGO_PKG_DESCRIPTION", String::new());
-    env.set("CARGO_PKG_HOMEPAGE", String::new());
-    env.set("CARGO_PKG_REPOSITORY", String::new());
-    env.set("CARGO_PKG_LICENSE", String::new());
-
-    env.set("CARGO_PKG_LICENSE_FILE", String::new());
-}
-
-fn create_cfg_options(rustc_cfg: Vec<CfgFlag>) -> CfgOptions {
-    let mut cfg_options = CfgOptions::default();
-    cfg_options.extend(rustc_cfg);
-    cfg_options.insert_atom("debug_assertions".into());
-    cfg_options
-}
-
-fn cargo_config_env(
-    cargo_toml: &ManifestPath,
-    extra_env: &FxHashMap<String, String>,
-    sysroot: Option<&Sysroot>,
-) -> FxHashMap<String, String> {
-    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
-    cargo_config.envs(extra_env);
-    cargo_config
-        .current_dir(cargo_toml.parent())
-        .args(["-Z", "unstable-options", "config", "get", "env"])
-        .env("RUSTC_BOOTSTRAP", "1");
-    // if successful we receive `env.key.value = "value" per entry
-    tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
-    utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
-}
-
-fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
-    stdout
-        .lines()
-        .filter_map(|l| l.strip_prefix("env."))
-        .filter_map(|l| l.split_once(".value = "))
-        .map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
-        .collect()
-}
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 6a5f7b0262..83dd99b36b 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -33,55 +33,53 @@ impl CargoTargetSpec {
         kind: &RunnableKind,
         cfg: &Option<CfgExpr>,
     ) -> (Vec<String>, Vec<String>) {
-        let extra_test_binary_args = snap.config.runnables().extra_test_binary_args;
-
-        let mut cargo_args = Vec::new();
-        let mut executable_args = Vec::new();
+        let mut args = Vec::new();
+        let mut extra_args = Vec::new();
 
         match kind {
             RunnableKind::Test { test_id, attr } => {
-                cargo_args.push("test".to_owned());
-                executable_args.push(test_id.to_string());
+                args.push("test".to_owned());
+                extra_args.push(test_id.to_string());
                 if let TestId::Path(_) = test_id {
-                    executable_args.push("--exact".to_owned());
+                    extra_args.push("--exact".to_owned());
                 }
-                executable_args.extend(extra_test_binary_args);
+                extra_args.push("--nocapture".to_owned());
                 if attr.ignore {
-                    executable_args.push("--ignored".to_owned());
+                    extra_args.push("--ignored".to_owned());
                 }
             }
             RunnableKind::TestMod { path } => {
-                cargo_args.push("test".to_owned());
-                executable_args.push(path.clone());
-                executable_args.extend(extra_test_binary_args);
+                args.push("test".to_owned());
+                extra_args.push(path.clone());
+                extra_args.push("--nocapture".to_owned());
             }
             RunnableKind::Bench { test_id } => {
-                cargo_args.push("bench".to_owned());
-                executable_args.push(test_id.to_string());
+                args.push("bench".to_owned());
+                extra_args.push(test_id.to_string());
                 if let TestId::Path(_) = test_id {
-                    executable_args.push("--exact".to_owned());
+                    extra_args.push("--exact".to_owned());
                 }
-                executable_args.extend(extra_test_binary_args);
+                extra_args.push("--nocapture".to_owned());
             }
             RunnableKind::DocTest { test_id } => {
-                cargo_args.push("test".to_owned());
-                cargo_args.push("--doc".to_owned());
-                executable_args.push(test_id.to_string());
-                executable_args.extend(extra_test_binary_args);
+                args.push("test".to_owned());
+                args.push("--doc".to_owned());
+                extra_args.push(test_id.to_string());
+                extra_args.push("--nocapture".to_owned());
             }
             RunnableKind::Bin => {
                 let subcommand = match spec {
                     Some(CargoTargetSpec { target_kind: TargetKind::Test, .. }) => "test",
                     _ => "run",
                 };
-                cargo_args.push(subcommand.to_owned());
+                args.push(subcommand.to_owned());
             }
         }
 
         let (allowed_features, target_required_features) = if let Some(mut spec) = spec {
             let allowed_features = mem::take(&mut spec.features);
             let required_features = mem::take(&mut spec.required_features);
-            spec.push_to(&mut cargo_args, kind);
+            spec.push_to(&mut args, kind);
             (allowed_features, required_features)
         } else {
             (Default::default(), Default::default())
@@ -91,10 +89,10 @@ impl CargoTargetSpec {
 
         match &cargo_config.features {
             CargoFeatures::All => {
-                cargo_args.push("--all-features".to_owned());
+                args.push("--all-features".to_owned());
                 for feature in target_required_features {
-                    cargo_args.push("--features".to_owned());
-                    cargo_args.push(feature);
+                    args.push("--features".to_owned());
+                    args.push(feature);
                 }
             }
             CargoFeatures::Selected { features, no_default_features } => {
@@ -110,16 +108,16 @@ impl CargoTargetSpec {
 
                 feats.dedup();
                 for feature in feats {
-                    cargo_args.push("--features".to_owned());
-                    cargo_args.push(feature);
+                    args.push("--features".to_owned());
+                    args.push(feature);
                 }
 
                 if *no_default_features {
-                    cargo_args.push("--no-default-features".to_owned());
+                    args.push("--no-default-features".to_owned());
                 }
             }
         }
-        (cargo_args, executable_args)
+        (args, extra_args)
     }
 
     pub(crate) fn for_file(
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 5dfd7c4435..0d99a8f113 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -124,7 +124,12 @@ config_data! {
         /// avoid checking unnecessary things.
         cargo_buildScripts_useRustcWrapper: bool = true,
         /// List of cfg options to enable with the given values.
-        cargo_cfgs: FxHashMap<String, String> = FxHashMap::default(),
+        cargo_cfgs: FxHashMap<String, Option<String>> = {
+            let mut m = FxHashMap::default();
+            m.insert("debug_assertions".to_owned(), None);
+            m.insert("miri".to_owned(), None);
+            m
+        },
         /// Extra arguments that are passed to every cargo invocation.
         cargo_extraArgs: Vec<String> = vec![],
         /// Extra environment variables that will be set when running cargo, rustc
@@ -390,14 +395,6 @@ config_data! {
         /// Additional arguments to be passed to cargo for runnables such as
         /// tests or binaries. For example, it may be `--release`.
         runnables_extraArgs: Vec<String>   = vec![],
-        /// Additional arguments to be passed through Cargo to launched tests, benchmarks, or
-        /// doc-tests.
-        ///
-        /// Unless the launched target uses a
-        /// [custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),
-        /// they will end up being interpreted as options to
-        /// [`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).
-        runnables_extraTestBinaryArgs: Vec<String> = vec!["--show-output".to_owned()],
 
         /// Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private
         /// projects, or "discover" to try to automatically find it if the `rustc-dev` component
@@ -829,8 +826,6 @@ pub struct RunnablesConfig {
     pub override_cargo: Option<String>,
     /// Additional arguments for the `cargo`, e.g. `--release`.
     pub cargo_extra_args: Vec<String>,
-    /// Additional arguments for the binary being run, if it is a test or benchmark.
-    pub extra_test_binary_args: Vec<String>,
 }
 
 /// Configuration for workspace symbol search requests.
@@ -1601,12 +1596,9 @@ impl Config {
                 global: CfgDiff::new(
                     self.cargo_cfgs()
                         .iter()
-                        .map(|(key, val)| {
-                            if val.is_empty() {
-                                CfgAtom::Flag(key.into())
-                            } else {
-                                CfgAtom::KeyValue { key: key.into(), value: val.into() }
-                            }
+                        .map(|(key, val)| match val {
+                            Some(val) => CfgAtom::KeyValue { key: key.into(), value: val.into() },
+                            None => CfgAtom::Flag(key.into()),
                         })
                         .collect(),
                     vec![],
@@ -1748,7 +1740,6 @@ impl Config {
         RunnablesConfig {
             override_cargo: self.runnables_command().clone(),
             cargo_extra_args: self.runnables_extraArgs().clone(),
-            extra_test_binary_args: self.runnables_extraTestBinaryArgs().clone(),
         }
     }
 
@@ -2678,6 +2669,9 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
         "FxHashMap<Box<str>, usize>" => set! {
             "type": "object",
         },
+        "FxHashMap<String, Option<String>>" => set! {
+            "type": "object",
+        },
         "Option<usize>" => set! {
             "type": ["null", "integer"],
             "minimum": 0,
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index d2e495dbfc..00a61758f0 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -234,6 +234,7 @@ impl GlobalState {
                                 it.clone(),
                                 cargo_config.target.as_deref(),
                                 &cargo_config.extra_env,
+                                &cargo_config.cfg_overrides,
                             ))
                         }
                     })
diff --git a/crates/span/src/map.rs b/crates/span/src/map.rs
index 81fc56c961..6d8c9c30fb 100644
--- a/crates/span/src/map.rs
+++ b/crates/span/src/map.rs
@@ -15,9 +15,6 @@ use crate::{
 #[derive(Debug, PartialEq, Eq, Clone, Hash)]
 pub struct SpanMap<S> {
     spans: Vec<(TextSize, SpanData<S>)>,
-    /// Index of the matched macro arm on successful expansion for declarative macros.
-    // FIXME: Does it make sense to have this here?
-    pub matched_arm: Option<u32>,
 }
 
 impl<S> SpanMap<S>
@@ -26,7 +23,7 @@ where
 {
     /// Creates a new empty [`SpanMap`].
     pub fn empty() -> Self {
-        Self { spans: Vec::new(), matched_arm: None }
+        Self { spans: Vec::new() }
     }
 
     /// Finalizes the [`SpanMap`], shrinking its backing storage and validating that the offsets are
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index f20baee789..7bd3012056 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -88,10 +88,18 @@ or build-script sources change and are saved.
 Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
 avoid checking unnecessary things.
 --
-[[rust-analyzer.cargo.cfgs]]rust-analyzer.cargo.cfgs (default: `{}`)::
+[[rust-analyzer.cargo.cfgs]]rust-analyzer.cargo.cfgs::
 +
 --
+Default:
+----
+{
+  "debug_assertions": null,
+  "miri": null
+}
+----
 List of cfg options to enable with the given values.
+
 --
 [[rust-analyzer.cargo.extraArgs]]rust-analyzer.cargo.extraArgs (default: `[]`)::
 +
@@ -839,24 +847,6 @@ Command to be executed instead of 'cargo' for runnables.
 --
 Additional arguments to be passed to cargo for runnables such as
 tests or binaries. For example, it may be `--release`.
---
-[[rust-analyzer.runnables.extraTestBinaryArgs]]rust-analyzer.runnables.extraTestBinaryArgs::
-+
---
-Default:
-----
-[
-  "--show-output"
-]
-----
-Additional arguments to be passed through Cargo to launched tests, benchmarks, or
-doc-tests.
-
-Unless the launched target uses a
-[custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),
-they will end up being interpreted as options to
-[`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).
-
 --
 [[rust-analyzer.rustc.source]]rust-analyzer.rustc.source (default: `null`)::
 +
diff --git a/editors/code/package.json b/editors/code/package.json
index a6d21cbf58..0fd17f385e 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -610,7 +610,10 @@
                 },
                 "rust-analyzer.cargo.cfgs": {
                     "markdownDescription": "List of cfg options to enable with the given values.",
-                    "default": {},
+                    "default": {
+                        "debug_assertions": null,
+                        "miri": null
+                    },
                     "type": "object"
                 },
                 "rust-analyzer.cargo.extraArgs": {
@@ -1584,16 +1587,6 @@
                         "type": "string"
                     }
                 },
-                "rust-analyzer.runnables.extraTestBinaryArgs": {
-                    "markdownDescription": "Additional arguments to be passed through Cargo to launched tests, benchmarks, or\ndoc-tests.\n\nUnless the launched target uses a\n[custom test harness](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-harness-field),\nthey will end up being interpreted as options to\n[`rustc`’s built-in test harness (“libtest”)](https://doc.rust-lang.org/rustc/tests/index.html#cli-arguments).",
-                    "default": [
-                        "--show-output"
-                    ],
-                    "type": "array",
-                    "items": {
-                        "type": "string"
-                    }
-                },
                 "rust-analyzer.rustc.source": {
                     "markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it if the `rustc-dev` component\nis installed.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option does not take effect until rust-analyzer is restarted.",
                     "default": null,


Test patch:
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 937e78f8d7..d0355bd028 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -390,36 +390,6 @@ fn main() {
     )
 }
 
-#[test]
-fn doctest_convert_from_to_tryfrom() {
-    check_doc_test(
-        "convert_from_to_tryfrom",
-        r#####"
-//- minicore: from
-impl $0From<usize> for Thing {
-    fn from(val: usize) -> Self {
-        Thing {
-            b: val.to_string(),
-            a: val
-        }
-    }
-}
-"#####,
-        r#####"
-impl TryFrom<usize> for Thing {
-    type Error = ${0:()};
-
-    fn try_from(val: usize) -> Result<Self, Self::Error> {
-        Ok(Thing {
-            b: val.to_string(),
-            a: val
-        })
-    }
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_convert_if_to_bool_then() {
     check_doc_test(
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 6bbc8b380d..67f10f0374 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -1560,21 +1560,21 @@ fn y() {
 fn test_hover_macro_invocation() {
     check(
         r#"
-macro_rules! foo { (a) => {}; () => {} }
+macro_rules! foo { () => {} }
 
 fn f() { fo$0o!(); }
 "#,
         expect![[r#"
-            *foo*
+                *foo*
 
-            ```rust
-            test
-            ```
+                ```rust
+                test
+                ```
 
-            ```rust
-            macro_rules! foo // matched arm #1
-            ```
-        "#]],
+                ```rust
+                macro_rules! foo
+                ```
+            "#]],
     )
 }
 
@@ -1590,22 +1590,22 @@ macro foo() {}
 fn f() { fo$0o!(); }
 "#,
         expect![[r#"
-            *foo*
+                *foo*
 
-            ```rust
-            test
-            ```
+                ```rust
+                test
+                ```
 
-            ```rust
-            macro foo // matched arm #0
-            ```
+                ```rust
+                macro foo
+                ```
 
-            ---
+                ---
 
-            foo bar
+                foo bar
 
-            foo bar baz
-        "#]],
+                foo bar baz
+            "#]],
     )
 }
 
diff --git a/crates/proc-macro-srv/proc-macro-test/build.rs b/crates/proc-macro-srv/proc-macro-test/build.rs
index 6a0ae362d8..c76c201d69 100644
--- a/crates/proc-macro-srv/proc-macro-test/build.rs
+++ b/crates/proc-macro-srv/proc-macro-test/build.rs
@@ -53,7 +53,7 @@ fn main() {
     println!("Creating {}", src_dir.display());
     std::fs::create_dir_all(src_dir).unwrap();
 
-    for item_els in [&["Cargo.toml"][..], &["build.rs"][..], &["src", "lib.rs"]] {
+    for item_els in [&["Cargo.toml"][..], &["src", "lib.rs"]] {
         let mut src = imp_dir.clone();
         let mut dst = staging_dir.clone();
         for el in item_els {
diff --git a/crates/proc-macro-srv/proc-macro-test/imp/build.rs b/crates/proc-macro-srv/proc-macro-test/imp/build.rs
deleted file mode 100644
index 07f914fece..0000000000
--- a/crates/proc-macro-srv/proc-macro-test/imp/build.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//! This teaches cargo about our cfg(rust_analyzer)
-
-fn main() {
-    println!("cargo:rustc-check-cfg=cfg(rust_analyzer)");
-}
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index fc0b507b33..fd09dff503 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -75,6 +75,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
         rustc_cfg: Vec::new(),
         toolchain: None,
         target_layout: Err(Arc::from("test has no data layout")),
+        cfg_overrides: Default::default(),
     };
     to_crate_graph(project_workspace)
 }
@@ -97,6 +98,11 @@ fn get_test_json_file<T: DeserializeOwned>(file: &str) -> T {
     }
 }
 
+fn replace_cargo(s: &mut String) {
+    let path = toolchain::Tool::Cargo.path().to_string().escape_debug().collect::<String>();
+    *s = s.replace(&path, "$CARGO$");
+}
+
 fn replace_root(s: &mut String, direction: bool) {
     if direction {
         let root = if cfg!(windows) { r#"C:\\ROOT\"# } else { "/ROOT/" };
@@ -155,7 +161,9 @@ fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacro
 
 fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
     let mut crate_graph = format!("{crate_graph:#?}");
+
     replace_root(&mut crate_graph, false);
+    replace_cargo(&mut crate_graph);
     replace_fake_sys_root(&mut crate_graph);
     expect.assert_eq(&crate_graph);
 }
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 0ad19ca9f7..c2a2d6ed91 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -17,7 +17,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -25,20 +24,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -77,7 +78,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -85,20 +85,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -144,7 +146,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -152,20 +153,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "an_example",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -211,7 +214,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -219,20 +221,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "it",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -278,7 +282,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "feature=default",
                 "feature=std",
             ],
@@ -286,7 +289,6 @@
         potential_cfg_options: Some(
             CfgOptions(
                 [
-                    "debug_assertions",
                     "feature=align",
                     "feature=const-extern-fn",
                     "feature=default",
@@ -299,20 +301,22 @@
         ),
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
-                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                "CARGO_PKG_VERSION": "0.2.98",
-                "CARGO_PKG_AUTHORS": "",
+                "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
+                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_PKG_AUTHORS": "The Rust Project Developers",
+                "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
+                "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_LICENSE": "MIT OR Apache-2.0",
                 "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
-                "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_NAME": "libc",
-                "CARGO_PKG_VERSION_PATCH": "98",
-                "CARGO": "cargo",
-                "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_README": "README.md",
+                "CARGO_PKG_REPOSITORY": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.2.98",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "2",
+                "CARGO_PKG_VERSION_PATCH": "98",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 0ad19ca9f7..c2a2d6ed91 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -17,7 +17,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -25,20 +24,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -77,7 +78,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -85,20 +85,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -144,7 +146,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -152,20 +153,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "an_example",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -211,7 +214,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
                 "test",
             ],
@@ -219,20 +221,22 @@
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "it",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -278,7 +282,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "feature=default",
                 "feature=std",
             ],
@@ -286,7 +289,6 @@
         potential_cfg_options: Some(
             CfgOptions(
                 [
-                    "debug_assertions",
                     "feature=align",
                     "feature=const-extern-fn",
                     "feature=default",
@@ -299,20 +301,22 @@
         ),
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
-                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                "CARGO_PKG_VERSION": "0.2.98",
-                "CARGO_PKG_AUTHORS": "",
+                "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
+                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_PKG_AUTHORS": "The Rust Project Developers",
+                "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
+                "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_LICENSE": "MIT OR Apache-2.0",
                 "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
-                "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_NAME": "libc",
-                "CARGO_PKG_VERSION_PATCH": "98",
-                "CARGO": "cargo",
-                "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_README": "README.md",
+                "CARGO_PKG_REPOSITORY": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.2.98",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "2",
+                "CARGO_PKG_VERSION_PATCH": "98",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index e2334dca87..c291ffcca7 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -17,27 +17,28 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
             ],
         ),
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -76,27 +77,28 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
             ],
         ),
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "hello_world",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -142,27 +144,28 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
             ],
         ),
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "an_example",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -208,27 +211,28 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "rust_analyzer",
             ],
         ),
         potential_cfg_options: None,
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
+                "CARGO": "$CARGO$",
+                "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
-                "CARGO_PKG_VERSION": "0.1.0",
                 "CARGO_PKG_AUTHORS": "",
-                "CARGO_CRATE_NAME": "it",
-                "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
                 "CARGO_PKG_DESCRIPTION": "",
+                "CARGO_PKG_HOMEPAGE": "",
+                "CARGO_PKG_LICENSE": "",
+                "CARGO_PKG_LICENSE_FILE": "",
                 "CARGO_PKG_NAME": "hello-world",
-                "CARGO_PKG_VERSION_PATCH": "0",
-                "CARGO": "cargo",
+                "CARGO_PKG_README": "",
                 "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.1.0",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "1",
+                "CARGO_PKG_VERSION_PATCH": "0",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
@@ -274,7 +278,6 @@
         ),
         cfg_options: CfgOptions(
             [
-                "debug_assertions",
                 "feature=default",
                 "feature=std",
             ],
@@ -282,7 +285,6 @@
         potential_cfg_options: Some(
             CfgOptions(
                 [
-                    "debug_assertions",
                     "feature=align",
                     "feature=const-extern-fn",
                     "feature=default",
@@ -295,20 +297,22 @@
         ),
         env: Env {
             entries: {
-                "CARGO_PKG_LICENSE": "",
-                "CARGO_PKG_VERSION_MAJOR": "0",
-                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
-                "CARGO_PKG_VERSION": "0.2.98",
-                "CARGO_PKG_AUTHORS": "",
+                "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
+                "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_PKG_AUTHORS": "The Rust Project Developers",
+                "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
+                "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_LICENSE": "MIT OR Apache-2.0",
                 "CARGO_PKG_LICENSE_FILE": "",
-                "CARGO_PKG_HOMEPAGE": "",
-                "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_NAME": "libc",
-                "CARGO_PKG_VERSION_PATCH": "98",
-                "CARGO": "cargo",
-                "CARGO_PKG_REPOSITORY": "",
+                "CARGO_PKG_README": "README.md",
+                "CARGO_PKG_REPOSITORY": "https://github.com/rust-lang/libc",
+                "CARGO_PKG_RUST_VERSION": "",
+                "CARGO_PKG_VERSION": "0.2.98",
+                "CARGO_PKG_VERSION_MAJOR": "0",
                 "CARGO_PKG_VERSION_MINOR": "2",
+                "CARGO_PKG_VERSION_PATCH": "98",
                 "CARGO_PKG_VERSION_PRE": "",
             },
         },
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index ccaba963de..80c9136589 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -16,6 +16,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -53,6 +54,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -82,6 +84,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -111,6 +114,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -140,6 +144,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -184,6 +189,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -213,6 +219,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -299,6 +306,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -328,6 +336,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
@@ -357,6 +366,7 @@
         cfg_options: CfgOptions(
             [
                 "debug_assertions",
+                "miri",
             ],
         ),
         potential_cfg_options: None,
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index eeec13a14b..548dd4e70e 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -81,6 +81,7 @@ impl Tester {
             rustc_cfg: vec![],
             toolchain: None,
             target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+            cfg_overrides: Default::default(),
         };
         let load_cargo_config = LoadCargoConfig {
             load_out_dirs_from_check: false,
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index 786a80c4a6..8c982b4687 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -157,7 +157,7 @@ fn main() {}
           {
             "args": {
               "cargoArgs": ["test", "--package", "foo", "--test", "spam"],
-              "executableArgs": ["test_eggs", "--exact", "--show-output"],
+              "executableArgs": ["test_eggs", "--exact", "--nocapture"],
               "cargoExtraArgs": [],
               "overrideCargo": null,
               "workspaceRoot": server.path().join("foo")
@@ -190,7 +190,7 @@ fn main() {}
               "cargoExtraArgs": [],
               "executableArgs": [
                 "",
-                "--show-output"
+                "--nocapture"
               ]
             },
             "kind": "cargo",
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index fdca069dc8..89ed6a6157 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -209,7 +209,7 @@ impl ChangeFixture {
                 assert!(default_crate_root.is_none());
                 default_crate_root = Some(file_id);
                 default_cfg.extend(meta.cfg.into_iter());
-                default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
+                default_env.extend_from_other(&meta.env);
             }
 
             source_change.change_file(file_id, Some(text));