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