ide_diagnostics/handlers/
moved_out_of_ref.rs1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2use hir::HirDisplay;
3
4pub(crate) fn moved_out_of_ref(
8 ctx: &DiagnosticsContext<'_>,
9 d: &hir::MovedOutOfRef<'_>,
10) -> Diagnostic {
11 Diagnostic::new_with_syntax_node_ptr(
12 ctx,
13 DiagnosticCode::RustcHardError("E0507"),
14 format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.display_target)),
15 d.span,
16 )
17 }
19
20#[cfg(test)]
21mod tests {
22 use crate::tests::check_diagnostics;
23
24 #[test]
25 fn operand_field_span_respected() {
26 check_diagnostics(
27 r#"
28struct NotCopy;
29struct S {
30 field: NotCopy,
31}
32
33fn f(s: &S) -> S {
34 S { field: s.field }
35 //^^^^^^^ error: cannot move `NotCopy` out of reference
36}
37 "#,
38 );
39 }
40
41 #[test]
42 fn move_by_explicit_deref() {
43 check_diagnostics(
44 r#"
45struct X;
46fn main() {
47 let a = &X;
48 let b = *a;
49 //^ error: cannot move `X` out of reference
50 _ = b;
51}
52"#,
53 );
54 }
55
56 #[test]
57 fn move_out_of_field() {
58 check_diagnostics(
59 r#"
60//- minicore: copy
61struct X;
62struct Y(X, i32);
63fn main() {
64 let a = &Y(X, 5);
65 let b = a.0;
66 //^ error: cannot move `X` out of reference
67 let y = a.1;
68 _ = (b, y);
69}
70"#,
71 );
72 }
73
74 #[test]
75 fn move_out_of_static() {
76 check_diagnostics(
77 r#"
78//- minicore: copy
79struct X;
80fn main() {
81 static S: X = X;
82 let _s = S;
83 //^^ error: cannot move `X` out of reference
84}
85"#,
86 );
87 }
88
89 #[test]
90 fn generic_types() {
91 check_diagnostics(
92 r#"
93//- minicore: derive, copy
94
95#[derive(Copy)]
96struct X<T>(T);
97struct Y;
98
99fn consume<T>(_: X<T>) {
100
101}
102
103fn main() {
104 let a = &X(Y);
105 consume(*a);
106 //^^ error: cannot move `X<Y>` out of reference
107 let a = &X(5);
108 consume(*a);
109}
110"#,
111 );
112 }
113
114 #[test]
115 fn no_false_positive_simple() {
116 check_diagnostics(
117 r#"
118//- minicore: copy
119fn f(_: i32) {}
120fn main() {
121 let x = &2;
122 f(*x);
123}
124"#,
125 );
126 }
127
128 #[test]
129 fn no_false_positive_unknown_type() {
130 check_diagnostics(
131 r#"
132//- minicore: derive, copy
133fn f(x: &Unknown) -> Unknown {
134 *x
135}
136
137#[derive(Copy)]
138struct X<T>(T);
139
140struct Y<T>(T);
141
142fn g(x: &X<Unknown>) -> X<Unknown> {
143 *x
144}
145
146fn h(x: &Y<Unknown>) -> Y<Unknown> {
147 // FIXME: we should show error for this, as `Y` is not copy
148 // regardless of its generic parameter.
149 *x
150}
151
152"#,
153 );
154 }
155
156 #[test]
157 fn no_false_positive_dyn_fn() {
158 check_diagnostics(
159 r#"
160//- minicore: copy, fn, dispatch_from_dyn
161fn f(x: &mut &mut dyn Fn()) {
162 x();
163}
164
165struct X<'a> {
166 field: &'a mut dyn Fn(),
167}
168
169fn g(x: &mut X<'_>) {
170 (x.field)();
171}
172"#,
173 );
174 }
175
176 #[test]
177 fn no_false_positive_match_and_closure_capture() {
178 check_diagnostics(
179 r#"
180//- minicore: copy, fn
181enum X {
182 Foo(u16),
183 Bar,
184}
185
186fn main() {
187 let x = &X::Bar;
188 let _c = || match *x {
189 X::Foo(t) => t,
190 _ => 5,
191 };
192}
193 "#,
194 );
195 }
196
197 #[test]
198 fn regression_15787() {
199 check_diagnostics(
200 r#"
201//- minicore: coerce_unsized, slice, copy
202fn foo(mut slice: &[u32]) -> usize {
203 slice = match slice {
204 [0, rest @ ..] | rest => rest,
205 };
206 slice.len()
207}
208"#,
209 );
210 }
211
212 #[test]
213 fn regression_16564() {
214 check_diagnostics(
215 r#"
216//- minicore: copy
217fn test() {
218 let _x = (&(&mut (),)).0 as *const ();
219}
220 "#,
221 )
222 }
223
224 #[test]
225 fn regression_18201() {
226 check_diagnostics(
227 r#"
228//- minicore: copy
229struct NotCopy;
230struct S(NotCopy);
231impl S {
232 fn f(&mut self) {
233 || {
234 if let ref mut _cb = self.0 {
235 }
236 };
237 }
238}
239"#,
240 )
241 }
242
243 #[test]
244 fn regression_20155() {
245 check_diagnostics(
246 r#"
247//- minicore: copy, option
248struct Box(i32);
249fn test() {
250 let b = Some(Box(0));
251 || {
252 if let Some(b) = b {
253 let _move = b;
254 }
255 };
256}
257"#,
258 )
259 }
260}