@@ -85,6 +85,17 @@ fn contains_trait_object(ty: Ty<'_>) -> bool {
85
85
}
86
86
}
87
87
88
+ fn determine_derive_macro ( cx : & LateContext < ' _ > , is_const : bool ) -> Option < & ' static str > {
89
+ if is_const {
90
+ if !cx. tcx . features ( ) . enabled ( sym:: derive_const) {
91
+ return None ;
92
+ }
93
+ return Some ( "derive_const" ) ;
94
+ }
95
+ Some ( "derive" )
96
+ }
97
+
98
+ #[ expect( clippy:: too_many_arguments) ]
88
99
fn check_struct < ' tcx > (
89
100
cx : & LateContext < ' tcx > ,
90
101
item : & ' tcx Item < ' _ > ,
@@ -93,6 +104,7 @@ fn check_struct<'tcx>(
93
104
adt_def : AdtDef < ' _ > ,
94
105
ty_args : GenericArgsRef < ' _ > ,
95
106
typeck_results : & ' tcx TypeckResults < ' tcx > ,
107
+ is_const : bool ,
96
108
) {
97
109
if let TyKind :: Path ( QPath :: Resolved ( _, p) ) = self_ty. kind
98
110
&& let Some ( PathSegment { args, .. } ) = p. segments . last ( )
@@ -128,11 +140,15 @@ fn check_struct<'tcx>(
128
140
_ => false ,
129
141
} ;
130
142
143
+ let Some ( derive_snippet) = determine_derive_macro ( cx, is_const) else {
144
+ return ;
145
+ } ;
146
+
131
147
if should_emit {
132
148
let struct_span = cx. tcx . def_span ( adt_def. did ( ) ) ;
133
149
let suggestions = vec ! [
134
150
( item. span, String :: new( ) ) , // Remove the manual implementation
135
- ( struct_span. shrink_to_lo( ) , "#[derive (Default)]\n " . to_string ( ) ) , // Add the derive attribute
151
+ ( struct_span. shrink_to_lo( ) , format! ( "#[{derive_snippet} (Default)]\n " ) ) , // Add the derive attribute
136
152
] ;
137
153
138
154
span_lint_and_then ( cx, DERIVABLE_IMPLS , item. span , "this `impl` can be derived" , |diag| {
@@ -145,7 +161,13 @@ fn check_struct<'tcx>(
145
161
}
146
162
}
147
163
148
- fn check_enum < ' tcx > ( cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > , func_expr : & Expr < ' _ > , adt_def : AdtDef < ' _ > ) {
164
+ fn check_enum < ' tcx > (
165
+ cx : & LateContext < ' tcx > ,
166
+ item : & ' tcx Item < ' _ > ,
167
+ func_expr : & Expr < ' _ > ,
168
+ adt_def : AdtDef < ' _ > ,
169
+ is_const : bool ,
170
+ ) {
149
171
if let ExprKind :: Path ( QPath :: Resolved ( None , p) ) = & peel_blocks ( func_expr) . kind
150
172
&& let Res :: Def ( DefKind :: Ctor ( CtorOf :: Variant , CtorKind :: Const ) , id) = p. res
151
173
&& let variant_id = cx. tcx . parent ( id)
@@ -158,11 +180,15 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex
158
180
let variant_span = cx. tcx . def_span ( variant_def. def_id ) ;
159
181
let indent_variant = indent_of ( cx, variant_span) . unwrap_or ( 0 ) ;
160
182
183
+ let Some ( derive_snippet) = determine_derive_macro ( cx, is_const) else {
184
+ return ;
185
+ } ;
186
+
161
187
let suggestions = vec ! [
162
188
( item. span, String :: new( ) ) , // Remove the manual implementation
163
189
(
164
190
enum_span. shrink_to_lo( ) ,
165
- format!( "#[derive (Default)]\n {}" , " " . repeat( indent_enum) ) ,
191
+ format!( "#[{derive_snippet} (Default)]\n {}" , " " . repeat( indent_enum) ) ,
166
192
) , // Add the derive attribute
167
193
(
168
194
variant_span. shrink_to_lo( ) ,
@@ -201,10 +227,20 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
201
227
&& !attrs. iter ( ) . any ( |attr| attr. doc_str ( ) . is_some ( ) )
202
228
&& cx. tcx . hir_attrs ( impl_item_hir) . is_empty ( )
203
229
{
230
+ let is_const = of_trait. constness == hir:: Constness :: Const ;
204
231
if adt_def. is_struct ( ) {
205
- check_struct ( cx, item, self_ty, func_expr, adt_def, args, cx. tcx . typeck_body ( * b) ) ;
232
+ check_struct (
233
+ cx,
234
+ item,
235
+ self_ty,
236
+ func_expr,
237
+ adt_def,
238
+ args,
239
+ cx. tcx . typeck_body ( * b) ,
240
+ is_const,
241
+ ) ;
206
242
} else if adt_def. is_enum ( ) && self . msrv . meets ( cx, msrvs:: DEFAULT_ENUM_ATTRIBUTE ) {
207
- check_enum ( cx, item, func_expr, adt_def) ;
243
+ check_enum ( cx, item, func_expr, adt_def, is_const ) ;
208
244
}
209
245
}
210
246
}
0 commit comments