Skip to content

Commit 8845f82

Browse files
committed
Auto merge of #9490 - kraktus:needless_borrow, r=Jarcho
fix [`needless_borrow`], [`explicit_auto_deref`] FPs on unions fix #9383 changelog: fix [`needless_borrow`] false positive on unions changelog: fix [`explicit_auto_deref`] false positive on unions Left a couple debug derived impls on purpose I needed to debug as I don't think it's noise
2 parents 0f6932a + 14ba4fb commit 8845f82

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-8
lines changed

clippy_lints/src/dereference.rs

+29-8
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,22 @@ impl Dereferencing {
184184
}
185185
}
186186

187+
#[derive(Debug)]
187188
struct StateData {
188189
/// Span of the top level expression
189190
span: Span,
190191
hir_id: HirId,
191192
position: Position,
192193
}
193194

195+
#[derive(Debug)]
194196
struct DerefedBorrow {
195197
count: usize,
196198
msg: &'static str,
197199
snip_expr: Option<HirId>,
198200
}
199201

202+
#[derive(Debug)]
200203
enum State {
201204
// Any number of deref method calls.
202205
DerefMethod {
@@ -276,10 +279,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
276279
(None, kind) => {
277280
let expr_ty = typeck.expr_ty(expr);
278281
let (position, adjustments) = walk_parents(cx, expr, self.msrv);
279-
280282
match kind {
281283
RefOp::Deref => {
282-
if let Position::FieldAccess(name) = position
284+
if let Position::FieldAccess {
285+
name,
286+
of_union: false,
287+
} = position
283288
&& !ty_contains_field(typeck.expr_ty(sub_expr), name)
284289
{
285290
self.state = Some((
@@ -451,7 +456,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
451456
(Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
452457
let position = data.position;
453458
report(cx, expr, State::DerefedBorrow(state), data);
454-
if let Position::FieldAccess(name) = position
459+
if let Position::FieldAccess{name, ..} = position
455460
&& !ty_contains_field(typeck.expr_ty(sub_expr), name)
456461
{
457462
self.state = Some((
@@ -616,14 +621,17 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
616621
}
617622

618623
/// The position of an expression relative to it's parent.
619-
#[derive(Clone, Copy)]
624+
#[derive(Clone, Copy, Debug)]
620625
enum Position {
621626
MethodReceiver,
622627
/// The method is defined on a reference type. e.g. `impl Foo for &T`
623628
MethodReceiverRefImpl,
624629
Callee,
625630
ImplArg(HirId),
626-
FieldAccess(Symbol),
631+
FieldAccess {
632+
name: Symbol,
633+
of_union: bool,
634+
}, // union fields cannot be auto borrowed
627635
Postfix,
628636
Deref,
629637
/// Any other location which will trigger auto-deref to a specific time.
@@ -645,7 +653,10 @@ impl Position {
645653
}
646654

647655
fn can_auto_borrow(self) -> bool {
648-
matches!(self, Self::MethodReceiver | Self::FieldAccess(_) | Self::Callee)
656+
matches!(
657+
self,
658+
Self::MethodReceiver | Self::FieldAccess { of_union: false, .. } | Self::Callee
659+
)
649660
}
650661

651662
fn lint_explicit_deref(self) -> bool {
@@ -657,7 +668,7 @@ impl Position {
657668
Self::MethodReceiver
658669
| Self::MethodReceiverRefImpl
659670
| Self::Callee
660-
| Self::FieldAccess(_)
671+
| Self::FieldAccess { .. }
661672
| Self::Postfix => PREC_POSTFIX,
662673
Self::ImplArg(_) | Self::Deref => PREC_PREFIX,
663674
Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p,
@@ -844,7 +855,10 @@ fn walk_parents<'tcx>(
844855
}
845856
})
846857
},
847-
ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
858+
ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess {
859+
name: name.name,
860+
of_union: is_union(cx.typeck_results(), child),
861+
}),
848862
ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
849863
ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
850864
| ExprKind::Index(child, _)
@@ -865,6 +879,13 @@ fn walk_parents<'tcx>(
865879
(position, adjustments)
866880
}
867881

882+
fn is_union<'tcx>(typeck: &'tcx TypeckResults<'_>, path_expr: &'tcx Expr<'_>) -> bool {
883+
typeck
884+
.expr_ty_adjusted(path_expr)
885+
.ty_adt_def()
886+
.map_or(false, rustc_middle::ty::AdtDef::is_union)
887+
}
888+
868889
fn closure_result_position<'tcx>(
869890
cx: &LateContext<'tcx>,
870891
closure: &'tcx Closure<'_>,

tests/ui/needless_borrow.fixed

+29
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,32 @@ mod meets_msrv {
298298
let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap();
299299
}
300300
}
301+
302+
#[allow(unused)]
303+
fn issue9383() {
304+
// Should not lint because unions need explicit deref when accessing field
305+
use std::mem::ManuallyDrop;
306+
307+
union Coral {
308+
crab: ManuallyDrop<Vec<i32>>,
309+
}
310+
311+
union Ocean {
312+
coral: ManuallyDrop<Coral>,
313+
}
314+
315+
let mut ocean = Ocean {
316+
coral: ManuallyDrop::new(Coral {
317+
crab: ManuallyDrop::new(vec![1, 2, 3]),
318+
}),
319+
};
320+
321+
unsafe {
322+
ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
323+
324+
(*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
325+
ManuallyDrop::drop(&mut (*ocean.coral).crab);
326+
327+
ManuallyDrop::drop(&mut ocean.coral);
328+
}
329+
}

tests/ui/needless_borrow.rs

+29
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,32 @@ mod meets_msrv {
298298
let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
299299
}
300300
}
301+
302+
#[allow(unused)]
303+
fn issue9383() {
304+
// Should not lint because unions need explicit deref when accessing field
305+
use std::mem::ManuallyDrop;
306+
307+
union Coral {
308+
crab: ManuallyDrop<Vec<i32>>,
309+
}
310+
311+
union Ocean {
312+
coral: ManuallyDrop<Coral>,
313+
}
314+
315+
let mut ocean = Ocean {
316+
coral: ManuallyDrop::new(Coral {
317+
crab: ManuallyDrop::new(vec![1, 2, 3]),
318+
}),
319+
};
320+
321+
unsafe {
322+
ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
323+
324+
(*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
325+
ManuallyDrop::drop(&mut (*ocean.coral).crab);
326+
327+
ManuallyDrop::drop(&mut ocean.coral);
328+
}
329+
}

0 commit comments

Comments
 (0)