diff options
| author | bors <bors@rust-lang.org> | 2022-09-28 14:58:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-09-28 14:58:07 +0000 |
| commit | 8845f8214201bf8945de37997394994c5f6f7ace (patch) | |
| tree | 752f5c872231e9698cf04ce7df840c7b1d8e0724 | |
| parent | 0f6932a1f7623663e50922225ea304340949c051 (diff) | |
| parent | 14ba4fba11e0e38d35c63559553380d8fde4517a (diff) | |
| download | rust-8845f8214201bf8945de37997394994c5f6f7ace.tar.gz rust-8845f8214201bf8945de37997394994c5f6f7ace.zip | |
Auto merge of #9490 - kraktus:needless_borrow, r=Jarcho
fix [`needless_borrow`], [`explicit_auto_deref`] FPs on unions fix https://github.com/rust-lang/rust-clippy/issues/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
| -rw-r--r-- | clippy_lints/src/dereference.rs | 37 | ||||
| -rw-r--r-- | tests/ui/needless_borrow.fixed | 29 | ||||
| -rw-r--r-- | tests/ui/needless_borrow.rs | 29 |
3 files changed, 87 insertions, 8 deletions
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index e272283152d..d8c57ec9ebe 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -184,6 +184,7 @@ impl Dereferencing { } } +#[derive(Debug)] struct StateData { /// Span of the top level expression span: Span, @@ -191,12 +192,14 @@ struct StateData { position: Position, } +#[derive(Debug)] struct DerefedBorrow { count: usize, msg: &'static str, snip_expr: Option<HirId>, } +#[derive(Debug)] enum State { // Any number of deref method calls. DerefMethod { @@ -276,10 +279,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { (None, kind) => { let expr_ty = typeck.expr_ty(expr); let (position, adjustments) = walk_parents(cx, expr, self.msrv); - match kind { RefOp::Deref => { - if let Position::FieldAccess(name) = position + if let Position::FieldAccess { + name, + of_union: false, + } = position && !ty_contains_field(typeck.expr_ty(sub_expr), name) { self.state = Some(( @@ -451,7 +456,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => { let position = data.position; report(cx, expr, State::DerefedBorrow(state), data); - if let Position::FieldAccess(name) = position + if let Position::FieldAccess{name, ..} = position && !ty_contains_field(typeck.expr_ty(sub_expr), name) { self.state = Some(( @@ -616,14 +621,17 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool { } /// The position of an expression relative to it's parent. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] enum Position { MethodReceiver, /// The method is defined on a reference type. e.g. `impl Foo for &T` MethodReceiverRefImpl, Callee, ImplArg(HirId), - FieldAccess(Symbol), + FieldAccess { + name: Symbol, + of_union: bool, + }, // union fields cannot be auto borrowed Postfix, Deref, /// Any other location which will trigger auto-deref to a specific time. @@ -645,7 +653,10 @@ impl Position { } fn can_auto_borrow(self) -> bool { - matches!(self, Self::MethodReceiver | Self::FieldAccess(_) | Self::Callee) + matches!( + self, + Self::MethodReceiver | Self::FieldAccess { of_union: false, .. } | Self::Callee + ) } fn lint_explicit_deref(self) -> bool { @@ -657,7 +668,7 @@ impl Position { Self::MethodReceiver | Self::MethodReceiverRefImpl | Self::Callee - | Self::FieldAccess(_) + | Self::FieldAccess { .. } | Self::Postfix => PREC_POSTFIX, Self::ImplArg(_) | Self::Deref => PREC_PREFIX, Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p, @@ -844,7 +855,10 @@ fn walk_parents<'tcx>( } }) }, - ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)), + ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess { + name: name.name, + of_union: is_union(cx.typeck_results(), child), + }), ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref), ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar) | ExprKind::Index(child, _) @@ -865,6 +879,13 @@ fn walk_parents<'tcx>( (position, adjustments) } +fn is_union<'tcx>(typeck: &'tcx TypeckResults<'_>, path_expr: &'tcx Expr<'_>) -> bool { + typeck + .expr_ty_adjusted(path_expr) + .ty_adt_def() + .map_or(false, rustc_middle::ty::AdtDef::is_union) +} + fn closure_result_position<'tcx>( cx: &LateContext<'tcx>, closure: &'tcx Closure<'_>, diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 8cf93bd2481..6914f9183c7 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -298,3 +298,32 @@ mod meets_msrv { let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap(); } } + +#[allow(unused)] +fn issue9383() { + // Should not lint because unions need explicit deref when accessing field + use std::mem::ManuallyDrop; + + union Coral { + crab: ManuallyDrop<Vec<i32>>, + } + + union Ocean { + coral: ManuallyDrop<Coral>, + } + + let mut ocean = Ocean { + coral: ManuallyDrop::new(Coral { + crab: ManuallyDrop::new(vec![1, 2, 3]), + }), + }; + + unsafe { + ManuallyDrop::drop(&mut (&mut ocean.coral).crab); + + (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]); + ManuallyDrop::drop(&mut (*ocean.coral).crab); + + ManuallyDrop::drop(&mut ocean.coral); + } +} diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index fd9b2a11df9..e2a609fa5d2 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -298,3 +298,32 @@ mod meets_msrv { let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap(); } } + +#[allow(unused)] +fn issue9383() { + // Should not lint because unions need explicit deref when accessing field + use std::mem::ManuallyDrop; + + union Coral { + crab: ManuallyDrop<Vec<i32>>, + } + + union Ocean { + coral: ManuallyDrop<Coral>, + } + + let mut ocean = Ocean { + coral: ManuallyDrop::new(Coral { + crab: ManuallyDrop::new(vec![1, 2, 3]), + }), + }; + + unsafe { + ManuallyDrop::drop(&mut (&mut ocean.coral).crab); + + (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]); + ManuallyDrop::drop(&mut (*ocean.coral).crab); + + ManuallyDrop::drop(&mut ocean.coral); + } +} |
