diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 4f68c91cc97..fd45eccf5aa 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -8,7 +8,7 @@ use either::Either;
 use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
 use itertools::Itertools;
 use la_arena::ArenaMap;
-use mbe::{syntax_node_to_token_tree, DelimiterKind};
+use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
 use smallvec::{smallvec, SmallVec};
 use syntax::{
     ast::{self, AstNode, HasAttrs, IsString},
@@ -722,41 +722,35 @@ impl Attr {
     /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
     /// to derive macros.
     ///
-    /// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
+    /// Returns `None` when the attribute does not have a well-formed `#[derive]` attribute input.
     pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
-        if self.path.as_ident() != Some(&hir_expand::name![derive]) {
-            return None;
-        }
-
-        match self.input.as_deref() {
-            Some(AttrInput::TokenTree(args, _)) => {
-                let mut counter = 0;
-                let paths = args
-                    .token_trees
-                    .iter()
-                    .group_by(move |tt| {
-                        match tt {
-                            tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
-                                counter += 1;
-                            }
-                            _ => {}
-                        }
-                        counter
-                    })
-                    .into_iter()
-                    .map(|(_, tts)| {
-                        let segments = tts.filter_map(|tt| match tt {
-                            tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
-                            _ => None,
-                        });
-                        ModPath::from_segments(PathKind::Plain, segments)
-                    })
-                    .collect::<Vec<_>>();
-
-                Some(paths.into_iter())
+        if let Some(AttrInput::TokenTree(args, _)) = self.input.as_deref() {
+            if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
+                return None;
             }
-            _ => None,
+            let mut counter = 0;
+            let paths = args
+                .token_trees
+                .iter()
+                .group_by(move |tt| {
+                    if let tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })) = tt {
+                        counter += 1;
+                    }
+                    counter
+                })
+                .into_iter()
+                .map(|(_, tts)| {
+                    let segments = tts.filter_map(|tt| match tt {
+                        tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
+                        _ => None,
+                    });
+                    ModPath::from_segments(PathKind::Plain, segments)
+                })
+                .collect::<Vec<_>>();
+
+            return Some(paths.into_iter());
         }
+        None
     }
 
     pub fn string_value(&self) -> Option<&SmolStr> {
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 1abda2d66aa..b68ede40039 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -776,13 +776,10 @@ fn attr_macro_as_call_id(
     macro_attr: &Attr,
     db: &dyn db::DefDatabase,
     krate: CrateId,
-    resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+    def: Option<MacroDefId>,
 ) -> Result<MacroCallId, UnresolvedMacro> {
     let attr_path = &item_attr.path;
-
-    let def = resolver(attr_path.clone())
-        .filter(MacroDefId::is_attribute)
-        .ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
+    let def = def.ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
     let last_segment =
         attr_path.segments().last().ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
     let mut arg = match macro_attr.input.as_deref() {
diff --git a/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs
index aa50fa6d33e..8ee33101e4d 100644
--- a/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs
+++ b/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs
@@ -26,12 +26,16 @@ fn test_copy_expand_in_core() {
     check(
         r#"
 #[rustc_builtin_macro]
+macro derive {}
+#[rustc_builtin_macro]
 macro Copy {}
 #[derive(Copy)]
 struct Foo;
 "#,
         expect![[r##"
 #[rustc_builtin_macro]
+macro derive {}
+#[rustc_builtin_macro]
 macro Copy {}
 #[derive(Copy)]
 struct Foo;
diff --git a/crates/hir_def/src/macro_expansion_tests/proc_macros.rs b/crates/hir_def/src/macro_expansion_tests/proc_macros.rs
index 81f58fa2cef..901872eddab 100644
--- a/crates/hir_def/src/macro_expansion_tests/proc_macros.rs
+++ b/crates/hir_def/src/macro_expansion_tests/proc_macros.rs
@@ -31,6 +31,7 @@ fn derive_censoring() {
     check(
         r#"
 //- proc_macros: derive_identity
+//- minicore:derive
 #[attr1]
 #[derive(Foo)]
 #[derive(proc_macros::DeriveIdentity)]
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index e45711db756..bafba0672fc 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -9,7 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
 use cfg::{CfgExpr, CfgOptions};
 use hir_expand::{
     ast_id_map::FileAstId,
-    builtin_attr_macro::{find_builtin_attr, is_builtin_test_or_bench_attr},
+    builtin_attr_macro::find_builtin_attr,
     builtin_derive_macro::find_builtin_derive,
     builtin_fn_macro::find_builtin_macro,
     name::{name, AsName, Name},
@@ -781,7 +781,7 @@ impl DefCollector<'_> {
     }
 
     fn resolve_extern_crate(&self, name: &Name) -> PerNs {
-        if name == &name!(self) {
+        if *name == name!(self) {
             cov_mark::hit!(extern_crate_self_as);
             let root = match self.def_map.block {
                 Some(_) => {
@@ -1054,14 +1054,15 @@ impl DefCollector<'_> {
 
             match &directive.kind {
                 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
-                    match macro_call_as_call_id(
+                    let call_id = macro_call_as_call_id(
                         ast_id,
                         *expand_to,
                         self.db,
                         self.def_map.krate,
                         &resolver,
                         &mut |_err| (),
-                    ) {
+                    );
+                    match call_id {
                         Ok(Ok(call_id)) => {
                             resolved.push((directive.module_id, call_id, directive.depth));
                             res = ReachedFixedPoint::No;
@@ -1071,13 +1072,14 @@ impl DefCollector<'_> {
                     }
                 }
                 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
-                    match derive_macro_as_call_id(
+                    let call_id = derive_macro_as_call_id(
                         ast_id,
                         *derive_attr,
                         self.db,
                         self.def_map.krate,
                         &resolver,
-                    ) {
+                    );
+                    match call_id {
                         Ok(call_id) => {
                             self.def_map.modules[directive.module_id].scope.add_derive_macro_invoc(
                                 ast_id.ast_id,
@@ -1089,73 +1091,103 @@ impl DefCollector<'_> {
                             res = ReachedFixedPoint::No;
                             return false;
                         }
-                        Err(UnresolvedMacro { .. }) => (),
+                        Err(UnresolvedMacro { .. }) => {}
                     }
                 }
                 MacroDirectiveKind::Attr { ast_id, mod_item, attr } => {
+                    let file_id = ast_id.ast_id.file_id;
+                    let mut recollect_without = |collector: &mut Self, item_tree| {
+                        // Remove the original directive since we resolved it.
+                        let mod_dir = collector.mod_dirs[&directive.module_id].clone();
+                        collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
+                        ModCollector {
+                            def_collector: collector,
+                            macro_depth: directive.depth,
+                            module_id: directive.module_id,
+                            tree_id: TreeId::new(file_id, None),
+                            item_tree,
+                            mod_dir,
+                        }
+                        .collect(&[*mod_item]);
+                        res = ReachedFixedPoint::No;
+                        false
+                    };
+
                     if let Some(ident) = ast_id.path.as_ident() {
                         if let Some(helpers) = self.derive_helpers_in_scope.get(&ast_id.ast_id) {
                             if helpers.contains(ident) {
                                 cov_mark::hit!(resolved_derive_helper);
-
                                 // Resolved to derive helper. Collect the item's attributes again,
                                 // starting after the derive helper.
-                                let file_id = ast_id.ast_id.file_id;
                                 let item_tree = self.db.file_item_tree(file_id);
-                                let mod_dir = self.mod_dirs[&directive.module_id].clone();
-                                self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
-                                ModCollector {
-                                    def_collector: &mut *self,
-                                    macro_depth: directive.depth,
-                                    module_id: directive.module_id,
-                                    tree_id: TreeId::new(file_id, None),
-                                    item_tree: &item_tree,
-                                    mod_dir,
-                                }
-                                .collect(&[*mod_item]);
+                                return recollect_without(self, &item_tree);
+                            }
+                        }
+                    }
 
-                                // Remove the original directive since we resolved it.
+                    let def = resolver(ast_id.path.clone()).filter(MacroDefId::is_attribute);
+                    if matches!(
+                        def,
+                        Some(MacroDefId {  kind:MacroDefKind::BuiltInAttr(expander, _),.. })
+                        if expander.is_derive()
+                    ) {
+                        // Resolved to `#[derive]`
+                        let file_id = ast_id.ast_id.file_id;
+                        let item_tree = self.db.file_item_tree(file_id);
+
+                        let ast_id: FileAstId<ast::Item> = match *mod_item {
+                            ModItem::Struct(it) => item_tree[it].ast_id.upcast(),
+                            ModItem::Union(it) => item_tree[it].ast_id.upcast(),
+                            ModItem::Enum(it) => item_tree[it].ast_id.upcast(),
+                            _ => {
+                                // Cannot use derive on this item.
+                                // FIXME: diagnose
                                 res = ReachedFixedPoint::No;
                                 return false;
                             }
+                        };
+
+                        match attr.parse_derive() {
+                            Some(derive_macros) => {
+                                for path in derive_macros {
+                                    let ast_id = AstIdWithPath::new(file_id, ast_id, path);
+                                    self.unresolved_macros.push(MacroDirective {
+                                        module_id: directive.module_id,
+                                        depth: directive.depth + 1,
+                                        kind: MacroDirectiveKind::Derive {
+                                            ast_id,
+                                            derive_attr: attr.id,
+                                        },
+                                    });
+                                }
+                            }
+                            None => {
+                                // FIXME: diagnose
+                                tracing::debug!("malformed derive: {:?}", attr);
+                            }
                         }
+
+                        return recollect_without(self, &item_tree);
                     }
 
                     if !self.db.enable_proc_attr_macros() {
                         return true;
                     }
 
-                    // Not resolved to a derive helper, so try to resolve as a macro.
-                    match attr_macro_as_call_id(
-                        ast_id,
-                        attr,
-                        self.db,
-                        self.def_map.krate,
-                        &resolver,
-                    ) {
+                    // Not resolved to a derive helper or the derive attribute, so try to resolve as a normal attribute.
+                    match attr_macro_as_call_id(ast_id, attr, self.db, self.def_map.krate, def) {
                         Ok(call_id) => {
                             let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
 
                             // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
                             // due to duplicating functions into macro expansions
-                            if is_builtin_test_or_bench_attr(loc.def) {
-                                let file_id = ast_id.ast_id.file_id;
+                            if matches!(
+                                loc.def.kind,
+                                MacroDefKind::BuiltInAttr(expander, _)
+                                if expander.is_test() || expander.is_bench()
+                            ) {
                                 let item_tree = self.db.file_item_tree(file_id);
-                                let mod_dir = self.mod_dirs[&directive.module_id].clone();
-                                self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
-                                ModCollector {
-                                    def_collector: &mut *self,
-                                    macro_depth: directive.depth,
-                                    module_id: directive.module_id,
-                                    tree_id: TreeId::new(file_id, None),
-                                    item_tree: &item_tree,
-                                    mod_dir,
-                                }
-                                .collect(&[*mod_item]);
-
-                                // Remove the original directive since we resolved it.
-                                res = ReachedFixedPoint::No;
-                                return false;
+                                return recollect_without(self, &item_tree);
                             }
 
                             if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
@@ -1171,21 +1203,7 @@ impl DefCollector<'_> {
 
                                     let file_id = ast_id.ast_id.file_id;
                                     let item_tree = self.db.file_item_tree(file_id);
-                                    let mod_dir = self.mod_dirs[&directive.module_id].clone();
-                                    self.skip_attrs
-                                        .insert(InFile::new(file_id, *mod_item), attr.id);
-                                    ModCollector {
-                                        def_collector: &mut *self,
-                                        macro_depth: directive.depth,
-                                        module_id: directive.module_id,
-                                        tree_id: TreeId::new(file_id, None),
-                                        item_tree: &item_tree,
-                                        mod_dir,
-                                    }
-                                    .collect(&[*mod_item]);
-
-                                    // Remove the macro directive.
-                                    return false;
+                                    return recollect_without(self, &item_tree);
                                 }
                             }
 
@@ -1281,7 +1299,7 @@ impl DefCollector<'_> {
         for directive in &self.unresolved_macros {
             match &directive.kind {
                 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
-                    match macro_call_as_call_id(
+                    let macro_call_as_call_id = macro_call_as_call_id(
                         ast_id,
                         *expand_to,
                         self.db,
@@ -1297,15 +1315,13 @@ impl DefCollector<'_> {
                             resolved_res.resolved_def.take_macros()
                         },
                         &mut |_| (),
-                    ) {
-                        Ok(_) => (),
-                        Err(UnresolvedMacro { path }) => {
-                            self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
-                                directive.module_id,
-                                ast_id.ast_id,
-                                path,
-                            ));
-                        }
+                    );
+                    if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
+                        self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+                            directive.module_id,
+                            ast_id.ast_id,
+                            path,
+                        ));
                     }
                 }
                 MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
@@ -1747,26 +1763,23 @@ impl ModCollector<'_, '_> {
             });
 
         for attr in iter {
-            if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
-                self.collect_derive(attr, mod_item);
-            } else if self.is_builtin_or_registered_attr(&attr.path) {
+            if self.is_builtin_or_registered_attr(&attr.path) {
                 continue;
-            } else {
-                tracing::debug!("non-builtin attribute {}", attr.path);
-
-                let ast_id = AstIdWithPath::new(
-                    self.file_id(),
-                    mod_item.ast_id(self.item_tree),
-                    attr.path.as_ref().clone(),
-                );
-                self.def_collector.unresolved_macros.push(MacroDirective {
-                    module_id: self.module_id,
-                    depth: self.macro_depth + 1,
-                    kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
-                });
-
-                return Err(());
             }
+            tracing::debug!("non-builtin attribute {}", attr.path);
+
+            let ast_id = AstIdWithPath::new(
+                self.file_id(),
+                mod_item.ast_id(self.item_tree),
+                attr.path.as_ref().clone(),
+            );
+            self.def_collector.unresolved_macros.push(MacroDirective {
+                module_id: self.module_id,
+                depth: self.macro_depth + 1,
+                kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
+            });
+
+            return Err(());
         }
 
         Ok(())
@@ -1800,36 +1813,6 @@ impl ModCollector<'_, '_> {
         false
     }
 
-    fn collect_derive(&mut self, attr: &Attr, mod_item: ModItem) {
-        let ast_id: FileAstId<ast::Item> = match mod_item {
-            ModItem::Struct(it) => self.item_tree[it].ast_id.upcast(),
-            ModItem::Union(it) => self.item_tree[it].ast_id.upcast(),
-            ModItem::Enum(it) => self.item_tree[it].ast_id.upcast(),
-            _ => {
-                // Cannot use derive on this item.
-                // FIXME: diagnose
-                return;
-            }
-        };
-
-        match attr.parse_derive() {
-            Some(derive_macros) => {
-                for path in derive_macros {
-                    let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path);
-                    self.def_collector.unresolved_macros.push(MacroDirective {
-                        module_id: self.module_id,
-                        depth: self.macro_depth + 1,
-                        kind: MacroDirectiveKind::Derive { ast_id, derive_attr: attr.id },
-                    });
-                }
-            }
-            None => {
-                // FIXME: diagnose
-                tracing::debug!("malformed derive: {:?}", attr);
-            }
-        }
-    }
-
     /// If `attrs` registers a procedural macro, collects its definition.
     fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
         // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 763dff5a214..fbb1320d6e8 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -669,19 +669,20 @@ pub struct bar;
 fn expand_derive() {
     let map = compute_crate_def_map(
         r#"
-        //- /main.rs crate:main deps:core
-        use core::Copy;
+//- /main.rs crate:main deps:core
+use core::Copy;
 
-        #[derive(Copy, core::Clone)]
-        struct Foo;
+#[core::derive(Copy, core::Clone)]
+struct Foo;
 
-        //- /core.rs crate:core
-        #[rustc_builtin_macro]
-        pub macro Copy {}
-
-        #[rustc_builtin_macro]
-        pub macro Clone {}
-        "#,
+//- /core.rs crate:core
+#[rustc_builtin_macro]
+pub macro derive($item:item) {}
+#[rustc_builtin_macro]
+pub macro Copy {}
+#[rustc_builtin_macro]
+pub macro Clone {}
+"#,
     );
     assert_eq!(map.modules[map.root].scope.impls().len(), 2);
 }
@@ -712,17 +713,19 @@ fn builtin_derive_with_unresolved_attributes_fall_back() {
     cov_mark::check!(unresolved_attribute_fallback);
     let map = compute_crate_def_map(
         r#"
-        //- /main.rs crate:main deps:core
-        use core::Clone;
+//- /main.rs crate:main deps:core
+use core::{Clone, derive};
 
-        #[derive(Clone)]
-        #[unresolved]
-        struct Foo;
+#[derive(Clone)]
+#[unresolved]
+struct Foo;
 
-        //- /core.rs crate:core
-        #[rustc_builtin_macro]
-        pub macro Clone {}
-        "#,
+//- /core.rs crate:core
+#[rustc_builtin_macro]
+pub macro derive($item:item) {}
+#[rustc_builtin_macro]
+pub macro Clone {}
+"#,
     );
     assert_eq!(map.modules[map.root].scope.impls().len(), 1);
 }
@@ -799,6 +802,9 @@ fn resolves_derive_helper() {
     check(
         r#"
 //- /main.rs crate:main deps:proc
+#[rustc_builtin_macro]
+pub macro derive($item:item) {}
+
 #[derive(proc::Derive)]
 #[helper]
 #[unresolved]
@@ -811,6 +817,7 @@ fn derive() {}
         expect![[r#"
             crate
             S: t v
+            derive: m
         "#]],
     );
 }
diff --git a/crates/hir_expand/src/builtin_attr_macro.rs b/crates/hir_expand/src/builtin_attr_macro.rs
index ec587daf9ba..8da8c2ee4f2 100644
--- a/crates/hir_expand/src/builtin_attr_macro.rs
+++ b/crates/hir_expand/src/builtin_attr_macro.rs
@@ -36,6 +36,18 @@ macro_rules! register_builtin {
     };
 }
 
+impl BuiltinAttrExpander {
+    pub fn is_derive(self) -> bool {
+        matches!(self, BuiltinAttrExpander::Derive)
+    }
+    pub fn is_test(self) -> bool {
+        matches!(self, BuiltinAttrExpander::Test)
+    }
+    pub fn is_bench(self) -> bool {
+        matches!(self, BuiltinAttrExpander::Bench)
+    }
+}
+
 register_builtin! {
     (bench, Bench) => dummy_attr_expand,
     (cfg_accessible, CfgAccessible) => dummy_attr_expand,
@@ -46,16 +58,6 @@ register_builtin! {
     (test_case, TestCase) => dummy_attr_expand
 }
 
-pub fn is_builtin_test_or_bench_attr(makro: MacroDefId) -> bool {
-    match makro.kind {
-        MacroDefKind::BuiltInAttr(expander, ..) => {
-            BuiltinAttrExpander::find_by_name(&name!(test)) == Some(expander)
-                || BuiltinAttrExpander::find_by_name(&name!(bench)) == Some(expander)
-        }
-        _ => false,
-    }
-}
-
 pub fn find_builtin_attr(
     ident: &name::Name,
     krate: CrateId,
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index ac5d749b092..a61175f2733 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -974,61 +974,12 @@ fn infer_builtin_macros_env() {
 fn infer_derive_clone_simple() {
     check_types(
         r#"
-//- /main.rs crate:main deps:core
+//- minicore: derive, clone
 #[derive(Clone)]
 struct S;
 fn test() {
     S.clone();
 } //^^^^^^^^^ S
-
-//- /lib.rs crate:core
-pub mod prelude {
-    pub mod rust_2018 {
-        #[rustc_builtin_macro]
-        pub macro Clone {}
-        pub use crate::clone::Clone;
-    }
-}
-
-pub mod clone {
-    pub trait Clone {
-        fn clone(&self) -> Self;
-    }
-}
-"#,
-    );
-}
-
-#[test]
-fn infer_derive_clone_in_core() {
-    check_types(
-        r#"
-//- /lib.rs crate:core
-#[prelude_import]
-use prelude::rust_2018::*;
-
-pub mod prelude {
-    pub mod rust_2018 {
-        #[rustc_builtin_macro]
-        pub macro Clone {}
-        pub use crate::clone::Clone;
-    }
-}
-
-pub mod clone {
-    pub trait Clone {
-        fn clone(&self) -> Self;
-    }
-}
-
-#[derive(Clone)]
-pub struct S;
-
-//- /main.rs crate:main deps:core
-use core::S;
-fn test() {
-    S.clone();
-} //^^^^^^^^^ S
 "#,
     );
 }
@@ -1037,7 +988,7 @@ fn test() {
 fn infer_derive_clone_with_params() {
     check_types(
         r#"
-//- /main.rs crate:main deps:core
+//- minicore: clone, derive
 #[derive(Clone)]
 struct S;
 #[derive(Clone)]
@@ -1048,21 +999,6 @@ fn test() {
     x;
   //^ (Wrapper<S>, {unknown})
 }
-
-//- /lib.rs crate:core
-pub mod prelude {
-    pub mod rust_2018 {
-        #[rustc_builtin_macro]
-        pub macro Clone {}
-        pub use crate::clone::Clone;
-    }
-}
-
-pub mod clone {
-    pub trait Clone {
-        fn clone(&self) -> Self;
-    }
-}
 "#,
     );
 }
@@ -1072,7 +1008,7 @@ fn infer_custom_derive_simple() {
     // FIXME: this test current now do nothing
     check_types(
         r#"
-//- /main.rs crate:main
+//- minicore: derive
 use foo::Foo;
 
 #[derive(Foo)]
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index c389d895f28..57c078ef57d 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -367,9 +367,7 @@ fn main() {
         check(
             r#"
 //- proc_macros: identity
-
-#[rustc_builtin_macro]
-pub macro Clone {}
+//- minicore: clone, derive
 
 #[proc_macros::identity]
 #[derive(C$0lone)]
@@ -377,7 +375,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Clone
-                impl< >crate::clone::Clone for Foo< >{}
+                impl< >core::clone::Clone for Foo< >{}
 
             "#]],
         );
@@ -387,10 +385,7 @@ struct Foo {}
     fn macro_expand_derive2() {
         check(
             r#"
-#[rustc_builtin_macro]
-pub macro Clone {}
-#[rustc_builtin_macro]
-pub macro Copy {}
+//- minicore: copy, clone, derive
 
 #[derive(Cop$0y)]
 #[derive(Clone)]
@@ -398,7 +393,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Copy
-                impl< >crate::marker::Copy for Foo< >{}
+                impl< >core::marker::Copy for Foo< >{}
 
             "#]],
         );
@@ -408,19 +403,16 @@ struct Foo {}
     fn macro_expand_derive_multi() {
         check(
             r#"
-#[rustc_builtin_macro]
-pub macro Clone {}
-#[rustc_builtin_macro]
-pub macro Copy {}
+//- minicore: copy, clone, derive
 
 #[derive(Cop$0y, Clone)]
 struct Foo {}
 "#,
             expect![[r#"
                 Copy, Clone
-                impl< >crate::marker::Copy for Foo< >{}
+                impl< >core::marker::Copy for Foo< >{}
 
-                impl< >crate::clone::Clone for Foo< >{}
+                impl< >core::clone::Clone for Foo< >{}
 
             "#]],
         );
diff --git a/crates/rust-analyzer/tests/slow-tests/main.rs b/crates/rust-analyzer/tests/slow-tests/main.rs
index e5963bae743..9e555dc49e6 100644
--- a/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -805,6 +805,9 @@ bar = {path = "../bar"}
 
 //- /foo/src/main.rs
 use bar::Bar;
+
+#[rustc_builtin_macro]
+macro derive($item:item) {}
 trait Bar {
   fn bar();
 }
@@ -875,7 +878,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
     let res = server.send_request::<HoverRequest>(HoverParams {
         text_document_position_params: TextDocumentPositionParams::new(
             server.doc_id("foo/src/main.rs"),
-            Position::new(7, 9),
+            Position::new(10, 9),
         ),
         work_done_progress_params: Default::default(),
     });