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