Skip to content

Commit 704f7a8

Browse files
committed
Keep track of whether deref or deref_mut was called
Remove more unnecessary code
1 parent 1666e43 commit 704f7a8

File tree

2 files changed

+17
-60
lines changed

2 files changed

+17
-60
lines changed

clippy_lints/src/dereference.rs

Lines changed: 16 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::utils::{get_parent_node, in_macro, is_allowed, peel_mid_ty_refs, snippet_with_context, span_lint_and_sugg};
22
use rustc_ast::util::parser::PREC_PREFIX;
33
use rustc_errors::Applicability;
4-
use rustc_hir::{BorrowKind, Destination, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
4+
use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, UnOp};
55
use rustc_lint::{LateContext, LateLintPass};
6-
use rustc_middle::ty::{self, adjustment::Adjustment, Ty, TyCtxt, TyS, TypeckResults};
6+
use rustc_middle::ty::{self, Ty, TyCtxt, TyS, TypeckResults};
77
use rustc_session::{declare_tool_lint, impl_lint_pass};
88
use rustc_span::{symbol::sym, Span};
99

@@ -66,7 +66,7 @@ enum State {
6666

6767
// A reference operation considered by this lint pass
6868
enum RefOp {
69-
Method,
69+
Method(Mutability),
7070
Deref,
7171
AddrOf,
7272
}
@@ -100,18 +100,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
100100
match (self.state.take(), kind) {
101101
(None, kind) => {
102102
let parent = get_parent_node(cx.tcx, expr.hir_id);
103-
104-
let expr_adjustments = find_adjustments(cx.tcx, typeck, expr);
105103
let expr_ty = typeck.expr_ty(expr);
106-
let target_mut =
107-
if let ty::Ref(_, _, mutability) = *expr_adjustments.last().map_or(expr_ty, |a| a.target).kind() {
108-
mutability
109-
} else {
110-
Mutability::Not
111-
};
112104

113105
match kind {
114-
RefOp::Method
106+
RefOp::Method(target_mut)
115107
if !is_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
116108
&& is_linted_explicit_deref_position(parent, expr.hir_id) =>
117109
{
@@ -133,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
133125
_ => (),
134126
}
135127
},
136-
(Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method) => {
128+
(Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => {
137129
self.state = Some((
138130
State::DerefMethod {
139131
ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) {
@@ -173,9 +165,13 @@ fn try_parse_ref_op(
173165
ExprKind::AddrOf(BorrowKind::Ref, _, sub_expr) => return Some((RefOp::AddrOf, sub_expr)),
174166
_ => return None,
175167
};
176-
(tcx.is_diagnostic_item(sym::deref_method, def_id)
177-
|| tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()?)
178-
.then(|| (RefOp::Method, arg))
168+
if tcx.is_diagnostic_item(sym::deref_method, def_id) {
169+
Some((RefOp::Method(Mutability::Not), arg))
170+
} else if tcx.trait_of_item(def_id)? == tcx.lang_items().deref_mut_trait()? {
171+
Some((RefOp::Method(Mutability::Mut), arg))
172+
} else {
173+
None
174+
}
179175
}
180176

181177
// Checks whether the type for a deref call actually changed the type, not just the mutability of
@@ -191,48 +187,6 @@ fn deref_method_same_type(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
191187
}
192188
}
193189

194-
// Adjustments are sometimes made in the parent block rather than the expression itself.
195-
fn find_adjustments(
196-
tcx: TyCtxt<'tcx>,
197-
typeck: &'tcx TypeckResults<'_>,
198-
expr: &'tcx Expr<'_>,
199-
) -> &'tcx [Adjustment<'tcx>] {
200-
let map = tcx.hir();
201-
let mut iter = map.parent_iter(expr.hir_id);
202-
let mut prev = expr;
203-
204-
loop {
205-
match typeck.expr_adjustments(prev) {
206-
[] => (),
207-
a => break a,
208-
};
209-
210-
match iter.next().map(|(_, x)| x) {
211-
Some(Node::Block(_)) => {
212-
if let Some((_, Node::Expr(e))) = iter.next() {
213-
prev = e;
214-
} else {
215-
// This shouldn't happen. Blocks are always contained in an expression.
216-
break &[];
217-
}
218-
},
219-
Some(Node::Expr(&Expr {
220-
kind: ExprKind::Break(Destination { target_id: Ok(id), .. }, _),
221-
..
222-
})) => {
223-
if let Some(Node::Expr(e)) = map.find(id) {
224-
prev = e;
225-
iter = map.parent_iter(id);
226-
continue;
227-
}
228-
// This shouldn't happen. The destination should definitely exist at this point.
229-
break &[];
230-
},
231-
_ => break &[],
232-
}
233-
}
234-
}
235-
236190
// Checks whether the parent node is a suitable context for switching from a deref method to the
237191
// deref operator.
238192
fn is_linted_explicit_deref_position(parent: Option<Node<'_>>, child_id: HirId) -> bool {
@@ -331,7 +285,10 @@ fn report(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data: Stat
331285
cx,
332286
EXPLICIT_DEREF_METHODS,
333287
data.span,
334-
"explicit `deref` method call",
288+
match data.target_mut {
289+
Mutability::Not => "explicit `deref` method call",
290+
Mutability::Mut => "explicit `deref_mut` method call",
291+
},
335292
"try this",
336293
format!("{}{}{}", addr_of_str, deref_str, expr_str),
337294
app,

tests/ui/explicit_deref_methods.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | let b: &str = a.deref();
66
|
77
= note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
88

9-
error: explicit `deref` method call
9+
error: explicit `deref_mut` method call
1010
--> $DIR/explicit_deref_methods.rs:32:23
1111
|
1212
LL | let b: &mut str = a.deref_mut();

0 commit comments

Comments
 (0)