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 814afdd16c..0013c2a256 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
@@ -1,833 +1,828 @@
//! Tests for `builtin_derive_macro.rs` from `hir_expand`.
-// FIXME: This file is commented out because due to the fast path for builtin derives,
-// the macros do not really get expanded, and we cannot check their expansion.
-// It's not removed because we still need to find some way to do that nevertheless.
-// Maybe going through the list of registered derive calls in the def map?
-
-// use expect_test::expect;
-
-// use crate::macro_expansion_tests::{check, check_errors};
-
-// #[test]
-// fn test_copy_expand_simple() {
-// check(
-// r#"
-// //- minicore: derive, copy
-// #[derive(Copy)]
-// struct Foo;
-// "#,
-// expect![[r#"
-// #[derive(Copy)]
-// struct Foo;
-
-// impl <> $crate::marker::Copy for Foo< > where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_copy_expand_in_core() {
-// check(
-// r#"
-// //- /lib.rs crate:core
-// #[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;
-
-// impl <> $crate::marker::Copy for Foo< > where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_copy_expand_with_type_params() {
-// check(
-// r#"
-// //- minicore: derive, copy
-// #[derive(Copy)]
-// struct Foo;
-// "#,
-// expect![[r#"
-// #[derive(Copy)]
-// struct Foo;
-
-// impl $crate::marker::Copy for Foo where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_copy_expand_with_lifetimes() {
-// // We currently just ignore lifetimes
-// check(
-// r#"
-// //- minicore: derive, copy
-// #[derive(Copy)]
-// struct Foo;
-// "#,
-// expect![[r#"
-// #[derive(Copy)]
-// struct Foo;
-
-// impl $crate::marker::Copy for Foo where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_clone_expand() {
-// check(
-// r#"
-// //- minicore: derive, clone
-// #[derive(Clone)]
-// enum Command {
-// Move { x: A, y: B },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// #[derive(Clone)]
-// enum Command {
-// Move { x: A, y: B },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl $crate::clone::Clone for Command where {
-// fn clone(&self ) -> Self {
-// match self {
-// Command::Move {
-// x: x, y: y,
-// }
-// =>Command::Move {
-// x: x.clone(), y: y.clone(),
-// }
-// , Command::Do(f0, )=>Command::Do(f0.clone(), ), Command::Jump=>Command::Jump,
-// }
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_clone_expand_with_associated_types() {
-// check(
-// r#"
-// //- minicore: derive, clone
-// trait Trait {
-// type InWc;
-// type InFieldQualified;
-// type InFieldShorthand;
-// type InGenericArg;
-// }
-// trait Marker {}
-// struct Vec(T);
-
-// #[derive(Clone)]
-// struct Foo
-// where
-// ::InWc: Marker,
-// {
-// qualified: ::InFieldQualified,
-// shorthand: T::InFieldShorthand,
-// generic: Vec,
-// }
-// "#,
-// expect![[r#"
-// trait Trait {
-// type InWc;
-// type InFieldQualified;
-// type InFieldShorthand;
-// type InGenericArg;
-// }
-// trait Marker {}
-// struct Vec(T);
-
-// #[derive(Clone)]
-// struct Foo
-// where
-// ::InWc: Marker,
-// {
-// qualified: ::InFieldQualified,
-// shorthand: T::InFieldShorthand,
-// generic: Vec,
-// }
-
-// impl $crate::clone::Clone for Foo where ::InWc: Marker, T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, {
-// fn clone(&self ) -> Self {
-// match self {
-// Foo {
-// qualified: qualified, shorthand: shorthand, generic: generic,
-// }
-// =>Foo {
-// qualified: qualified.clone(), shorthand: shorthand.clone(), generic: generic.clone(),
-// }
-// ,
-// }
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_clone_expand_with_const_generics() {
-// check(
-// r#"
-// //- minicore: derive, clone
-// #[derive(Clone)]
-// struct Foo(u32);
-// "#,
-// expect![[r#"
-// #[derive(Clone)]
-// struct Foo(u32);
-
-// impl $crate::clone::Clone for Foo where {
-// fn clone(&self ) -> Self {
-// match self {
-// Foo(f0, )=>Foo(f0.clone(), ),
-// }
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_default_expand() {
-// check(
-// r#"
-// //- minicore: derive, default
-// #[derive(Default)]
-// struct Foo {
-// field1: i32,
-// field2: (),
-// }
-// #[derive(Default)]
-// enum Bar {
-// Foo(u8),
-// #[default]
-// Bar,
-// }
-// "#,
-// expect![[r#"
-// #[derive(Default)]
-// struct Foo {
-// field1: i32,
-// field2: (),
-// }
-// #[derive(Default)]
-// enum Bar {
-// Foo(u8),
-// #[default]
-// Bar,
-// }
-
-// impl <> $crate::default::Default for Foo< > where {
-// fn default() -> Self {
-// Foo {
-// field1: $crate::default::Default::default(), field2: $crate::default::Default::default(),
-// }
-// }
-// }
-// impl <> $crate::default::Default for Bar< > where {
-// fn default() -> Self {
-// Bar::Bar
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_partial_eq_expand() {
-// check(
-// r#"
-// //- minicore: derive, eq
-// #[derive(PartialEq, Eq)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// #[derive(PartialEq, Eq)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl <> $crate::cmp::PartialEq for Command< > where {
-// fn eq(&self , other: &Self ) -> bool {
-// match (self , other) {
-// (Command::Move {
-// x: x_self, y: y_self,
-// }
-// , Command::Move {
-// x: x_other, y: y_other,
-// }
-// )=>x_self.eq(x_other) && y_self.eq(y_other), (Command::Do(f0_self, ), Command::Do(f0_other, ))=>f0_self.eq(f0_other), (Command::Jump, Command::Jump)=>true , _unused=>false
-// }
-// }
-// }
-// impl <> $crate::cmp::Eq for Command< > where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_partial_eq_expand_with_derive_const() {
-// // FIXME: actually expand with const
-// check(
-// r#"
-// //- minicore: derive, eq
-// #[derive_const(PartialEq, Eq)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// #[derive_const(PartialEq, Eq)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl <> $crate::cmp::PartialEq for Command< > where {
-// fn eq(&self , other: &Self ) -> bool {
-// match (self , other) {
-// (Command::Move {
-// x: x_self, y: y_self,
-// }
-// , Command::Move {
-// x: x_other, y: y_other,
-// }
-// )=>x_self.eq(x_other) && y_self.eq(y_other), (Command::Do(f0_self, ), Command::Do(f0_other, ))=>f0_self.eq(f0_other), (Command::Jump, Command::Jump)=>true , _unused=>false
-// }
-// }
-// }
-// impl <> $crate::cmp::Eq for Command< > where {}"#]],
-// );
-// }
-
-// #[test]
-// fn test_partial_ord_expand() {
-// check(
-// r#"
-// //- minicore: derive, ord
-// #[derive(PartialOrd, Ord)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// #[derive(PartialOrd, Ord)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl <> $crate::cmp::PartialOrd for Command< > where {
-// fn partial_cmp(&self , other: &Self ) -> $crate::option::Option<$crate::cmp::Ordering> {
-// match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
-// match (self , other) {
-// (Command::Move {
-// x: x_self, y: y_self,
-// }
-// , Command::Move {
-// x: x_other, y: y_other,
-// }
-// )=>match x_self.partial_cmp(&x_other) {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
-// match y_self.partial_cmp(&y_other) {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)
-// }
-// c=>return c,
-// }
-// }
-// c=>return c,
-// }
-// , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.partial_cmp(&f0_other) {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
-// $crate::option::Option::Some($crate::cmp::Ordering::Equal)
-// }
-// c=>return c,
-// }
-// , (Command::Jump, Command::Jump)=>$crate::option::Option::Some($crate::cmp::Ordering::Equal), _unused=>$crate::option::Option::Some($crate::cmp::Ordering::Equal)
-// }
-// }
-// c=>return c,
-// }
-// }
-// }
-// impl <> $crate::cmp::Ord for Command< > where {
-// fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering {
-// match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) {
-// $crate::cmp::Ordering::Equal=> {
-// match (self , other) {
-// (Command::Move {
-// x: x_self, y: y_self,
-// }
-// , Command::Move {
-// x: x_other, y: y_other,
-// }
-// )=>match x_self.cmp(&x_other) {
-// $crate::cmp::Ordering::Equal=> {
-// match y_self.cmp(&y_other) {
-// $crate::cmp::Ordering::Equal=> {
-// $crate::cmp::Ordering::Equal
-// }
-// c=>return c,
-// }
-// }
-// c=>return c,
-// }
-// , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.cmp(&f0_other) {
-// $crate::cmp::Ordering::Equal=> {
-// $crate::cmp::Ordering::Equal
-// }
-// c=>return c,
-// }
-// , (Command::Jump, Command::Jump)=>$crate::cmp::Ordering::Equal, _unused=>$crate::cmp::Ordering::Equal
-// }
-// }
-// c=>return c,
-// }
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_hash_expand() {
-// check(
-// r#"
-// //- minicore: derive, hash
-// use core::hash::Hash;
-
-// #[derive(Hash)]
-// struct Foo {
-// x: i32,
-// y: u64,
-// z: (i32, u64),
-// }
-// "#,
-// expect![[r#"
-// use core::hash::Hash;
-
-// #[derive(Hash)]
-// struct Foo {
-// x: i32,
-// y: u64,
-// z: (i32, u64),
-// }
-
-// impl <> $crate::hash::Hash for Foo< > where {
-// fn hash(&self , ra_expand_state: &mut H) {
-// match self {
-// Foo {
-// x: x, y: y, z: z,
-// }
-// => {
-// x.hash(ra_expand_state);
-// y.hash(ra_expand_state);
-// z.hash(ra_expand_state);
-// }
-// ,
-// }
-// }
-// }"#]],
-// );
-// check(
-// r#"
-// //- minicore: derive, hash
-// use core::hash::Hash;
-
-// #[derive(Hash)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// use core::hash::Hash;
-
-// #[derive(Hash)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl <> $crate::hash::Hash for Command< > where {
-// fn hash(&self , ra_expand_state: &mut H) {
-// $crate::mem::discriminant(self ).hash(ra_expand_state);
-// match self {
-// Command::Move {
-// x: x, y: y,
-// }
-// => {
-// x.hash(ra_expand_state);
-// y.hash(ra_expand_state);
-// }
-// , Command::Do(f0, )=> {
-// f0.hash(ra_expand_state);
-// }
-// , Command::Jump=> {}
-// ,
-// }
-// }
-// }"#]],
-// );
-// }
-
-// #[test]
-// fn test_debug_expand() {
-// check(
-// r#"
-// //- minicore: derive, fmt
-// use core::fmt::Debug;
-
-// #[derive(Debug)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-// "#,
-// expect![[r#"
-// use core::fmt::Debug;
-
-// #[derive(Debug)]
-// enum Command {
-// Move { x: i32, y: i32 },
-// Do(&'static str),
-// Jump,
-// }
-
-// impl <> $crate::fmt::Debug for Command< > where {
-// fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
-// match self {
-// Command::Move {
-// x: x, y: y,
-// }
-// =>f.debug_struct("Move").field("x", &x).field("y", &y).finish(), Command::Do(f0, )=>f.debug_tuple("Do").field(&f0).finish(), Command::Jump=>f.write_str("Jump"),
-// }
-// }
-// }"#]],
-// );
-// }
-// #[test]
-// fn test_debug_expand_with_cfg() {
-// check(
-// r#"
-// //- minicore: derive, fmt
-// use core::fmt::Debug;
-
-// #[derive(Debug)]
-// struct HideAndShow {
-// #[cfg(never)]
-// always_hide: u32,
-// #[cfg(not(never))]
-// always_show: u32,
-// }
-// #[derive(Debug)]
-// enum HideAndShowEnum {
-// #[cfg(never)]
-// AlwaysHide,
-// #[cfg(not(never))]
-// AlwaysShow{
-// #[cfg(never)]
-// always_hide: u32,
-// #[cfg(not(never))]
-// always_show: u32,
-// }
-// }
-// "#,
-// expect![[r#"
-// use core::fmt::Debug;
-
-// #[derive(Debug)]
-// struct HideAndShow {
-// #[cfg(never)]
-// always_hide: u32,
-// #[cfg(not(never))]
-// always_show: u32,
-// }
-// #[derive(Debug)]
-// enum HideAndShowEnum {
-// #[cfg(never)]
-// AlwaysHide,
-// #[cfg(not(never))]
-// AlwaysShow{
-// #[cfg(never)]
-// always_hide: u32,
-// #[cfg(not(never))]
-// always_show: u32,
-// }
-// }
-
-// impl <> $crate::fmt::Debug for HideAndShow< > where {
-// fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
-// match self {
-// HideAndShow {
-// always_show: always_show,
-// }
-// =>f.debug_struct("HideAndShow").field("always_show", &always_show).finish()
-// }
-// }
-// }
-// impl <> $crate::fmt::Debug for HideAndShowEnum< > where {
-// fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
-// match self {
-// HideAndShowEnum::AlwaysShow {
-// always_show: always_show,
-// }
-// =>f.debug_struct("AlwaysShow").field("always_show", &always_show).finish(),
-// }
-// }
-// }"#]],
-// );
-// }
-// #[test]
-// fn test_default_expand_with_cfg() {
-// check(
-// r#"
-// //- minicore: derive, default
-// #[derive(Default)]
-// struct Foo {
-// field1: i32,
-// #[cfg(never)]
-// field2: (),
-// #[cfg(feature = "never")]
-// field3: (),
-// #[cfg(not(feature = "never"))]
-// field4: (),
-// }
-// #[derive(Default)]
-// enum Bar {
-// Foo,
-// #[cfg_attr(not(never), default)]
-// Bar,
-// }
-// "#,
-// expect![[r##"
-// #[derive(Default)]
-// struct Foo {
-// field1: i32,
-// #[cfg(never)]
-// field2: (),
-// #[cfg(feature = "never")]
-// field3: (),
-// #[cfg(not(feature = "never"))]
-// field4: (),
-// }
-// #[derive(Default)]
-// enum Bar {
-// Foo,
-// #[cfg_attr(not(never), default)]
-// Bar,
-// }
-
-// impl <> $crate::default::Default for Foo< > where {
-// fn default() -> Self {
-// Foo {
-// field1: $crate::default::Default::default(), field4: $crate::default::Default::default(),
-// }
-// }
-// }
-// impl <> $crate::default::Default for Bar< > where {
-// fn default() -> Self {
-// Bar::Bar
-// }
-// }"##]],
-// );
-// }
-
-// #[test]
-// fn coerce_pointee_expansion() {
-// check(
-// r#"
-// //- minicore: coerce_pointee
-
-// use core::marker::CoercePointee;
-
-// pub trait Trait {}
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// pub struct Foo<'a, T: ?Sized + Trait, #[pointee] U: ?Sized, const N: u32>(T)
-// where
-// U: Trait + ToString;"#,
-// expect![[r#"
-
-// use core::marker::CoercePointee;
-
-// pub trait Trait {}
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// pub struct Foo<'a, T: ?Sized + Trait, #[pointee] U: ?Sized, const N: u32>(T)
-// where
-// U: Trait + ToString;
-// impl $crate::ops::DispatchFromDyn> for Foo where U: Trait +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait, U:?Sized, {}
-// impl $crate::ops::CoerceUnsized> for Foo where U: Trait +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait, U:?Sized, {}"#]],
-// );
-// }
-
-// #[test]
-// fn coerce_pointee_errors() {
-// check_errors(
-// r#"
-// //- minicore: coerce_pointee
-
-// use core::marker::CoercePointee;
-
-// #[derive(CoercePointee)]
-// enum Enum {}
-
-// #[derive(CoercePointee)]
-// struct Struct1;
-
-// #[derive(CoercePointee)]
-// struct Struct2();
-
-// #[derive(CoercePointee)]
-// struct Struct3 {}
-
-// #[derive(CoercePointee)]
-// struct Struct4(T);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct5(i32);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct6<#[pointee] T: ?Sized, #[pointee] U: ?Sized>(T, U);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct7(T, U);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct8<#[pointee] T, U: ?Sized>(T);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct9(T);
-
-// #[derive(CoercePointee)]
-// #[repr(transparent)]
-// struct Struct9<#[pointee] T, U>(T) where T: ?Sized;
-// "#,
-// expect![[r#"
-// 35..72: `CoercePointee` can only be derived on `struct`s
-// 74..114: `CoercePointee` can only be derived on `struct`s with at least one field
-// 116..158: `CoercePointee` can only be derived on `struct`s with at least one field
-// 160..202: `CoercePointee` can only be derived on `struct`s with at least one field
-// 204..258: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
-// 260..326: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
-// 328..439: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
-// 441..530: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
-// 532..621: `derive(CoercePointee)` requires `T` to be marked `?Sized`
-// 623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]],
-// );
-// }
-
-// #[test]
-// fn union_derive() {
-// check_errors(
-// r#"
-// //- minicore: clone, copy, default, fmt, hash, ord, eq, derive
-
-// #[derive(Copy)]
-// union Foo1 { _v: () }
-// #[derive(Clone)]
-// union Foo2 { _v: () }
-// #[derive(Default)]
-// union Foo3 { _v: () }
-// #[derive(Debug)]
-// union Foo4 { _v: () }
-// #[derive(Hash)]
-// union Foo5 { _v: () }
-// #[derive(Ord)]
-// union Foo6 { _v: () }
-// #[derive(PartialOrd)]
-// union Foo7 { _v: () }
-// #[derive(Eq)]
-// union Foo8 { _v: () }
-// #[derive(PartialEq)]
-// union Foo9 { _v: () }
-// "#,
-// expect![[r#"
-// 78..118: this trait cannot be derived for unions
-// 119..157: this trait cannot be derived for unions
-// 158..195: this trait cannot be derived for unions
-// 196..232: this trait cannot be derived for unions
-// 233..276: this trait cannot be derived for unions
-// 313..355: this trait cannot be derived for unions"#]],
-// );
-// }
-
-// #[test]
-// fn default_enum_without_default_attr() {
-// check_errors(
-// r#"
-// //- minicore: default, derive
-
-// #[derive(Default)]
-// enum Foo {
-// Bar,
-// }
-// "#,
-// expect!["1..41: `#[derive(Default)]` on enum with no `#[default]`"],
-// );
-// }
-
-// #[test]
-// fn generic_enum_default() {
-// check(
-// r#"
-// //- minicore: default, derive
-
-// #[derive(Default)]
-// enum Foo {
-// Bar(T),
-// #[default]
-// Baz,
-// }
-// "#,
-// expect![[r#"
-
-// #[derive(Default)]
-// enum Foo {
-// Bar(T),
-// #[default]
-// Baz,
-// }
-
-// impl $crate::default::Default for Foo where {
-// fn default() -> Self {
-// Foo::Baz
-// }
-// }"#]],
-// );
-// }
+use expect_test::expect;
+
+use crate::macro_expansion_tests::{check, check_errors};
+
+#[test]
+fn test_copy_expand_simple() {
+ check(
+ r#"
+//- minicore: derive, copy
+#[derive(Copy)]
+struct Foo;
+"#,
+ expect![[r#"
+#[derive(Copy)]
+struct Foo;
+
+impl <> $crate::marker::Copy for Foo< > where {}"#]],
+ );
+}
+
+#[test]
+fn test_copy_expand_in_core() {
+ check(
+ r#"
+//- /lib.rs crate:core
+#[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;
+
+impl <> $crate::marker::Copy for Foo< > where {}"#]],
+ );
+}
+
+#[test]
+fn test_copy_expand_with_type_params() {
+ check(
+ r#"
+//- minicore: derive, copy
+#[derive(Copy)]
+struct Foo;
+"#,
+ expect![[r#"
+#[derive(Copy)]
+struct Foo;
+
+impl $crate::marker::Copy for Foo where {}"#]],
+ );
+}
+
+#[test]
+fn test_copy_expand_with_lifetimes() {
+ // We currently just ignore lifetimes
+ check(
+ r#"
+//- minicore: derive, copy
+#[derive(Copy)]
+struct Foo;
+"#,
+ expect![[r#"
+#[derive(Copy)]
+struct Foo;
+
+impl $crate::marker::Copy for Foo where {}"#]],
+ );
+}
+
+#[test]
+fn test_clone_expand() {
+ check(
+ r#"
+//- minicore: derive, clone
+#[derive(Clone)]
+enum Command {
+ Move { x: A, y: B },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+#[derive(Clone)]
+enum Command {
+ Move { x: A, y: B },
+ Do(&'static str),
+ Jump,
+}
+
+impl $crate::clone::Clone for Command where {
+ fn clone(&self ) -> Self {
+ match self {
+ Command::Move {
+ x: x, y: y,
+ }
+ =>Command::Move {
+ x: x.clone(), y: y.clone(),
+ }
+ , Command::Do(f0, )=>Command::Do(f0.clone(), ), Command::Jump=>Command::Jump,
+ }
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_clone_expand_with_associated_types() {
+ check(
+ r#"
+//- minicore: derive, clone
+trait Trait {
+ type InWc;
+ type InFieldQualified;
+ type InFieldShorthand;
+ type InGenericArg;
+}
+trait Marker {}
+struct Vec(T);
+
+#[derive(Clone)]
+struct Foo
+where
+ ::InWc: Marker,
+{
+ qualified: ::InFieldQualified,
+ shorthand: T::InFieldShorthand,
+ generic: Vec,
+}
+"#,
+ expect![[r#"
+trait Trait {
+ type InWc;
+ type InFieldQualified;
+ type InFieldShorthand;
+ type InGenericArg;
+}
+trait Marker {}
+struct Vec(T);
+
+#[derive(Clone)]
+struct Foo
+where
+ ::InWc: Marker,
+{
+ qualified: ::InFieldQualified,
+ shorthand: T::InFieldShorthand,
+ generic: Vec,
+}
+
+impl $crate::clone::Clone for Foo where ::InWc: Marker, T: Trait, T::InFieldShorthand: $crate::clone::Clone, T::InGenericArg: $crate::clone::Clone, {
+ fn clone(&self ) -> Self {
+ match self {
+ Foo {
+ qualified: qualified, shorthand: shorthand, generic: generic,
+ }
+ =>Foo {
+ qualified: qualified.clone(), shorthand: shorthand.clone(), generic: generic.clone(),
+ }
+ ,
+ }
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_clone_expand_with_const_generics() {
+ check(
+ r#"
+//- minicore: derive, clone
+#[derive(Clone)]
+struct Foo(u32);
+"#,
+ expect![[r#"
+#[derive(Clone)]
+struct Foo(u32);
+
+impl $crate::clone::Clone for Foo where {
+ fn clone(&self ) -> Self {
+ match self {
+ Foo(f0, )=>Foo(f0.clone(), ),
+ }
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_default_expand() {
+ check(
+ r#"
+//- minicore: derive, default
+#[derive(Default)]
+struct Foo {
+ field1: i32,
+ field2: (),
+}
+#[derive(Default)]
+enum Bar {
+ Foo(u8),
+ #[default]
+ Bar,
+}
+"#,
+ expect![[r#"
+#[derive(Default)]
+struct Foo {
+ field1: i32,
+ field2: (),
+}
+#[derive(Default)]
+enum Bar {
+ Foo(u8),
+ #[default]
+ Bar,
+}
+
+impl <> $crate::default::Default for Foo< > where {
+ fn default() -> Self {
+ Foo {
+ field1: $crate::default::Default::default(), field2: $crate::default::Default::default(),
+ }
+ }
+}
+impl <> $crate::default::Default for Bar< > where {
+ fn default() -> Self {
+ Bar::Bar
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_partial_eq_expand() {
+ check(
+ r#"
+//- minicore: derive, eq
+#[derive(PartialEq, Eq)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+#[derive(PartialEq, Eq)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+
+impl <> $crate::cmp::PartialEq for Command< > where {
+ fn eq(&self , other: &Self ) -> bool {
+ match (self , other) {
+ (Command::Move {
+ x: x_self, y: y_self,
+ }
+ , Command::Move {
+ x: x_other, y: y_other,
+ }
+ )=>x_self.eq(x_other) && y_self.eq(y_other), (Command::Do(f0_self, ), Command::Do(f0_other, ))=>f0_self.eq(f0_other), (Command::Jump, Command::Jump)=>true , _unused=>false
+ }
+ }
+}
+impl <> $crate::cmp::Eq for Command< > where {}"#]],
+ );
+}
+
+#[test]
+fn test_partial_eq_expand_with_derive_const() {
+ // FIXME: actually expand with const
+ check(
+ r#"
+//- minicore: derive, eq
+#[derive_const(PartialEq, Eq)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+#[derive_const(PartialEq, Eq)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+
+impl <> $crate::cmp::PartialEq for Command< > where {
+ fn eq(&self , other: &Self ) -> bool {
+ match (self , other) {
+ (Command::Move {
+ x: x_self, y: y_self,
+ }
+ , Command::Move {
+ x: x_other, y: y_other,
+ }
+ )=>x_self.eq(x_other) && y_self.eq(y_other), (Command::Do(f0_self, ), Command::Do(f0_other, ))=>f0_self.eq(f0_other), (Command::Jump, Command::Jump)=>true , _unused=>false
+ }
+ }
+}
+impl <> $crate::cmp::Eq for Command< > where {}"#]],
+ );
+}
+
+#[test]
+fn test_partial_ord_expand() {
+ check(
+ r#"
+//- minicore: derive, ord
+#[derive(PartialOrd, Ord)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+#[derive(PartialOrd, Ord)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+
+impl <> $crate::cmp::PartialOrd for Command< > where {
+ fn partial_cmp(&self , other: &Self ) -> $crate::option::Option<$crate::cmp::Ordering> {
+ match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
+ match (self , other) {
+ (Command::Move {
+ x: x_self, y: y_self,
+ }
+ , Command::Move {
+ x: x_other, y: y_other,
+ }
+ )=>match x_self.partial_cmp(&x_other) {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
+ match y_self.partial_cmp(&y_other) {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)
+ }
+ c=>return c,
+ }
+ }
+ c=>return c,
+ }
+ , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.partial_cmp(&f0_other) {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
+ $crate::option::Option::Some($crate::cmp::Ordering::Equal)
+ }
+ c=>return c,
+ }
+ , (Command::Jump, Command::Jump)=>$crate::option::Option::Some($crate::cmp::Ordering::Equal), _unused=>$crate::option::Option::Some($crate::cmp::Ordering::Equal)
+ }
+ }
+ c=>return c,
+ }
+ }
+}
+impl <> $crate::cmp::Ord for Command< > where {
+ fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering {
+ match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) {
+ $crate::cmp::Ordering::Equal=> {
+ match (self , other) {
+ (Command::Move {
+ x: x_self, y: y_self,
+ }
+ , Command::Move {
+ x: x_other, y: y_other,
+ }
+ )=>match x_self.cmp(&x_other) {
+ $crate::cmp::Ordering::Equal=> {
+ match y_self.cmp(&y_other) {
+ $crate::cmp::Ordering::Equal=> {
+ $crate::cmp::Ordering::Equal
+ }
+ c=>return c,
+ }
+ }
+ c=>return c,
+ }
+ , (Command::Do(f0_self, ), Command::Do(f0_other, ))=>match f0_self.cmp(&f0_other) {
+ $crate::cmp::Ordering::Equal=> {
+ $crate::cmp::Ordering::Equal
+ }
+ c=>return c,
+ }
+ , (Command::Jump, Command::Jump)=>$crate::cmp::Ordering::Equal, _unused=>$crate::cmp::Ordering::Equal
+ }
+ }
+ c=>return c,
+ }
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_hash_expand() {
+ check(
+ r#"
+//- minicore: derive, hash
+use core::hash::Hash;
+
+#[derive(Hash)]
+struct Foo {
+ x: i32,
+ y: u64,
+ z: (i32, u64),
+}
+"#,
+ expect![[r#"
+use core::hash::Hash;
+
+#[derive(Hash)]
+struct Foo {
+ x: i32,
+ y: u64,
+ z: (i32, u64),
+}
+
+impl <> $crate::hash::Hash for Foo< > where {
+ fn hash(&self , ra_expand_state: &mut H) {
+ match self {
+ Foo {
+ x: x, y: y, z: z,
+ }
+ => {
+ x.hash(ra_expand_state);
+ y.hash(ra_expand_state);
+ z.hash(ra_expand_state);
+ }
+ ,
+ }
+ }
+}"#]],
+ );
+ check(
+ r#"
+//- minicore: derive, hash
+use core::hash::Hash;
+
+#[derive(Hash)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+use core::hash::Hash;
+
+#[derive(Hash)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+
+impl <> $crate::hash::Hash for Command< > where {
+ fn hash(&self , ra_expand_state: &mut H) {
+ $crate::mem::discriminant(self ).hash(ra_expand_state);
+ match self {
+ Command::Move {
+ x: x, y: y,
+ }
+ => {
+ x.hash(ra_expand_state);
+ y.hash(ra_expand_state);
+ }
+ , Command::Do(f0, )=> {
+ f0.hash(ra_expand_state);
+ }
+ , Command::Jump=> {}
+ ,
+ }
+ }
+}"#]],
+ );
+}
+
+#[test]
+fn test_debug_expand() {
+ check(
+ r#"
+//- minicore: derive, fmt
+use core::fmt::Debug;
+
+#[derive(Debug)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+"#,
+ expect![[r#"
+use core::fmt::Debug;
+
+#[derive(Debug)]
+enum Command {
+ Move { x: i32, y: i32 },
+ Do(&'static str),
+ Jump,
+}
+
+impl <> $crate::fmt::Debug for Command< > where {
+ fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
+ match self {
+ Command::Move {
+ x: x, y: y,
+ }
+ =>f.debug_struct("Move").field("x", &x).field("y", &y).finish(), Command::Do(f0, )=>f.debug_tuple("Do").field(&f0).finish(), Command::Jump=>f.write_str("Jump"),
+ }
+ }
+}"#]],
+ );
+}
+#[test]
+fn test_debug_expand_with_cfg() {
+ check(
+ r#"
+ //- minicore: derive, fmt
+ use core::fmt::Debug;
+
+ #[derive(Debug)]
+ struct HideAndShow {
+ #[cfg(never)]
+ always_hide: u32,
+ #[cfg(not(never))]
+ always_show: u32,
+ }
+ #[derive(Debug)]
+ enum HideAndShowEnum {
+ #[cfg(never)]
+ AlwaysHide,
+ #[cfg(not(never))]
+ AlwaysShow{
+ #[cfg(never)]
+ always_hide: u32,
+ #[cfg(not(never))]
+ always_show: u32,
+ }
+ }
+ "#,
+ expect![[r#"
+use core::fmt::Debug;
+
+#[derive(Debug)]
+struct HideAndShow {
+ #[cfg(never)]
+ always_hide: u32,
+ #[cfg(not(never))]
+ always_show: u32,
+}
+#[derive(Debug)]
+enum HideAndShowEnum {
+ #[cfg(never)]
+ AlwaysHide,
+ #[cfg(not(never))]
+ AlwaysShow{
+ #[cfg(never)]
+ always_hide: u32,
+ #[cfg(not(never))]
+ always_show: u32,
+ }
+}
+
+impl <> $crate::fmt::Debug for HideAndShow< > where {
+ fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
+ match self {
+ HideAndShow {
+ always_show: always_show,
+ }
+ =>f.debug_struct("HideAndShow").field("always_show", &always_show).finish()
+ }
+ }
+}
+impl <> $crate::fmt::Debug for HideAndShowEnum< > where {
+ fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
+ match self {
+ HideAndShowEnum::AlwaysShow {
+ always_show: always_show,
+ }
+ =>f.debug_struct("AlwaysShow").field("always_show", &always_show).finish(),
+ }
+ }
+}"#]],
+ );
+}
+#[test]
+fn test_default_expand_with_cfg() {
+ check(
+ r#"
+//- minicore: derive, default
+#[derive(Default)]
+struct Foo {
+ field1: i32,
+ #[cfg(never)]
+ field2: (),
+ #[cfg(feature = "never")]
+ field3: (),
+ #[cfg(not(feature = "never"))]
+ field4: (),
+}
+#[derive(Default)]
+enum Bar {
+ Foo,
+ #[cfg_attr(not(never), default)]
+ Bar,
+}
+"#,
+ expect![[r##"
+#[derive(Default)]
+struct Foo {
+ field1: i32,
+ #[cfg(never)]
+ field2: (),
+ #[cfg(feature = "never")]
+ field3: (),
+ #[cfg(not(feature = "never"))]
+ field4: (),
+}
+#[derive(Default)]
+enum Bar {
+ Foo,
+ #[cfg_attr(not(never), default)]
+ Bar,
+}
+
+impl <> $crate::default::Default for Foo< > where {
+ fn default() -> Self {
+ Foo {
+ field1: $crate::default::Default::default(), field4: $crate::default::Default::default(),
+ }
+ }
+}
+impl <> $crate::default::Default for Bar< > where {
+ fn default() -> Self {
+ Bar::Bar
+ }
+}"##]],
+ );
+}
+
+#[test]
+fn coerce_pointee_expansion() {
+ check(
+ r#"
+//- minicore: coerce_pointee
+
+use core::marker::CoercePointee;
+
+pub trait Trait {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+pub struct Foo<'a, T: ?Sized + Trait, #[pointee] U: ?Sized, const N: u32>(T)
+where
+ U: Trait + ToString;"#,
+ expect![[r#"
+
+use core::marker::CoercePointee;
+
+pub trait Trait {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+pub struct Foo<'a, T: ?Sized + Trait, #[pointee] U: ?Sized, const N: u32>(T)
+where
+ U: Trait + ToString;
+impl $crate::ops::DispatchFromDyn> for Foo where U: Trait +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait, U:?Sized, {}
+impl $crate::ops::CoerceUnsized> for Foo where U: Trait +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait, U:?Sized, {}"#]],
+ );
+}
+
+#[test]
+fn coerce_pointee_errors() {
+ check_errors(
+ r#"
+//- minicore: coerce_pointee
+
+use core::marker::CoercePointee;
+
+#[derive(CoercePointee)]
+enum Enum {}
+
+#[derive(CoercePointee)]
+struct Struct1;
+
+#[derive(CoercePointee)]
+struct Struct2();
+
+#[derive(CoercePointee)]
+struct Struct3 {}
+
+#[derive(CoercePointee)]
+struct Struct4(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct5(i32);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct6<#[pointee] T: ?Sized, #[pointee] U: ?Sized>(T, U);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct7(T, U);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct8<#[pointee] T, U: ?Sized>(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct9(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct9<#[pointee] T, U>(T) where T: ?Sized;
+"#,
+ expect![[r#"
+ 35..72: `CoercePointee` can only be derived on `struct`s
+ 74..114: `CoercePointee` can only be derived on `struct`s with at least one field
+ 116..158: `CoercePointee` can only be derived on `struct`s with at least one field
+ 160..202: `CoercePointee` can only be derived on `struct`s with at least one field
+ 204..258: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
+ 260..326: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
+ 328..439: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
+ 441..530: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
+ 532..621: `derive(CoercePointee)` requires `T` to be marked `?Sized`
+ 623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]],
+ );
+}
+
+#[test]
+fn union_derive() {
+ check_errors(
+ r#"
+//- minicore: clone, copy, default, fmt, hash, ord, eq, derive
+
+#[derive(Copy)]
+union Foo1 { _v: () }
+#[derive(Clone)]
+union Foo2 { _v: () }
+#[derive(Default)]
+union Foo3 { _v: () }
+#[derive(Debug)]
+union Foo4 { _v: () }
+#[derive(Hash)]
+union Foo5 { _v: () }
+#[derive(Ord)]
+union Foo6 { _v: () }
+#[derive(PartialOrd)]
+union Foo7 { _v: () }
+#[derive(Eq)]
+union Foo8 { _v: () }
+#[derive(PartialEq)]
+union Foo9 { _v: () }
+ "#,
+ expect![[r#"
+ 78..118: this trait cannot be derived for unions
+ 119..157: this trait cannot be derived for unions
+ 158..195: this trait cannot be derived for unions
+ 196..232: this trait cannot be derived for unions
+ 233..276: this trait cannot be derived for unions
+ 313..355: this trait cannot be derived for unions"#]],
+ );
+}
+
+#[test]
+fn default_enum_without_default_attr() {
+ check_errors(
+ r#"
+//- minicore: default, derive
+
+#[derive(Default)]
+enum Foo {
+ Bar,
+}
+ "#,
+ expect!["1..41: `#[derive(Default)]` on enum with no `#[default]`"],
+ );
+}
+
+#[test]
+fn generic_enum_default() {
+ check(
+ r#"
+//- minicore: default, derive
+
+#[derive(Default)]
+enum Foo {
+ Bar(T),
+ #[default]
+ Baz,
+}
+"#,
+ expect![[r#"
+
+#[derive(Default)]
+enum Foo {
+ Bar(T),
+ #[default]
+ Baz,
+}
+
+impl $crate::default::Default for Foo where {
+ fn default() -> Self {
+ Foo::Baz
+ }
+}"#]],
+ );
+}
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index 59bd9474a9..fa4409e117 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -53,6 +53,8 @@ use crate::{
#[track_caller]
fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
+ crate::nameres::ENABLE_BUILTIN_DERIVE_FAST_PATH.set(false);
+
let db = TestDB::with_files(ra_fixture);
let krate = db.fetch_test_crate();
let def_map = crate_def_map(&db, krate);
@@ -80,10 +82,15 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect)
.sorted_unstable_by_key(|(range, _)| range.start())
.format_with("\n", |(range, err), format| format(&format_args!("{range:?}: {err}")))
.to_string();
+
+ crate::nameres::ENABLE_BUILTIN_DERIVE_FAST_PATH.set(true);
+
expect.assert_eq(&errors);
}
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) {
+ crate::nameres::ENABLE_BUILTIN_DERIVE_FAST_PATH.set(false);
+
let extra_proc_macros = vec![(
r#"
#[proc_macro_attribute]
@@ -246,6 +253,8 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
}
}
+ crate::nameres::ENABLE_BUILTIN_DERIVE_FAST_PATH.set(true);
+
expect.indent(false);
expect.assert_eq(&expanded_text);
}
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 3f29619bcb..59ca38c7c0 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -87,6 +87,25 @@ use crate::{
pub use self::path_resolution::ResolvePathResultPrefixInfo;
+#[cfg(test)]
+thread_local! {
+ /// HACK: In order to test builtin derive expansion, we gate their fast path with this atomic when cfg(test).
+ pub(crate) static ENABLE_BUILTIN_DERIVE_FAST_PATH: std::cell::Cell =
+ const { std::cell::Cell::new(true) };
+}
+
+#[inline]
+#[cfg(test)]
+fn enable_builtin_derive_fast_path() -> bool {
+ ENABLE_BUILTIN_DERIVE_FAST_PATH.get()
+}
+
+#[inline(always)]
+#[cfg(not(test))]
+fn enable_builtin_derive_fast_path() -> bool {
+ true
+}
+
const PREDEFINED_TOOLS: &[SmolStr] = &[
SmolStr::new_static("clippy"),
SmolStr::new_static("rustfmt"),
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 8694ebe4e4..a7f687a316 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -1526,8 +1526,9 @@ impl<'db> DefCollector<'db> {
}
}
- if let MacroDefKind::BuiltInDerive(_, builtin_derive) =
- def_id.kind
+ if super::enable_builtin_derive_fast_path()
+ && let MacroDefKind::BuiltInDerive(_, builtin_derive) =
+ def_id.kind
{
self.deferred_builtin_derives
.entry(ast_id.ast_id.upcast())