@@ -184,19 +184,22 @@ impl Dereferencing {
184
184
}
185
185
}
186
186
187
+ #[ derive( Debug ) ]
187
188
struct StateData {
188
189
/// Span of the top level expression
189
190
span : Span ,
190
191
hir_id : HirId ,
191
192
position : Position ,
192
193
}
193
194
195
+ #[ derive( Debug ) ]
194
196
struct DerefedBorrow {
195
197
count : usize ,
196
198
msg : & ' static str ,
197
199
snip_expr : Option < HirId > ,
198
200
}
199
201
202
+ #[ derive( Debug ) ]
200
203
enum State {
201
204
// Any number of deref method calls.
202
205
DerefMethod {
@@ -276,11 +279,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
276
279
( None , kind) => {
277
280
let expr_ty = typeck. expr_ty ( expr) ;
278
281
let ( position, adjustments) = walk_parents ( cx, expr, self . msrv ) ;
282
+ let is_field_of_union = is_field_of_union ( typeck, sub_expr) ;
279
283
280
284
match kind {
281
285
RefOp :: Deref => {
282
286
if let Position :: FieldAccess ( name) = position
283
287
&& !ty_contains_field ( typeck. expr_ty ( sub_expr) , name)
288
+ && !is_field_of_union
284
289
{
285
290
self . state = Some ( (
286
291
State :: ExplicitDerefField { name } ,
@@ -355,7 +360,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
355
360
let borrow_msg = "this expression borrows a value the compiler would automatically borrow" ;
356
361
let impl_msg = "the borrowed expression implements the required traits" ;
357
362
358
- let ( required_refs, msg, snip_expr) = if position. can_auto_borrow ( ) {
363
+ let ( required_refs, msg, snip_expr) = if position. can_auto_borrow ( is_field_of_union ) {
359
364
( 1 , if deref_count == 1 { borrow_msg } else { deref_msg } , None )
360
365
} else if let Position :: ImplArg ( hir_id) = position {
361
366
( 0 , impl_msg, Some ( hir_id) )
@@ -572,6 +577,17 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
572
577
extract_msrv_attr ! ( LateContext ) ;
573
578
}
574
579
580
+ // deref needs to be explicit on union fields
581
+ fn is_field_of_union < ' tcx > ( typeck : & ' tcx TypeckResults < ' _ > , expr : & ' tcx Expr < ' _ > ) -> bool {
582
+ if let ExprKind :: Field ( path_expr, _) = expr. kind {
583
+ let ty = typeck. expr_ty_adjusted ( path_expr) ;
584
+ if let Some ( adt_def) = ty. ty_adt_def ( ) {
585
+ return adt_def. is_union ( ) ;
586
+ }
587
+ }
588
+ false
589
+ }
590
+
575
591
fn try_parse_ref_op < ' tcx > (
576
592
tcx : TyCtxt < ' tcx > ,
577
593
typeck : & ' tcx TypeckResults < ' _ > ,
@@ -616,7 +632,7 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
616
632
}
617
633
618
634
/// The position of an expression relative to it's parent.
619
- #[ derive( Clone , Copy ) ]
635
+ #[ derive( Clone , Copy , Debug ) ]
620
636
enum Position {
621
637
MethodReceiver ,
622
638
/// The method is defined on a reference type. e.g. `impl Foo for &T`
@@ -644,8 +660,9 @@ impl Position {
644
660
matches ! ( self , Self :: DerefStable ( ..) | Self :: ReborrowStable ( _) )
645
661
}
646
662
647
- fn can_auto_borrow ( self ) -> bool {
648
- matches ! ( self , Self :: MethodReceiver | Self :: FieldAccess ( _) | Self :: Callee )
663
+ fn can_auto_borrow ( self , is_field_of_union : bool ) -> bool {
664
+ // union fields cannot be auto borrowed
665
+ !is_field_of_union && matches ! ( self , Self :: MethodReceiver | Self :: FieldAccess ( _) | Self :: Callee )
649
666
}
650
667
651
668
fn lint_explicit_deref ( self ) -> bool {
0 commit comments