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