hir_id: HirId,
}
+struct DerefedBorrow {
+ count: usize,
+ required_precedence: i8,
+ msg: &'static str,
+ stability: AutoDerefStability,
+ position: Position,
+}
+
enum State {
// Any number of deref method calls.
DerefMethod {
/// The required mutability
target_mut: Mutability,
},
- DerefedBorrow {
- count: usize,
- required_precedence: i8,
- msg: &'static str,
- },
+ DerefedBorrow(DerefedBorrow),
ExplicitDeref {
deref_span: Span,
deref_hir_id: HirId,
if deref_count >= required_refs {
self.state = Some((
- State::DerefedBorrow {
+ State::DerefedBorrow(DerefedBorrow {
// One of the required refs is for the current borrow expression, the remaining ones
// can't be removed without breaking the code. See earlier comment.
count: deref_count - required_refs,
required_precedence,
msg,
- },
- StateData {
- span: expr.span,
- hir_id: expr.hir_id,
- },
+ stability,
+ position,
+ }),
+ StateData { span: expr.span, hir_id: expr.hir_id },
));
} else if stability.is_deref_stable() {
self.state = Some((
data,
));
},
- (
- Some((
- State::DerefedBorrow {
- count,
- required_precedence,
- msg,
- },
- data,
- )),
- RefOp::AddrOf,
- ) if count != 0 => {
+ (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) if state.count != 0 => {
self.state = Some((
- State::DerefedBorrow {
- count: count - 1,
- required_precedence,
- msg,
- },
+ State::DerefedBorrow(DerefedBorrow {
+ count: state.count - 1,
+ ..state
+ }),
data,
));
},
+ (Some((State::DerefedBorrow(state), data)), RefOp::AddrOf) => {
+ let stability = state.stability;
+ report(cx, expr, State::DerefedBorrow(state), data);
+ if stability.is_deref_stable() {
+ self.state = Some((
+ State::Borrow,
+ StateData {
+ span: expr.span,
+ hir_id: expr.hir_id,
+ },
+ ));
+ }
+ },
+ (Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
+ let stability = state.stability;
+ let position = state.position;
+ report(cx, expr, State::DerefedBorrow(state), data);
+ if let Position::FieldAccess(name) = position
+ && !ty_contains_field(typeck.expr_ty(sub_expr), name)
+ {
+ self.state = Some((
+ State::ExplicitDerefField { name },
+ StateData { span: expr.span, hir_id: expr.hir_id },
+ ));
+ } else if stability.is_deref_stable() {
+ self.state = Some((
+ State::ExplicitDeref { deref_span: expr.span, deref_hir_id: expr.hir_id },
+ StateData { span: expr.span, hir_id: expr.hir_id },
+ ));
+ }
+ },
+
(Some((State::Borrow, data)), RefOp::Deref) => {
if typeck.expr_ty(sub_expr).is_ref() {
self.state = Some((
app,
);
},
- State::DerefedBorrow {
- required_precedence,
- msg,
- ..
- } => {
+ State::DerefedBorrow(state) => {
let mut app = Applicability::MachineApplicable;
let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0;
- span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, msg, |diag| {
- let sugg = if required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) {
+ span_lint_hir_and_then(cx, NEEDLESS_BORROW, data.hir_id, data.span, state.msg, |diag| {
+ let sugg = if state.required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) {
format!("({})", snip)
} else {
snip.into()
LL | let _ = f_str(**ref_ref_str);
| ^^^^^^^^^^^^^ help: try this: `ref_ref_str`
-error: aborting due to 30 previous errors
+error: deref which would be done by auto-deref
+ --> $DIR/explicit_auto_deref.rs:201:13
+ |
+LL | f_str(&&*ref_str); // `needless_borrow` will suggest removing both references
+ | ^^^^^^^^ help: try this: `ref_str`
+
+error: deref which would be done by auto-deref
+ --> $DIR/explicit_auto_deref.rs:202:12
+ |
+LL | f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference
+ | ^^^^^^^^^^ help: try this: `ref_str`
+
+error: aborting due to 32 previous errors