Skip to content

Commit cdf2e7c

Browse files
authored
fix: borrow_deref_ref suggests wrongly when coerce to mut (rust-lang#14403)
Closes rust-lang#11346. Partially fix rust-lang#9905. The first case in this issue is a little tricky as the coerce does not happen in the borrowing. changelog: [`borrow_deref_ref`]: fix wrong suggestions when coerce to mut
2 parents 37e1b80 + 80ce9d1 commit cdf2e7c

File tree

4 files changed

+97
-2
lines changed

4 files changed

+97
-2
lines changed

clippy_lints/src/borrow_deref_ref.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::reference::DEREF_ADDROF;
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::source::SpanRangeExt;
44
use clippy_utils::ty::implements_trait;
5-
use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed};
5+
use clippy_utils::{get_parent_expr, is_from_proc_macro, is_lint_allowed, is_mutable};
66
use rustc_errors::Applicability;
77
use rustc_hir::{BorrowKind, ExprKind, UnOp};
88
use rustc_lint::{LateContext, LateLintPass};
@@ -73,6 +73,9 @@ impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
7373
}
7474
})
7575
&& !is_from_proc_macro(cx, e)
76+
&& let e_ty = cx.typeck_results().expr_ty_adjusted(e)
77+
// check if the reference is coercing to a mutable reference
78+
&& (!matches!(e_ty.kind(), ty::Ref(_, _, Mutability::Mut)) || is_mutable(cx, deref_target))
7679
&& let Some(deref_text) = deref_target.span.get_source_text(cx)
7780
{
7881
span_lint_and_then(

tests/ui/borrow_deref_ref.fixed

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,46 @@ fn issue_13584() {
8181
let p = &raw const *s;
8282
let _ = p as *const i8;
8383
}
84+
85+
mod issue_9905 {
86+
use std::{fs, io};
87+
88+
pub enum File {
89+
Stdio,
90+
File(fs::File),
91+
}
92+
93+
impl io::Read for &'_ File {
94+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
95+
match self {
96+
File::Stdio => io::stdin().read(buf),
97+
File::File(file) => (&*file).read(buf),
98+
}
99+
}
100+
}
101+
}
102+
103+
mod issue_11346 {
104+
struct Struct;
105+
106+
impl Struct {
107+
fn foo(self: &mut &Self) {}
108+
}
109+
110+
trait Trait {
111+
fn bar(&mut self) {}
112+
}
113+
114+
impl Trait for &Struct {}
115+
116+
fn bar() {
117+
let s = &Struct;
118+
(&*s).foo();
119+
(&*s).bar();
120+
121+
let mut s = &Struct;
122+
s.foo(); // To avoid a warning about `s` not needing to be mutable
123+
s.foo();
124+
//~^ borrow_deref_ref
125+
}
126+
}

tests/ui/borrow_deref_ref.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,46 @@ fn issue_13584() {
8181
let p = &raw const *s;
8282
let _ = p as *const i8;
8383
}
84+
85+
mod issue_9905 {
86+
use std::{fs, io};
87+
88+
pub enum File {
89+
Stdio,
90+
File(fs::File),
91+
}
92+
93+
impl io::Read for &'_ File {
94+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
95+
match self {
96+
File::Stdio => io::stdin().read(buf),
97+
File::File(file) => (&*file).read(buf),
98+
}
99+
}
100+
}
101+
}
102+
103+
mod issue_11346 {
104+
struct Struct;
105+
106+
impl Struct {
107+
fn foo(self: &mut &Self) {}
108+
}
109+
110+
trait Trait {
111+
fn bar(&mut self) {}
112+
}
113+
114+
impl Trait for &Struct {}
115+
116+
fn bar() {
117+
let s = &Struct;
118+
(&*s).foo();
119+
(&*s).bar();
120+
121+
let mut s = &Struct;
122+
s.foo(); // To avoid a warning about `s` not needing to be mutable
123+
(&*s).foo();
124+
//~^ borrow_deref_ref
125+
}
126+
}

tests/ui/borrow_deref_ref.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,11 @@ error: deref on an immutable reference
1919
LL | let addr_y = &&*x as *const _ as usize; // assert ok
2020
| ^^^ help: if you would like to reborrow, try removing `&*`: `x`
2121

22-
error: aborting due to 3 previous errors
22+
error: deref on an immutable reference
23+
--> tests/ui/borrow_deref_ref.rs:123:9
24+
|
25+
LL | (&*s).foo();
26+
| ^^^^^ help: if you would like to reborrow, try removing `&*`: `s`
27+
28+
error: aborting due to 4 previous errors
2329

0 commit comments

Comments
 (0)