2023-06-14 22:17:22 +00:00
|
|
|
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
|
2023-05-18 15:47:06 +00:00
|
|
|
use hir::HirDisplay;
|
|
|
|
|
|
|
|
// Diagnostic: moved-out-of-ref
|
|
|
|
//
|
|
|
|
// This diagnostic is triggered on moving non copy things out of references.
|
|
|
|
pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOfRef) -> Diagnostic {
|
2023-06-14 22:17:22 +00:00
|
|
|
Diagnostic::new_with_syntax_node_ptr(
|
|
|
|
ctx,
|
|
|
|
DiagnosticCode::RustcHardError("E0507"),
|
2023-05-18 15:47:06 +00:00
|
|
|
format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db)),
|
2023-06-14 22:17:22 +00:00
|
|
|
d.span.clone(),
|
2023-05-18 15:47:06 +00:00
|
|
|
)
|
|
|
|
.experimental() // spans are broken, and I'm not sure how precise we can detect copy types
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::tests::check_diagnostics;
|
|
|
|
|
|
|
|
// FIXME: spans are broken
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn move_by_explicit_deref() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
struct X;
|
|
|
|
fn main() {
|
|
|
|
let a = &X;
|
|
|
|
let b = *a;
|
|
|
|
//^ error: cannot move `X` out of reference
|
2023-09-24 20:15:36 +00:00
|
|
|
_ = b;
|
2023-05-18 15:47:06 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn move_out_of_field() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: copy
|
|
|
|
struct X;
|
|
|
|
struct Y(X, i32);
|
|
|
|
fn main() {
|
|
|
|
let a = &Y(X, 5);
|
|
|
|
let b = a.0;
|
|
|
|
//^ error: cannot move `X` out of reference
|
|
|
|
let y = a.1;
|
2023-09-24 20:15:36 +00:00
|
|
|
_ = (b, y);
|
2023-05-18 15:47:06 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn move_out_of_static() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: copy
|
|
|
|
struct X;
|
|
|
|
fn main() {
|
|
|
|
static S: X = X;
|
2023-09-24 20:15:36 +00:00
|
|
|
let _s = S;
|
|
|
|
//^^ error: cannot move `X` out of reference
|
2023-05-18 15:47:06 +00:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn generic_types() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: derive, copy
|
|
|
|
|
|
|
|
#[derive(Copy)]
|
|
|
|
struct X<T>(T);
|
|
|
|
struct Y;
|
|
|
|
|
|
|
|
fn consume<T>(_: X<T>) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let a = &X(Y);
|
|
|
|
consume(*a);
|
|
|
|
//^^^^^^^^^^^ error: cannot move `X<Y>` out of reference
|
|
|
|
let a = &X(5);
|
|
|
|
consume(*a);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_false_positive_simple() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: copy
|
|
|
|
fn f(_: i32) {}
|
|
|
|
fn main() {
|
|
|
|
let x = &2;
|
|
|
|
f(*x);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_false_positive_unknown_type() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: derive, copy
|
|
|
|
fn f(x: &Unknown) -> Unknown {
|
|
|
|
*x
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy)]
|
|
|
|
struct X<T>(T);
|
|
|
|
|
|
|
|
struct Y<T>(T);
|
|
|
|
|
|
|
|
fn g(x: &X<Unknown>) -> X<Unknown> {
|
|
|
|
*x
|
|
|
|
}
|
|
|
|
|
|
|
|
fn h(x: &Y<Unknown>) -> Y<Unknown> {
|
|
|
|
// FIXME: we should show error for this, as `Y` is not copy
|
|
|
|
// regardless of its generic parameter.
|
|
|
|
*x
|
|
|
|
}
|
|
|
|
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_false_positive_dyn_fn() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: copy, fn
|
|
|
|
fn f(x: &mut &mut dyn Fn()) {
|
|
|
|
x();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct X<'a> {
|
|
|
|
field: &'a mut dyn Fn(),
|
|
|
|
}
|
|
|
|
|
|
|
|
fn f(x: &mut X<'_>) {
|
|
|
|
(x.field)();
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
2023-05-19 08:30:19 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_false_positive_match_and_closure_capture() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: copy, fn
|
|
|
|
enum X {
|
|
|
|
Foo(u16),
|
|
|
|
Bar,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let x = &X::Bar;
|
2023-09-24 20:15:36 +00:00
|
|
|
let _c = || match *x {
|
2023-05-19 08:30:19 +00:00
|
|
|
X::Foo(t) => t,
|
|
|
|
_ => 5,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
2023-10-22 20:04:27 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn regression_15787() {
|
|
|
|
check_diagnostics(
|
|
|
|
r#"
|
|
|
|
//- minicore: coerce_unsized, slice, copy
|
|
|
|
fn foo(mut slice: &[u32]) -> usize {
|
|
|
|
slice = match slice {
|
|
|
|
[0, rest @ ..] | rest => rest,
|
|
|
|
};
|
|
|
|
slice.len()
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
2023-05-18 15:47:06 +00:00
|
|
|
}
|