@@ -143,7 +143,10 @@ impl<'ctx> CannotDerive<'ctx> {
143
143
" cannot derive {} for blacklisted type" ,
144
144
self . derive_trait
145
145
) ;
146
- return CanDerive :: No ;
146
+ match self . derive_trait {
147
+ DeriveTrait :: Default => return CanDerive :: Manually ,
148
+ _ => return CanDerive :: No ,
149
+ }
147
150
}
148
151
149
152
if self . derive_trait . not_by_name ( self . ctx , & item) {
@@ -156,15 +159,26 @@ impl<'ctx> CannotDerive<'ctx> {
156
159
157
160
trace ! ( "ty: {:?}" , ty) ;
158
161
if item. is_opaque ( self . ctx , & ( ) ) {
159
- if !self . derive_trait . can_derive_union ( ) &&
160
- ty. is_union ( ) &&
162
+ if ty. is_union ( ) &&
161
163
self . ctx . options ( ) . rust_features ( ) . untagged_union
162
164
{
163
- trace ! (
164
- " cannot derive {} for Rust unions" ,
165
- self . derive_trait
166
- ) ;
167
- return CanDerive :: No ;
165
+ match self . derive_trait . can_derive_union ( ) {
166
+ CanDerive :: Manually => {
167
+ trace ! (
168
+ " cannot derive {} for Rust unions, but it can be implemented" ,
169
+ self . derive_trait
170
+ ) ;
171
+ return CanDerive :: Manually ;
172
+ }
173
+ CanDerive :: No => {
174
+ trace ! (
175
+ " cannot derive {} for Rust unions" ,
176
+ self . derive_trait
177
+ ) ;
178
+ return CanDerive :: No ;
179
+ }
180
+ _ => ( ) ,
181
+ } ;
168
182
}
169
183
170
184
let layout_can_derive =
@@ -179,7 +193,13 @@ impl<'ctx> CannotDerive<'ctx> {
179
193
self . derive_trait
180
194
) ;
181
195
}
182
- _ => {
196
+ CanDerive :: Manually => {
197
+ trace ! (
198
+ " we cannot derive {} for the layout, but it can be implemented" ,
199
+ self . derive_trait
200
+ ) ;
201
+ }
202
+ CanDerive :: No => {
183
203
trace ! (
184
204
" we cannot derive {} for the layout" ,
185
205
self . derive_trait
@@ -223,15 +243,27 @@ impl<'ctx> CannotDerive<'ctx> {
223
243
TypeKind :: Array ( t, len) => {
224
244
let inner_type =
225
245
self . can_derive . get ( & t. into ( ) ) . cloned ( ) . unwrap_or_default ( ) ;
226
- if inner_type != CanDerive :: Yes {
227
- trace ! (
228
- " arrays of T for which we cannot derive {} \
229
- also cannot derive {}",
230
- self . derive_trait,
231
- self . derive_trait
232
- ) ;
233
- return CanDerive :: No ;
234
- }
246
+ match inner_type {
247
+ CanDerive :: Manually => {
248
+ trace ! (
249
+ " arrays of T for which we can only manually implement {} \
250
+ also can only manually implement {}",
251
+ self . derive_trait,
252
+ self . derive_trait
253
+ ) ;
254
+ return CanDerive :: Manually ;
255
+ }
256
+ CanDerive :: No => {
257
+ trace ! (
258
+ " arrays of T for which we cannot derive {} \
259
+ also cannot derive {}",
260
+ self . derive_trait,
261
+ self . derive_trait
262
+ ) ;
263
+ return CanDerive :: No ;
264
+ }
265
+ _ => ( ) ,
266
+ } ;
235
267
236
268
if len == 0 && !self . derive_trait . can_derive_incomplete_array ( )
237
269
{
@@ -308,62 +340,90 @@ impl<'ctx> CannotDerive<'ctx> {
308
340
}
309
341
310
342
if info. kind ( ) == CompKind :: Union {
311
- if self . derive_trait . can_derive_union ( ) {
312
- if self . ctx . options ( ) . rust_features ( ) . untagged_union &&
313
- // https://github.com/rust-lang/rust/issues/36640
314
- ( !info. self_template_params ( self . ctx ) . is_empty ( ) ||
315
- !item. all_template_params ( self . ctx ) . is_empty ( ) )
316
- {
317
- trace ! (
318
- " cannot derive {} for Rust union because issue 36640" , self . derive_trait
319
- ) ;
320
- return CanDerive :: No ;
321
- }
322
- // fall through to be same as non-union handling
323
- } else {
324
- if self . ctx . options ( ) . rust_features ( ) . untagged_union {
325
- trace ! (
326
- " cannot derive {} for Rust unions" ,
327
- self . derive_trait
328
- ) ;
329
- return CanDerive :: No ;
330
- }
331
-
332
- let layout_can_derive =
333
- ty. layout ( self . ctx ) . map_or ( CanDerive :: Yes , |l| {
334
- l. opaque ( )
335
- . array_size_within_derive_limit ( self . ctx )
336
- } ) ;
337
- match layout_can_derive {
338
- CanDerive :: Yes => {
343
+ match self . derive_trait . can_derive_union ( ) {
344
+ CanDerive :: Yes => {
345
+ if self . ctx . options ( ) . rust_features ( ) . untagged_union &&
346
+ // https://github.com/rust-lang/rust/issues/36640
347
+ ( !info. self_template_params ( self . ctx ) . is_empty ( ) ||
348
+ !item. all_template_params ( self . ctx ) . is_empty ( ) )
349
+ {
339
350
trace ! (
340
- " union layout can trivially derive {}" ,
341
- self . derive_trait
351
+ " cannot derive {} for Rust union because issue 36640" , self . derive_trait
342
352
) ;
353
+ return CanDerive :: No ;
343
354
}
344
- _ => {
345
- trace ! (
346
- " union layout cannot derive {}" ,
347
- self . derive_trait
348
- ) ;
355
+ // fall through to be same as non-union handling
356
+ }
357
+ trait_can_derive => {
358
+ if self . ctx . options ( ) . rust_features ( ) . untagged_union
359
+ {
360
+ match trait_can_derive {
361
+ CanDerive :: Manually => {
362
+ trace ! (
363
+ " cannot derive {} for Rust union, but it can be implemented" ,
364
+ self . derive_trait
365
+ ) ;
366
+ }
367
+ _ => {
368
+ trace ! (
369
+ " cannot derive {} for Rust unions" ,
370
+ self . derive_trait
371
+ ) ;
372
+ }
373
+ }
374
+ return trait_can_derive;
349
375
}
350
- } ;
351
- return layout_can_derive;
376
+
377
+ let layout_can_derive = ty. layout ( self . ctx ) . map_or (
378
+ CanDerive :: Yes ,
379
+ |l| {
380
+ l. opaque ( ) . array_size_within_derive_limit (
381
+ self . ctx ,
382
+ )
383
+ } ,
384
+ ) ;
385
+ match layout_can_derive {
386
+ CanDerive :: Yes => {
387
+ trace ! (
388
+ " union layout can trivially derive {}" ,
389
+ self . derive_trait
390
+ ) ;
391
+ }
392
+ _ => {
393
+ trace ! (
394
+ " union layout cannot derive {}" ,
395
+ self . derive_trait
396
+ ) ;
397
+ }
398
+ } ;
399
+ return layout_can_derive;
400
+ }
352
401
}
353
402
}
354
403
355
- if !self . derive_trait . can_derive_compound_with_vtable ( ) &&
356
- item. has_vtable ( self . ctx )
357
- {
358
- trace ! (
359
- " cannot derive {} for comp with vtable" ,
360
- self . derive_trait
361
- ) ;
362
- return CanDerive :: No ;
404
+ match (
405
+ self . derive_trait . can_derive_compound_with_vtable ( ) ,
406
+ item. has_vtable ( self . ctx ) ,
407
+ ) {
408
+ ( CanDerive :: Manually , true ) => {
409
+ trace ! (
410
+ " cannot derive {} for comp with vtable, but it can be implemented" ,
411
+ self . derive_trait
412
+ ) ;
413
+ return CanDerive :: Manually ;
414
+ }
415
+ ( CanDerive :: No , true ) => {
416
+ trace ! (
417
+ " cannot derive {} for comp with vtable" ,
418
+ self . derive_trait
419
+ ) ;
420
+ return CanDerive :: No ;
421
+ }
422
+ _ => ( ) ,
363
423
}
364
424
365
425
let pred = self . derive_trait . consider_edge_comp ( ) ;
366
- return self . constrain_join ( item, pred) ;
426
+ self . constrain_join ( item, pred)
367
427
}
368
428
369
429
TypeKind :: ResolvedTypeRef ( ..) |
@@ -476,10 +536,11 @@ impl DeriveTrait {
476
536
}
477
537
}
478
538
479
- fn can_derive_union ( & self ) -> bool {
539
+ fn can_derive_union ( & self ) -> CanDerive {
480
540
match self {
481
- DeriveTrait :: Copy => true ,
482
- _ => false ,
541
+ DeriveTrait :: Copy => CanDerive :: Yes ,
542
+ DeriveTrait :: Default => CanDerive :: Manually ,
543
+ _ => CanDerive :: No ,
483
544
}
484
545
}
485
546
@@ -490,10 +551,10 @@ impl DeriveTrait {
490
551
}
491
552
}
492
553
493
- fn can_derive_compound_with_vtable ( & self ) -> bool {
554
+ fn can_derive_compound_with_vtable ( & self ) -> CanDerive {
494
555
match self {
495
- DeriveTrait :: Default => false ,
496
- _ => true ,
556
+ DeriveTrait :: Default => CanDerive :: Manually ,
557
+ _ => CanDerive :: Yes ,
497
558
}
498
559
}
499
560
@@ -549,8 +610,8 @@ impl DeriveTrait {
549
610
fn can_derive_pointer ( & self ) -> CanDerive {
550
611
match self {
551
612
DeriveTrait :: Default => {
552
- trace ! ( " pointer cannot derive Default" ) ;
553
- CanDerive :: No
613
+ trace ! ( " pointer cannot derive Default, but it may be implemented " ) ;
614
+ CanDerive :: Manually
554
615
}
555
616
_ => {
556
617
trace ! ( " pointer can derive {}" , self ) ;
@@ -570,8 +631,8 @@ impl DeriveTrait {
570
631
( DeriveTrait :: Default , TypeKind :: ObjCInterface ( ..) ) |
571
632
( DeriveTrait :: Default , TypeKind :: ObjCId ) |
572
633
( DeriveTrait :: Default , TypeKind :: ObjCSel ) => {
573
- trace ! ( " types that always cannot derive Default" ) ;
574
- CanDerive :: No
634
+ trace ! ( " types that always cannot derive Default, but may implement it manually " ) ;
635
+ CanDerive :: Manually
575
636
}
576
637
( DeriveTrait :: Default , TypeKind :: UnresolvedTypeRef ( ..) ) => {
577
638
unreachable ! (
0 commit comments