Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 0204b95

Browse files
committed
Lint explicit_auto_deref immediately after needless_borrow
1 parent 65bc6cb commit 0204b95

File tree

4 files changed

+73
-35
lines changed

4 files changed

+73
-35
lines changed

clippy_lints/src/dereference.rs

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ struct StateData {
163163
hir_id: HirId,
164164
}
165165

166+
struct DerefedBorrow {
167+
count: usize,
168+
required_precedence: i8,
169+
msg: &'static str,
170+
stability: AutoDerefStability,
171+
position: Position,
172+
}
173+
166174
enum State {
167175
// Any number of deref method calls.
168176
DerefMethod {
@@ -172,11 +180,7 @@ enum State {
172180
/// The required mutability
173181
target_mut: Mutability,
174182
},
175-
DerefedBorrow {
176-
count: usize,
177-
required_precedence: i8,
178-
msg: &'static str,
179-
},
183+
DerefedBorrow(DerefedBorrow),
180184
ExplicitDeref {
181185
deref_span: Span,
182186
deref_hir_id: HirId,
@@ -344,17 +348,16 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
344348

345349
if deref_count >= required_refs {
346350
self.state = Some((
347-
State::DerefedBorrow {
351+
State::DerefedBorrow(DerefedBorrow {
348352
// One of the required refs is for the current borrow expression, the remaining ones
349353
// can't be removed without breaking the code. See earlier comment.
350354
count: deref_count - required_refs,
351355
required_precedence,
352356
msg,
353-
},
354-
StateData {
355-
span: expr.span,
356-
hir_id: expr.hir_id,
357-
},
357+
stability,
358+
position,
359+
}),
360+
StateData { span: expr.span, hir_id: expr.hir_id },
358361
));
359362
} else if stability.is_deref_stable() {
360363
self.state = Some((
@@ -393,26 +396,47 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
393396
data,
394397
));
395398
},
396-
(
397-
Some((
398-
State::DerefedBorrow {
399-
count,
400-
required_precedence,
401-
msg,
402-
},
403-
data,
404-
)),
405-
RefOp::AddrOf,
406-
) if count != 0 => {
399+
(Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) if state.count != 0 => {
407400
self.state = Some((
408-
State::DerefedBorrow {
409-
count: count - 1,
410-
required_precedence,
411-
msg,
412-
},
401+
State::DerefedBorrow(DerefedBorrow {
402+
count: state.count - 1,
403+
..state
404+
}),
413405
data,
414406
));
415407
},
408+
(Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) => {
409+
let stability = state.stability;
410+
report(cx, expr, State::DerefedBorrow(state), data);
411+
if stability.is_deref_stable() {
412+
self.state = Some((
413+
State::Borrow,
414+
StateData {
415+
span: expr.span,
416+
hir_id: expr.hir_id,
417+
},
418+
));
419+
}
420+
},
421+
(Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
422+
let stability = state.stability;
423+
let position = state.position;
424+
report(cx, expr, State::DerefedBorrow(state), data);
425+
if let Position::FieldAccess(name) = position
426+
&& !ty_contains_field(typeck.expr_ty(sub_expr), name)
427+
{
428+
self.state = Some((
429+
State::ExplicitDerefField { name },
430+
StateData { span: expr.span, hir_id: expr.hir_id },
431+
));
432+
} else if stability.is_deref_stable() {
433+
self.state = Some((
434+
State::ExplicitDeref { deref_span: expr.span, deref_hir_id: expr.hir_id },
435+
StateData { span: expr.span, hir_id: expr.hir_id },
436+
));
437+
}
438+
},
439+
416440
(Some((State::Borrow, data)), RefOp::Deref) => {
417441
if typeck.expr_ty(sub_expr).is_ref() {
418442
self.state = Some((
@@ -942,15 +966,11 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
942966
app,
943967
);
944968
},
945-
State::DerefedBorrow {
946-
required_precedence,
947-
msg,
948-
..
949-
} => {
969+
State::DerefedBorrow(state) => {
950970
let mut app = Applicability::MachineApplicable;
951971
let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0;
952-
span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, msg, |diag| {
953-
let sugg = if required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) {
972+
span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| {
973+
let sugg = if state.required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) {
954974
format!("({})", snip)
955975
} else {
956976
snip.into()

tests/ui/explicit_auto_deref.fixed

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,7 @@ fn main() {
198198
return *x;
199199
}
200200
}
201+
202+
f_str(&&ref_str); // `needless_borrow` will suggest removing both references
203+
f_str(&ref_str); // `needless_borrow` will suggest removing only one reference
201204
}

tests/ui/explicit_auto_deref.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,7 @@ fn main() {
198198
return *x;
199199
}
200200
}
201+
202+
f_str(&&*ref_str); // `needless_borrow` will suggest removing both references
203+
f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
201204
}

tests/ui/explicit_auto_deref.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,17 @@ error: deref which would be done by auto-deref
180180
LL | let _ = f_str(**ref_ref_str);
181181
| ^^^^^^^^^^^^^ help: try this: `ref_ref_str`
182182

183-
error: aborting due to 30 previous errors
183+
error: deref which would be done by auto-deref
184+
--> $DIR/explicit_auto_deref.rs:201:13
185+
|
186+
LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references
187+
| ^^^^^^^^ help: try this: `ref_str`
188+
189+
error: deref which would be done by auto-deref
190+
--> $DIR/explicit_auto_deref.rs:202:12
191+
|
192+
LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
193+
| ^^^^^^^^^^ help: try this: `ref_str`
194+
195+
error: aborting due to 32 previous errors
184196

0 commit comments

Comments
 (0)