mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-09 11:48:48 +00:00
303 lines
5.3 KiB
Rust
303 lines
5.3 KiB
Rust
|
use crate::{Diagnostic, DiagnosticsContext, Severity};
|
||
|
|
||
|
// Diagnostic: need-mut
|
||
|
//
|
||
|
// This diagnostic is triggered on mutating an immutable variable.
|
||
|
pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Diagnostic {
|
||
|
Diagnostic::new(
|
||
|
"need-mut",
|
||
|
format!("cannot mutate immutable variable `{}`", d.local.name(ctx.sema.db)),
|
||
|
ctx.sema.diagnostics_display_range(d.span.clone()).range,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// Diagnostic: unused-mut
|
||
|
//
|
||
|
// This diagnostic is triggered when a mutable variable isn't actually mutated.
|
||
|
pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Diagnostic {
|
||
|
Diagnostic::new(
|
||
|
"unused-mut",
|
||
|
"remove this `mut`",
|
||
|
ctx.sema.diagnostics_display_range(d.local.primary_source(ctx.sema.db).syntax_ptr()).range,
|
||
|
)
|
||
|
.severity(Severity::WeakWarning)
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use crate::tests::check_diagnostics;
|
||
|
|
||
|
#[test]
|
||
|
fn unused_mut_simple() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let mut x = 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn no_false_positive_simple() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let x = 2;
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let mut x = 2;
|
||
|
x = 5;
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn field_mutate() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let mut x = (2, 7);
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
f(x.1);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let mut x = (2, 7);
|
||
|
x.0 = 5;
|
||
|
f(x.1);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let x = (2, 7);
|
||
|
x.0 = 5;
|
||
|
//^^^^^^^ error: cannot mutate immutable variable `x`
|
||
|
f(x.1);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn mutable_reference() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
let mut x = &mut 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
*x = 5;
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
let x = 2;
|
||
|
&mut x;
|
||
|
//^^^^^^ error: cannot mutate immutable variable `x`
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
let x_own = 2;
|
||
|
let ref mut x_ref = x_own;
|
||
|
//^^^^^^^^^^^^^ error: cannot mutate immutable variable `x_own`
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
struct Foo;
|
||
|
impl Foo {
|
||
|
fn method(&mut self, x: i32) {}
|
||
|
}
|
||
|
fn main() {
|
||
|
let x = Foo;
|
||
|
x.method(2);
|
||
|
//^ error: cannot mutate immutable variable `x`
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn match_bindings() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
match (2, 3) {
|
||
|
(x, mut y) => {
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
x = 7;
|
||
|
//^^^^^ error: cannot mutate immutable variable `x`
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn mutation_in_dead_code() {
|
||
|
// This one is interesting. Dead code is not represented at all in the MIR, so
|
||
|
// there would be no mutablility error for locals in dead code. Rustc tries to
|
||
|
// not emit `unused_mut` in this case, but since it works without `mut`, and
|
||
|
// special casing it is not trivial, we emit it.
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
return;
|
||
|
let mut x = 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
&mut x;
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main() {
|
||
|
loop {}
|
||
|
let mut x = 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
&mut x;
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
enum X {}
|
||
|
fn g() -> X {
|
||
|
loop {}
|
||
|
}
|
||
|
fn f() -> ! {
|
||
|
loop {}
|
||
|
}
|
||
|
fn main(b: bool) {
|
||
|
if b {
|
||
|
f();
|
||
|
} else {
|
||
|
g();
|
||
|
}
|
||
|
let mut x = 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
&mut x;
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn main(b: bool) {
|
||
|
if b {
|
||
|
loop {}
|
||
|
} else {
|
||
|
return;
|
||
|
}
|
||
|
let mut x = 2;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
&mut x;
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn initialization_is_not_mutation() {
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let mut x;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
x = 5;
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main(b: bool) {
|
||
|
let mut x;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
if b {
|
||
|
x = 1;
|
||
|
} else {
|
||
|
x = 3;
|
||
|
}
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main(b: bool) {
|
||
|
let x;
|
||
|
if b {
|
||
|
x = 1;
|
||
|
}
|
||
|
x = 3;
|
||
|
//^^^^^ error: cannot mutate immutable variable `x`
|
||
|
f(x);
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
let x;
|
||
|
loop {
|
||
|
x = 1;
|
||
|
//^^^^^ error: cannot mutate immutable variable `x`
|
||
|
f(x);
|
||
|
}
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
check_diagnostics(
|
||
|
r#"
|
||
|
fn f(_: i32) {}
|
||
|
fn main() {
|
||
|
loop {
|
||
|
let mut x = 1;
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
f(x);
|
||
|
if let mut y = 2 {
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
f(y);
|
||
|
}
|
||
|
match 3 {
|
||
|
mut z => f(z),
|
||
|
//^^^^^ weak: remove this `mut`
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
"#,
|
||
|
);
|
||
|
}
|
||
|
}
|