1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
//@aux-build: proc_macros.rs
#![allow(dead_code, unused_variables)]
extern crate proc_macros;
use proc_macros::with_span;
fn main() {}
mod should_lint {
fn one_help() {
let a = &12;
let b = a;
//~^ borrow_deref_ref
let b = &mut bar(&12);
//~^ borrow_deref_ref
}
fn bar(x: &u32) -> &u32 {
x
}
}
// this mod explains why we should not lint `&mut &* (&T)`
mod should_not_lint1 {
fn foo(x: &mut &u32) {
*x = &1;
}
fn main() {
let mut x = &0;
foo(&mut &*x); // should not lint
assert_eq!(*x, 0);
foo(&mut x);
assert_eq!(*x, 1);
}
}
// similar to should_not_lint1
mod should_not_lint2 {
struct S<'a> {
a: &'a u32,
b: u32,
}
fn main() {
let s = S { a: &1, b: 1 };
let x = &mut &*s.a;
*x = &2;
}
}
with_span!(
span
fn just_returning(x: &u32) -> &u32 {
x
}
fn dont_lint_proc_macro() {
let a = &mut &*just_returning(&12);
}
);
// this mod explains why we should not lint `& &* (&T)`
mod false_negative {
fn foo() {
let x = &12;
let addr_x = &x as *const _ as usize;
let addr_y = &x as *const _ as usize; // assert ok
//
//~^^ borrow_deref_ref
// let addr_y = &x as *const _ as usize; // assert fail
assert_ne!(addr_x, addr_y);
}
}
fn issue_13584() {
let s = "Hello, world!\n";
let p = &raw const *s;
let _ = p as *const i8;
}
mod issue_9905 {
use std::{fs, io};
pub enum File {
Stdio,
File(fs::File),
}
impl io::Read for &'_ File {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
File::Stdio => io::stdin().read(buf),
File::File(file) => (&*file).read(buf),
}
}
}
}
mod issue_11346 {
struct Struct;
impl Struct {
fn foo(self: &mut &Self) {}
}
trait Trait {
fn bar(&mut self) {}
}
impl Trait for &Struct {}
fn bar() {
let s = &Struct;
(&*s).foo();
(&*s).bar();
let mut s = &Struct;
s.foo(); // To avoid a warning about `s` not needing to be mutable
s.foo();
//~^ borrow_deref_ref
}
}
fn issue_14934() {
let x: &'static str = "x";
let y = "y".to_string();
{
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = &*x; // Do not lint
*x = &*y;
}
{
let mut x = x;
//~^ borrow_deref_ref
x = &*y;
}
{
#[expect(clippy::toplevel_ref_arg, clippy::needless_borrow)]
let ref x = x;
//~^ borrow_deref_ref
}
{
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = std::convert::identity(x);
//~^ borrow_deref_ref
*x = &*y;
}
{
#[derive(Clone)]
struct S(&'static str);
let s = S("foo");
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = &*s.0; // Do not lint
*x = "bar";
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = s.clone().0;
//~^ borrow_deref_ref
*x = "bar";
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = &*std::convert::identity(&s).0;
*x = "bar";
}
{
let y = &1;
#[expect(clippy::toplevel_ref_arg)]
let ref mut x = { y };
//~^ borrow_deref_ref
}
}
|