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
8pub(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 span = d.span.with_value(SyntaxNodePtr::new(&parent));
23 };
24
25 let fixes = (|| {
26 if d.local.is_ref(ctx.sema.db) {
27 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 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 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
63pub(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 .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 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 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}