Skip to main content

ide_diagnostics/handlers/
mutability_errors.rs

1use hir::db::ExpandDatabase;
2use ide_db::source_change::SourceChange;
3use ide_db::text_edit::TextEdit;
4use syntax::{AstNode, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, T, ast};
5
6use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, fix};
7
8// Diagnostic: need-mut
9//
10// This diagnostic is triggered on mutating an immutable variable.
11pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_, '_>, d: &hir::NeedMut) -> Option<Diagnostic> {
12    let root = ctx.sema.db.parse_or_expand(d.span.file_id);
13    let node = d.span.value.to_node(&root);
14    let mut span = d.span;
15    if let Some(parent) = node.parent()
16        && ast::BinExpr::can_cast(parent.kind())
17    {
18        // In case of an assignment, the diagnostic is provided on the variable name.
19        // We want to expand it to include the whole assignment, but only when this
20        // is an ordinary assignment, not a destructuring assignment. So, the direct
21        // parent is an assignment expression.
22        span = d.span.with_value(SyntaxNodePtr::new(&parent));
23    };
24
25    let fixes = (|| {
26        if d.local.is_ref(ctx.sema.db) {
27            // There is no simple way to add `mut` to `ref x` and `ref mut x`
28            return None;
29        }
30        let file_id = span.file_id.file_id()?;
31        let mut edit_builder = TextEdit::builder();
32        let use_range = span.value.text_range();
33        for source in d.local.sources(ctx.sema.db) {
34            let Some(ast) = source.name() else { continue };
35            // FIXME: macros
36            edit_builder.insert(ast.value.syntax().text_range().start(), "mut ".to_owned());
37        }
38        let edit = edit_builder.finish();
39        Some(vec![fix(
40            "add_mut",
41            "Change it to be mutable",
42            SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit),
43            use_range,
44        )])
45    })();
46
47    Some(
48        Diagnostic::new_with_syntax_node_ptr(
49            ctx,
50            // FIXME: `E0384` is not the only error that this diagnostic handles
51            DiagnosticCode::RustcHardError("E0384"),
52            format!(
53                "cannot mutate immutable variable `{}`",
54                d.local.name(ctx.sema.db).display(ctx.sema.db, ctx.edition)
55            ),
56            span,
57        )
58        .stable()
59        .with_fixes(fixes),
60    )
61}
62
63// Diagnostic: unused-mut
64//
65// This diagnostic is triggered when a mutable variable isn't actually mutated.
66pub(crate) fn unused_mut(
67    ctx: &DiagnosticsContext<'_, '_>,
68    d: &hir::UnusedMut,
69) -> Option<Diagnostic> {
70    let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
71    let fixes = (|| {
72        let file_id = ast.file_id.file_id()?;
73        let mut edit_builder = TextEdit::builder();
74        let use_range = ast.value.text_range();
75        for source in d.local.sources(ctx.sema.db) {
76            let ast = source.syntax();
77            let Some(mut_token) = token(ast, T![mut]) else { continue };
78            edit_builder.delete(mut_token.text_range());
79            if let Some(token) = mut_token.next_token()
80                && token.kind() == SyntaxKind::WHITESPACE
81            {
82                edit_builder.delete(token.text_range());
83            }
84        }
85        let edit = edit_builder.finish();
86        Some(vec![fix(
87            "remove_mut",
88            "Remove unnecessary `mut`",
89            SourceChange::from_text_edit(file_id.file_id(ctx.sema.db), edit),
90            use_range,
91        )])
92    })();
93    Some(
94        Diagnostic::new_with_syntax_node_ptr(
95            ctx,
96            DiagnosticCode::RustcLint("unused_mut"),
97            "variable does not need to be mutable",
98            ast,
99        )
100        // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive, hence not stable.
101        .with_fixes(fixes),
102    )
103}
104
105pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
106    parent.children_with_tokens().filter_map(|it| it.into_token()).find(|it| it.kind() == kind)
107}
108
109#[cfg(test)]
110mod tests {
111    use crate::tests::{check_diagnostics, check_diagnostics_with_disabled, check_fix};
112
113    #[test]
114    fn unused_mut_simple() {
115        check_diagnostics(
116            r#"
117fn f(_: i32) {}
118fn main() {
119    let mut x = 2;
120      //^^^^^ 💡 warn: variable does not need to be mutable
121    f(x);
122}
123"#,
124        );
125    }
126
127    #[test]
128    fn no_false_positive_simple() {
129        check_diagnostics(
130            r#"
131fn f(_: i32) {}
132fn main() {
133    let x = 2;
134    f(x);
135}
136"#,
137        );
138        check_diagnostics(
139            r#"
140fn f(_: i32) {}
141fn main() {
142    let mut x = 2;
143    x = 5;
144    f(x);
145}
146"#,
147        );
148    }
149
150    #[test]
151    fn multiple_errors_for_single_variable() {
152        check_diagnostics(
153            r#"
154fn f(_: i32) {}
155fn main() {
156    let x = 2;
157    x = 10;
158  //^^^^^^ 💡 error: cannot mutate immutable variable `x`
159    x = 5;
160  //^^^^^ 💡 error: cannot mutate immutable variable `x`
161    &mut x;
162  //^^^^^^ 💡 error: cannot mutate immutable variable `x`
163    f(x);
164}
165"#,
166        );
167    }
168
169    #[test]
170    fn unused_mut_fix() {
171        check_fix(
172            r#"
173fn f(_: i32) {}
174fn main() {
175    let mu$0t x = 2;
176    f(x);
177}
178"#,
179            r#"
180fn f(_: i32) {}
181fn main() {
182    let x = 2;
183    f(x);
184}
185"#,
186        );
187        check_fix(
188            r#"
189fn f(_: i32) {}
190fn main() {
191    let ((mu$0t x, _) | (_, mut x)) = (2, 3);
192    f(x);
193}
194"#,
195            r#"
196fn f(_: i32) {}
197fn main() {
198    let ((x, _) | (_, x)) = (2, 3);
199    f(x);
200}
201"#,
202        );
203    }
204
205    #[test]
206    fn need_mut_fix() {
207        check_fix(
208            r#"
209fn f(_: i32) {}
210fn main() {
211    let x = 2;
212    x$0 = 5;
213    f(x);
214}
215"#,
216            r#"
217fn f(_: i32) {}
218fn main() {
219    let mut x = 2;
220    x = 5;
221    f(x);
222}
223"#,
224        );
225        check_fix(
226            r#"
227fn f(_: i32) {}
228fn main() {
229    let ((x, _) | (_, x)) = (2, 3);
230    x =$0 4;
231    f(x);
232}
233"#,
234            r#"
235fn f(_: i32) {}
236fn main() {
237    let ((mut x, _) | (_, mut x)) = (2, 3);
238    x = 4;
239    f(x);
240}
241"#,
242        );
243
244        check_fix(
245            r#"
246struct Foo(i32);
247
248impl Foo {
249    fn foo(self) {
250        self = Fo$0o(5);
251    }
252}
253"#,
254            r#"
255struct Foo(i32);
256
257impl Foo {
258    fn foo(mut self) {
259        self = Foo(5);
260    }
261}
262"#,
263        );
264    }
265
266    #[test]
267    fn need_mut_fix_not_applicable_on_ref() {
268        check_diagnostics(
269            r#"
270fn main() {
271    let ref x = 2;
272    x = &5;
273  //^^^^^^ error: cannot mutate immutable variable `x`
274}
275"#,
276        );
277        check_diagnostics(
278            r#"
279fn main() {
280    let ref mut x = 2;
281    x = &mut 5;
282  //^^^^^^^^^^ error: cannot mutate immutable variable `x`
283}
284"#,
285        );
286    }
287
288    #[test]
289    fn field_mutate() {
290        check_diagnostics(
291            r#"
292fn f(_: i32) {}
293fn main() {
294    let mut x = (2, 7);
295      //^^^^^ 💡 warn: variable does not need to be mutable
296    f(x.1);
297}
298"#,
299        );
300        check_diagnostics(
301            r#"
302fn f(_: i32) {}
303fn main() {
304    let mut x = (2, 7);
305    x.0 = 5;
306    f(x.1);
307}
308"#,
309        );
310        check_diagnostics(
311            r#"
312fn f(_: i32) {}
313fn main() {
314    let x = (2, 7);
315    x.0 = 5;
316  //^^^^^^^ 💡 error: cannot mutate immutable variable `x`
317    f(x.1);
318}
319"#,
320        );
321    }
322
323    #[test]
324    fn mutable_reference() {
325        check_diagnostics(
326            r#"
327fn main() {
328    let mut x = &mut 2;
329      //^^^^^ 💡 warn: variable does not need to be mutable
330    *x = 5;
331}
332"#,
333        );
334        check_diagnostics(
335            r#"
336fn main() {
337    let x = 2;
338    &mut x;
339  //^^^^^^ 💡 error: cannot mutate immutable variable `x`
340}
341"#,
342        );
343        check_diagnostics(
344            r#"
345fn main() {
346    let x_own = 2;
347    let ref mut x_ref = x_own;
348      //^^^^^^^^^^^^^ 💡 error: cannot mutate immutable variable `x_own`
349    _ = x_ref;
350}
351"#,
352        );
353        check_diagnostics(
354            r#"
355struct Foo;
356impl Foo {
357    fn method(&mut self, _x: i32) {}
358}
359fn main() {
360    let x = Foo;
361    x.method(2);
362  //^ 💡 error: cannot mutate immutable variable `x`
363}
364"#,
365        );
366    }
367
368    #[test]
369    fn regression_14310() {
370        check_diagnostics(
371            r#"
372            //- minicore: copy, builtin_impls
373            fn clone(mut i: &!) -> ! {
374                   //^^^^^ 💡 warn: variable does not need to be mutable
375                *i
376            }
377        "#,
378        );
379    }
380
381    #[test]
382    fn match_closure_capture() {
383        check_diagnostics(
384            r#"
385//- minicore: option
386fn main() {
387    let mut v = &mut Some(2);
388      //^^^^^ 💡 warn: variable does not need to be mutable
389    let _ = || match v {
390        Some(k) => {
391            *k = 5;
392        }
393        None => {}
394    };
395    let v = &mut Some(2);
396    let _ = || match v {
397                   //^ 💡 error: cannot mutate immutable variable `v`
398        ref mut k => {
399            *k = &mut Some(5);
400        }
401    };
402}
403"#,
404        );
405    }
406
407    #[test]
408    fn match_bindings() {
409        check_diagnostics(
410            r#"
411fn main() {
412    match (2, 3) {
413        (x, mut y) => {
414          //^^^^^ 💡 warn: variable does not need to be mutable
415            x = 7;
416          //^^^^^ 💡 error: cannot mutate immutable variable `x`
417            _ = y;
418        }
419    }
420}
421"#,
422        );
423    }
424
425    #[test]
426    fn mutation_in_dead_code() {
427        // This one is interesting. Dead code is not represented at all in the MIR, so
428        // there would be no mutability error for locals in dead code. Rustc tries to
429        // not emit `unused_mut` in this case, but since it works without `mut`, and
430        // special casing it is not trivial, we emit it.
431
432        // Update: now MIR based `unused-variable` is taking over `unused-mut` for the same reason.
433        check_diagnostics(
434            r#"
435fn main() {
436    return;
437    let mut x = 2;
438      //^^^^^ 💡 warn: unused variable
439    &mut x;
440}
441"#,
442        );
443        check_diagnostics(
444            r#"
445fn main() {
446    loop {}
447    let mut x = 2;
448      //^^^^^ 💡 warn: unused variable
449    &mut x;
450}
451"#,
452        );
453        check_diagnostics_with_disabled(
454            r#"
455enum X {}
456fn g() -> X {
457    loop {}
458}
459fn f() -> ! {
460    loop {}
461}
462fn main(b: bool) {
463    if b {
464        f();
465    } else {
466        g();
467    }
468    let mut x = 2;
469      //^^^^^ 💡 warn: unused variable
470    &mut x;
471}
472"#,
473            &["remove-unnecessary-else"],
474        );
475        check_diagnostics_with_disabled(
476            r#"
477fn main(b: bool) {
478    if b {
479        loop {}
480    } else {
481        return;
482    }
483    let mut x = 2;
484      //^^^^^ 💡 warn: unused variable
485    &mut x;
486}
487"#,
488            &["remove-unnecessary-else"],
489        );
490    }
491
492    #[test]
493    fn initialization_is_not_mutation() {
494        check_diagnostics(
495            r#"
496fn f(_: i32) {}
497fn main() {
498    let mut x;
499      //^^^^^ 💡 warn: variable does not need to be mutable
500    x = 5;
501    f(x);
502}
503"#,
504        );
505        check_diagnostics(
506            r#"
507fn f(_: i32) {}
508fn main(b: bool) {
509    let mut x;
510      //^^^^^ 💡 warn: variable does not need to be mutable
511    if b {
512        x = 1;
513    } else {
514        x = 3;
515    }
516    f(x);
517}
518"#,
519        );
520        check_diagnostics(
521            r#"
522fn f(_: i32) {}
523fn main(b: bool) {
524    let x;
525    if b {
526        x = 1;
527    }
528    x = 3;
529  //^^^^^ 💡 error: cannot mutate immutable variable `x`
530    f(x);
531}
532"#,
533        );
534        check_diagnostics(
535            r#"
536fn f(_: i32) {}
537fn main() {
538    let x;
539    loop {
540        x = 1;
541      //^^^^^ 💡 error: cannot mutate immutable variable `x`
542        f(x);
543    }
544}
545"#,
546        );
547        check_diagnostics(
548            r#"
549fn check(_: i32) -> bool {
550    false
551}
552fn main() {
553    loop {
554        let x = 1;
555        if check(x) {
556            break;
557        }
558        let y = (1, 2);
559        if check(y.1) {
560            return;
561        }
562        let z = (1, 2);
563        match z {
564            (k @ 5, ref mut t) if { continue; } => {
565                  //^^^^^^^^^ 💡 error: cannot mutate immutable variable `z`
566                *t = 5;
567                _ = k;
568            }
569            _ => {
570                let y = (1, 2);
571                if check(y.1) {
572                    return;
573                }
574            }
575        }
576    }
577}
578"#,
579        );
580        check_diagnostics(
581            r#"
582fn f(_: i32) {}
583fn main() {
584    loop {
585        let mut x = 1;
586          //^^^^^ 💡 warn: variable does not need to be mutable
587        f(x);
588        if let mut y = 2 {
589             //^^^^^ 💡 warn: variable does not need to be mutable
590            f(y);
591        }
592        match 3 {
593            mut z => f(z),
594          //^^^^^ 💡 warn: variable does not need to be mutable
595        }
596    }
597}
598"#,
599        );
600    }
601
602    #[test]
603    fn initialization_is_not_mutation_in_loop() {
604        check_diagnostics(
605            r#"
606fn main() {
607    let a;
608    loop {
609        let c @ (
610            mut b,
611          //^^^^^ 💡 warn: variable does not need to be mutable
612            mut d
613          //^^^^^ 💡 warn: variable does not need to be mutable
614        );
615        a = 1;
616      //^^^^^ 💡 error: cannot mutate immutable variable `a`
617        b = 1;
618        c = (2, 3);
619        d = 3;
620        _ = (c, b, d);
621    }
622}
623"#,
624        );
625    }
626
627    #[test]
628    fn function_arguments_are_initialized() {
629        check_diagnostics(
630            r#"
631fn f(mut x: i32) {
632   //^^^^^ 💡 warn: variable does not need to be mutable
633   f(x + 2);
634}
635"#,
636        );
637        check_diagnostics(
638            r#"
639fn f(x: i32) {
640   x = 5;
641 //^^^^^ 💡 error: cannot mutate immutable variable `x`
642}
643"#,
644        );
645        check_diagnostics(
646            r#"
647fn f((x, y): (i32, i32)) {
648    let t = [0; 2];
649    x = 5;
650  //^^^^^ 💡 error: cannot mutate immutable variable `x`
651    _ = x;
652    _ = y;
653    _ = t;
654}
655"#,
656        );
657    }
658
659    #[test]
660    fn no_diagnostics_in_case_of_multiple_bounds() {
661        check_diagnostics(
662            r#"
663fn f() {
664    let (b, a, b) = (2, 3, 5);
665    a = 8;
666  //^^^^^ 💡 error: cannot mutate immutable variable `a`
667}
668"#,
669        );
670    }
671
672    #[test]
673    fn for_loop() {
674        check_diagnostics(
675            r#"
676//- minicore: iterators, copy
677fn f(x: [(i32, u8); 10]) {
678    for (a, mut b) in x {
679          //^^^^^ 💡 warn: variable does not need to be mutable
680        a = 2;
681      //^^^^^ 💡 error: cannot mutate immutable variable `a`
682        _ = b;
683    }
684}
685"#,
686        );
687    }
688
689    #[test]
690    fn while_let() {
691        check_diagnostics(
692            r#"
693//- minicore: iterators, copy
694fn f(x: [(i32, u8); 10]) {
695    let mut it = x.into_iter();
696    while let Some((a, mut b)) = it.next() {
697                     //^^^^^ 💡 warn: variable does not need to be mutable
698        while let Some((c, mut d)) = it.next() {
699                         //^^^^^ 💡 warn: variable does not need to be mutable
700            a = 2;
701          //^^^^^ 💡 error: cannot mutate immutable variable `a`
702            c = 2;
703          //^^^^^ 💡 error: cannot mutate immutable variable `c`
704            _ = (b, d);
705        }
706    }
707}
708"#,
709        );
710    }
711
712    #[test]
713    fn index() {
714        check_diagnostics(
715            r#"
716//- minicore: coerce_unsized, index, slice
717fn f() {
718    let x = [1, 2, 3];
719    x[2] = 5;
720  //^^^^^^^^ 💡 error: cannot mutate immutable variable `x`
721    let x = &mut x;
722          //^^^^^^ 💡 error: cannot mutate immutable variable `x`
723    let mut x = x;
724      //^^^^^ 💡 warn: variable does not need to be mutable
725    x[2] = 5;
726}
727"#,
728        );
729    }
730
731    #[test]
732    fn overloaded_index() {
733        check_diagnostics(
734            r#"
735//- minicore: index, copy
736use core::ops::{Index, IndexMut};
737
738struct Foo;
739impl Index<usize> for Foo {
740    type Output = (i32, u8);
741    fn index(&self, _index: usize) -> &(i32, u8) {
742        &(5, 2)
743    }
744}
745impl IndexMut<usize> for Foo {
746    fn index_mut(&mut self, _index: usize) -> &mut (i32, u8) {
747        &mut (5, 2)
748    }
749}
750fn f() {
751    let mut x = Foo;
752      //^^^^^ 💡 warn: variable does not need to be mutable
753    let y = &x[2];
754    _ = (x, y);
755    let x = Foo;
756    let y = &mut x[2];
757               //^💡 error: cannot mutate immutable variable `x`
758    _ = (x, y);
759    let mut x = &mut Foo;
760      //^^^^^ 💡 warn: variable does not need to be mutable
761    let y: &mut (i32, u8) = &mut x[2];
762    _ = (x, y);
763    let x = Foo;
764    let ref mut y = x[7];
765                  //^ 💡 error: cannot mutate immutable variable `x`
766    _ = (x, y);
767    let (ref mut y, _) = x[3];
768                       //^ 💡 error: cannot mutate immutable variable `x`
769    _ = y;
770    match x[10] {
771        //^ 💡 error: cannot mutate immutable variable `x`
772        (ref y, 5) => _ = y,
773        (_, ref mut y) => _ = y,
774    }
775    let mut x = Foo;
776    let mut i = 5;
777      //^^^^^ 💡 warn: variable does not need to be mutable
778    let y = &mut x[i];
779    _ = y;
780}
781"#,
782        );
783    }
784
785    #[test]
786    fn overloaded_deref() {
787        check_diagnostics(
788            r#"
789//- minicore: deref_mut, copy
790use core::ops::{Deref, DerefMut};
791
792struct Foo;
793impl Deref for Foo {
794    type Target = (i32, u8);
795    fn deref(&self) -> &(i32, u8) {
796        &(5, 2)
797    }
798}
799impl DerefMut for Foo {
800    fn deref_mut(&mut self) -> &mut (i32, u8) {
801        &mut (5, 2)
802    }
803}
804fn f() {
805    let mut x = Foo;
806      //^^^^^ 💡 warn: variable does not need to be mutable
807    let y = &*x;
808    _ = (x, y);
809    let x = Foo;
810    let y = &mut *x;
811               // ^ 💡 error: cannot mutate immutable variable `x`
812    _ = (x, y);
813    let x = Foo;
814      //^ 💡 warn: unused variable
815    let x = Foo;
816    let y: &mut (i32, u8) = &mut x;
817                          //^^^^^^ 💡 error: cannot mutate immutable variable `x`
818    _ = (x, y);
819    let ref mut y = *x;
820                  // ^ 💡 error: cannot mutate immutable variable `x`
821    _ = y;
822    let (ref mut y, _) = *x;
823                       // ^ 💡 error: cannot mutate immutable variable `x`
824    _ = y;
825    match *x {
826        // ^ 💡 error: cannot mutate immutable variable `x`
827        (ref y, 5) => _ = y,
828        (_, ref mut y) => _ = y,
829    }
830}
831"#,
832        );
833    }
834
835    #[test]
836    fn or_pattern() {
837        check_diagnostics(
838            r#"
839//- minicore: option
840fn f(_: i32) {}
841fn main() {
842    let ((Some(mut x), None) | (_, Some(mut x))) = (None, Some(7)) else { return };
843             //^^^^^ 💡 warn: variable does not need to be mutable
844
845    f(x);
846}
847"#,
848        );
849        check_diagnostics(
850            r#"
851struct Foo(i32);
852
853const X: Foo = Foo(5);
854const Y: Foo = Foo(12);
855
856const fn f(mut a: Foo) -> bool {
857         //^^^^^ 💡 warn: variable does not need to be mutable
858    match a {
859        X | Y => true,
860        _ => false,
861    }
862}
863"#,
864        );
865    }
866
867    #[test]
868    fn or_pattern_no_terminator() {
869        check_diagnostics(
870            r#"
871enum Foo {
872    A, B, C, D
873}
874
875use Foo::*;
876
877fn f(inp: (Foo, Foo, Foo, Foo)) {
878    let ((A, B, _, x) | (B, C | D, x, _)) = inp else {
879        return;
880    };
881    x = B;
882  //^^^^^ 💡 error: cannot mutate immutable variable `x`
883}
884"#,
885        );
886    }
887
888    #[test]
889    // FIXME: We should have tests for `is_ty_uninhabited_from`
890    fn regression_14421() {
891        check_diagnostics(
892            r#"
893pub enum Tree {
894    Node(TreeNode),
895    Leaf(TreeLeaf),
896}
897
898struct Box<T>(&T);
899
900pub struct TreeNode {
901    pub depth: usize,
902    pub children: [Box<Tree>; 8]
903}
904
905pub struct TreeLeaf {
906    pub depth: usize,
907    pub data: u8
908}
909
910pub fn test() {
911    let mut tree = Tree::Leaf(
912      //^^^^^^^^ 💡 warn: variable does not need to be mutable
913        TreeLeaf {
914            depth: 0,
915            data: 0
916        }
917    );
918    _ = tree;
919}
920"#,
921        );
922    }
923
924    #[test]
925    fn fn_traits() {
926        check_diagnostics(
927            r#"
928//- minicore: fn
929fn fn_ref(mut x: impl Fn(u8) -> u8) -> u8 {
930        //^^^^^ 💡 warn: variable does not need to be mutable
931    x(2)
932}
933fn fn_mut(x: impl FnMut(u8) -> u8) -> u8 {
934    x(2)
935  //^ 💡 error: cannot mutate immutable variable `x`
936}
937fn fn_borrow_mut(mut x: &mut impl FnMut(u8) -> u8) -> u8 {
938               //^^^^^ 💡 warn: variable does not need to be mutable
939    x(2)
940}
941fn fn_once(mut x: impl FnOnce(u8) -> u8) -> u8 {
942         //^^^^^ 💡 warn: variable does not need to be mutable
943    x(2)
944}
945"#,
946        );
947    }
948
949    #[test]
950    fn closure() {
951        check_diagnostics(
952            r#"
953        //- minicore: copy, fn
954        struct X;
955
956        impl X {
957            fn mutate(&mut self) {}
958        }
959
960        fn f() {
961            let x = 5;
962            let closure1 = || { x = 2; };
963                              //^^^^^ 💡 error: cannot mutate immutable variable `x`
964            let _ = closure1();
965                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
966            let closure2 = || { x = x; };
967                              //^^^^^ 💡 error: cannot mutate immutable variable `x`
968            let closure3 = || {
969                let x = 2;
970                x = 5;
971              //^^^^^ 💡 error: cannot mutate immutable variable `x`
972                x
973            };
974            let x = X;
975            let closure4 = || { x.mutate(); };
976                              //^ 💡 error: cannot mutate immutable variable `x`
977            _ = (closure2, closure3, closure4);
978        }
979                    "#,
980        );
981        check_diagnostics(
982            r#"
983        //- minicore: copy, fn
984        fn f() {
985            let mut x = 5;
986              //^^^^^ 💡 warn: variable does not need to be mutable
987            let mut y = 2;
988            y = 7;
989            let closure = || {
990                let mut z = 8;
991                z = 3;
992                let mut k = z;
993                  //^^^^^ 💡 warn: variable does not need to be mutable
994                _ = k;
995            };
996            _ = (x, closure);
997        }
998                    "#,
999        );
1000        check_diagnostics(
1001            r#"
1002//- minicore: copy, fn
1003fn f() {
1004    let closure = || {
1005        || {
1006            || {
1007                let x = 2;
1008                || { || { x = 5; } }
1009                        //^^^^^ 💡 error: cannot mutate immutable variable `x`
1010            }
1011        }
1012    };
1013    _ = closure;
1014}
1015            "#,
1016        );
1017        check_diagnostics(
1018            r#"
1019//- minicore: copy, fn
1020fn f() {
1021    struct X;
1022    let mut x = X;
1023      //^^^^^ 💡 warn: variable does not need to be mutable
1024    let c1 = || x;
1025    let mut x = X;
1026    let c2 = || { x = X; x };
1027    let mut x = X;
1028    let c3 = move || { x = X; };
1029    _ = (c1, c2, c3);
1030}
1031            "#,
1032        );
1033        check_diagnostics(
1034            r#"
1035        //- minicore: copy, fn, deref_mut
1036        struct X(i32, i64);
1037
1038        fn f() {
1039            let mut x = &mut 5;
1040              //^^^^^ 💡 warn: variable does not need to be mutable
1041            let closure1 = || { *x = 2; };
1042            let _ = closure1();
1043                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
1044            let mut x = &mut 5;
1045              //^^^^^ 💡 warn: variable does not need to be mutable
1046            let closure1 = || { *x = 2; &x; };
1047            let _ = closure1();
1048                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
1049            let mut x = &mut 5;
1050            let closure1 = || { *x = 2; &x; x = &mut 3; };
1051            let _ = closure1();
1052                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
1053            let mut x = &mut 5;
1054              //^^^^^ 💡 warn: variable does not need to be mutable
1055            let closure1 = move || { *x = 2; };
1056            let _ = closure1();
1057                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
1058            let mut x = &mut X(1, 2);
1059              //^^^^^ 💡 warn: variable does not need to be mutable
1060            let closure1 = || { x.0 = 2; };
1061            let _ = closure1();
1062                  //^^^^^^^^ 💡 error: cannot mutate immutable variable `closure1`
1063        }
1064                    "#,
1065        );
1066    }
1067
1068    #[test]
1069    fn slice_pattern() {
1070        check_diagnostics(
1071            r#"
1072//- minicore: coerce_unsized, deref_mut, slice, copy
1073fn x(t: &[u8]) {
1074    match t {
1075        &[a, mut b] | &[a, _, mut b] => {
1076           //^^^^^ 💡 warn: variable does not need to be mutable
1077
1078            a = 2;
1079          //^^^^^ 💡 error: cannot mutate immutable variable `a`
1080            _ = b;
1081        }
1082        _ => {}
1083    }
1084}
1085            "#,
1086        );
1087    }
1088
1089    #[test]
1090    fn boxes() {
1091        check_diagnostics(
1092            r#"
1093//- minicore: coerce_unsized, deref_mut, slice
1094use core::ops::{Deref, DerefMut};
1095use core::{marker::Unsize, ops::CoerceUnsized};
1096
1097#[lang = "owned_box"]
1098pub struct Box<T: ?Sized> {
1099    inner: *mut T,
1100}
1101impl<T> Box<T> {
1102    fn new(t: T) -> Self {
1103        #[rustc_box]
1104        Box::new(t)
1105    }
1106}
1107
1108impl<T: ?Sized> Deref for Box<T> {
1109    type Target = T;
1110
1111    fn deref(&self) -> &T {
1112        &**self
1113    }
1114}
1115
1116impl<T: ?Sized> DerefMut for Box<T> {
1117    fn deref_mut(&mut self) -> &mut T {
1118        &mut **self
1119    }
1120}
1121
1122fn f() {
1123    let x = Box::new(5);
1124    x = Box::new(7);
1125  //^^^^^^^^^^^^^^^ 💡 error: cannot mutate immutable variable `x`
1126    let x = Box::new(5);
1127    *x = 7;
1128  //^^^^^^ 💡 error: cannot mutate immutable variable `x`
1129    let mut y = Box::new(5);
1130      //^^^^^ 💡 warn: variable does not need to be mutable
1131    *x = *y;
1132  //^^^^^^^ 💡 error: cannot mutate immutable variable `x`
1133    let x = Box::new(5);
1134    let closure = || *x = 2;
1135                   //^^^^^^ 💡 error: cannot mutate immutable variable `x`
1136    _ = closure;
1137}
1138"#,
1139        );
1140    }
1141
1142    #[test]
1143    fn regression_15143() {
1144        check_diagnostics(
1145            r#"
1146        trait Tr {
1147            type Ty;
1148        }
1149
1150        struct A;
1151
1152        impl Tr for A {
1153            type Ty = (u32, i64);
1154        }
1155
1156        struct B<T: Tr> {
1157            f: <T as Tr>::Ty,
1158        }
1159
1160        fn main(b: B<A>) {
1161            let f = b.f.0;
1162            f = 5;
1163          //^^^^^ 💡 error: cannot mutate immutable variable `f`
1164        }
1165            "#,
1166        );
1167    }
1168
1169    #[test]
1170    fn allow_unused_mut_for_identifiers_starting_with_underline() {
1171        check_diagnostics(
1172            r#"
1173fn f(_: i32) {}
1174fn main() {
1175    let mut _x = 2;
1176    f(_x);
1177}
1178"#,
1179        );
1180    }
1181
1182    #[test]
1183    fn respect_lint_attributes_for_unused_mut() {
1184        check_diagnostics(
1185            r#"
1186fn f(_: i32) {}
1187fn main() {
1188    #[allow(unused_mut)]
1189    let mut x = 2;
1190    f(x);
1191}
1192
1193fn main2() {
1194    #[deny(unused_mut)]
1195    let mut x = 2;
1196      //^^^^^ 💡 error: variable does not need to be mutable
1197    f(x);
1198}
1199"#,
1200        );
1201        check_diagnostics(
1202            r#"
1203macro_rules! mac {
1204    ($($x:expr),*$(,)*) => ({
1205        #[allow(unused_mut)]
1206        let mut vec = 2;
1207        vec
1208    });
1209}
1210
1211fn main2() {
1212    let mut x = mac![];
1213      //^^^^^ 💡 warn: variable does not need to be mutable
1214    _ = x;
1215}
1216        "#,
1217        );
1218    }
1219
1220    #[test]
1221    fn regression_15099() {
1222        check_diagnostics(
1223            r#"
1224//- minicore: iterator, range
1225fn f() {
1226    loop {}
1227    for _ in 0..2 {}
1228}
1229"#,
1230        );
1231    }
1232
1233    #[test]
1234    fn regression_15623() {
1235        check_diagnostics(
1236            r#"
1237//- minicore: fn
1238
1239struct Foo;
1240
1241impl Foo {
1242    fn needs_mut(&mut self) {}
1243}
1244
1245fn foo(mut foo: Foo) {
1246    let mut call_me = || {
1247        let 0 = 1 else { return };
1248        foo.needs_mut();
1249    };
1250    call_me();
1251}
1252"#,
1253        );
1254    }
1255
1256    #[test]
1257    fn regression_15670() {
1258        check_diagnostics(
1259            r#"
1260//- minicore: fn
1261
1262pub struct A {}
1263pub unsafe fn foo(a: *mut A) {
1264    let mut b = || -> *mut A { unsafe { &mut *a } };
1265      //^^^^^ 💡 warn: variable does not need to be mutable
1266    let _ = b();
1267}
1268"#,
1269        );
1270    }
1271
1272    #[test]
1273    fn regression_15799() {
1274        check_diagnostics(
1275            r#"
1276//- minicore: deref_mut
1277struct WrapPtr(*mut u32);
1278
1279impl core::ops::Deref for WrapPtr {
1280    type Target = *mut u32;
1281    fn deref(&self) -> &Self::Target {
1282        &self.0
1283    }
1284}
1285
1286fn main() {
1287    let mut x = 0u32;
1288    let wrap = WrapPtr(&mut x);
1289    unsafe {
1290        **wrap = 6;
1291    }
1292}
1293"#,
1294        );
1295    }
1296
1297    #[test]
1298    fn destructuring_assignment_needs_mut() {
1299        check_diagnostics(
1300            r#"
1301//- minicore: fn
1302
1303fn main() {
1304	let mut var = 1;
1305	let mut func = || (var,) = (2,);
1306	func();
1307}
1308        "#,
1309        );
1310    }
1311
1312    #[test]
1313    fn regression_20662() {
1314        check_diagnostics(
1315            r#"
1316//- minicore: index
1317pub trait A: core::ops::IndexMut<usize> {
1318    type T: A;
1319}
1320
1321fn func(a: &mut impl A, b: &mut [i32]) {
1322    b[0] += 1;
1323}
1324        "#,
1325        );
1326    }
1327}