Skip to content

Commit 860e50a

Browse files
committed
Lint resetting mut
1 parent 2b3d008 commit 860e50a

14 files changed

+149
-7
lines changed

compiler/rustc_hir_typeck/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
4646
4747
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
4848
49+
hir_typeck_dereferencing_mut_binding = dereferencing `mut` binding
50+
.label = `mut` dereferences the type of this binding
51+
.help = this will change in edition 2024
52+
4953
hir_typeck_expected_default_return_type = expected `()` because of default return type
5054
5155
hir_typeck_expected_return_type = expected `{$expected}` because of return type

compiler/rustc_hir_typeck/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,11 @@ pub struct SuggestConvertViaMethod<'tcx> {
630630
pub expected: Ty<'tcx>,
631631
pub found: Ty<'tcx>,
632632
}
633+
634+
#[derive(LintDiagnostic)]
635+
#[diag(hir_typeck_dereferencing_mut_binding)]
636+
pub struct DereferencingMutBinding {
637+
#[label]
638+
#[help]
639+
pub span: Span,
640+
}

compiler/rustc_hir_typeck/src/pat.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_infer::infer;
1414
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1515
use rustc_middle::mir::interpret::ErrorHandled;
1616
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt};
17-
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
17+
use rustc_session::lint;
1818
use rustc_span::edit_distance::find_best_match_for_name;
1919
use rustc_span::hygiene::DesugaringKind;
2020
use rustc_span::source_map::Spanned;
@@ -600,8 +600,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
600600

601601
// Determine the binding mode...
602602
let bm = match ba {
603-
hir::BindingAnnotation::NONE => def_bm,
604-
_ => BindingMode::convert(ba),
603+
hir::BindingAnnotation(ast::ByRef::No, hir::Mutability::Not) => def_bm,
604+
hir::BindingAnnotation(ast::ByRef::No, mutbl @ hir::Mutability::Mut) => {
605+
if let BindingMode::BindByReference(_) = def_bm {
606+
// `mut x` resets the binding mode.
607+
self.tcx.emit_spanned_lint(
608+
lint::builtin::DEREFERENCING_MUT_BINDING,
609+
pat.hir_id,
610+
pat.span,
611+
errors::DereferencingMutBinding { span: pat.span },
612+
);
613+
}
614+
BindingMode::BindByValue(mutbl)
615+
}
616+
hir::BindingAnnotation(ast::ByRef::Yes, mutbl) => BindingMode::BindByReference(mutbl),
605617
};
606618
// ...and store it in a side table:
607619
self.inh.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@@ -1838,7 +1850,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18381850
&unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
18391851
);
18401852

1841-
self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
1853+
self.tcx.struct_span_lint_hir(lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
18421854
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
18431855
lint.help(
18441856
"ensure that all fields are mentioned explicitly by adding the suggested fields",

tests/ui/or-patterns/or-patterns-default-binding-modes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![allow(irrefutable_let_patterns)]
66
#![allow(dropping_copy_types)]
77
#![allow(dropping_references)]
8+
#![allow(dereferencing_mut_binding)]
89

910
fn main() {
1011
// A regression test for a mistake we made at one point:

tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ fn main() {
99
let mut p = (U, U);
1010
let (a, ref mut b) = &mut p;
1111
//~^ ERROR cannot move out of a mutable reference
12+
//~| WARN dereferencing `mut`
1213
}

tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ fn main() {
99
let mut p = (U, U);
1010
let (a, mut b) = &mut p;
1111
//~^ ERROR cannot move out of a mutable reference
12+
//~| WARN dereferencing `mut`
1213
}

tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
warning: dereferencing `mut` binding
2+
--> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:13
3+
|
4+
LL | let (a, mut b) = &mut p;
5+
| ^^^^^ `mut` dereferences the type of this binding
6+
|
7+
help: this will change in edition 2024
8+
--> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:13
9+
|
10+
LL | let (a, mut b) = &mut p;
11+
| ^^^^^
12+
= note: `#[warn(dereferencing_mut_binding)]` on by default
13+
114
error[E0507]: cannot move out of a mutable reference
215
--> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22
316
|
@@ -12,6 +25,6 @@ help: consider borrowing the pattern binding
1225
LL | let (a, ref mut b) = &mut p;
1326
| +++
1427

15-
error: aborting due to 1 previous error
28+
error: aborting due to 1 previous error; 1 warning emitted
1629

1730
For more information about this error, try `rustc --explain E0507`.

tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ fn main() {
77
let p = (U, U);
88
let (a, mut b) = &p;
99
//~^ ERROR cannot move out of a shared reference
10+
//~| WARN dereferencing `mut`
1011
}

tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
warning: dereferencing `mut` binding
2+
--> $DIR/move-ref-patterns-default-binding-modes.rs:8:13
3+
|
4+
LL | let (a, mut b) = &p;
5+
| ^^^^^ `mut` dereferences the type of this binding
6+
|
7+
help: this will change in edition 2024
8+
--> $DIR/move-ref-patterns-default-binding-modes.rs:8:13
9+
|
10+
LL | let (a, mut b) = &p;
11+
| ^^^^^
12+
= note: `#[warn(dereferencing_mut_binding)]` on by default
13+
114
error[E0507]: cannot move out of a shared reference
215
--> $DIR/move-ref-patterns-default-binding-modes.rs:8:22
316
|
@@ -12,6 +25,6 @@ help: consider borrowing the pattern binding
1225
LL | let (a, ref mut b) = &p;
1326
| +++
1427

15-
error: aborting due to 1 previous error
28+
error: aborting due to 1 previous error; 1 warning emitted
1629

1730
For more information about this error, try `rustc --explain E0507`.

tests/ui/rfcs/rfc-2005-default-binding-mode/for.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ pub fn main() {
55
// The below desugars to &(ref n, mut m).
66
for (n, mut m) in &tups {
77
//~^ ERROR cannot move out of a shared reference
8+
//~| WARN dereferencing `mut`
89
}
910
}

tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
warning: dereferencing `mut` binding
2+
--> $DIR/for.rs:6:13
3+
|
4+
LL | for (n, mut m) in &tups {
5+
| ^^^^^ `mut` dereferences the type of this binding
6+
|
7+
help: this will change in edition 2024
8+
--> $DIR/for.rs:6:13
9+
|
10+
LL | for (n, mut m) in &tups {
11+
| ^^^^^
12+
= note: `#[warn(dereferencing_mut_binding)]` on by default
13+
114
error[E0507]: cannot move out of a shared reference
215
--> $DIR/for.rs:6:23
316
|
@@ -12,6 +25,6 @@ help: consider borrowing the pattern binding
1225
LL | for (n, ref mut m) in &tups {
1326
| +++
1427

15-
error: aborting due to 1 previous error
28+
error: aborting due to 1 previous error; 1 warning emitted
1629

1730
For more information about this error, try `rustc --explain E0507`.

tests/ui/rfcs/rfc-2005-default-binding-mode/general.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// run-pass
22
#![allow(unused_variables)]
3+
#![allow(dereferencing_mut_binding)]
34
fn some_or_wildcard(r: &Option<i32>, b: &i32) {
45
let _: &i32 = match r {
56
Some(a) => a,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// `mut` resets the binding mode.
2+
#![deny(dereferencing_mut_binding)]
3+
4+
fn main() {
5+
let (x, mut y) = &(0, 0);
6+
//~^ ERROR dereferencing `mut`
7+
let _: &u32 = x;
8+
let _: u32 = y;
9+
10+
match &Some(5i32) {
11+
Some(mut n) => {
12+
//~^ ERROR dereferencing `mut`
13+
n += 1;
14+
let _ = n;
15+
}
16+
None => {}
17+
};
18+
if let Some(mut n) = &Some(5i32) {
19+
//~^ ERROR dereferencing `mut`
20+
n += 1;
21+
let _ = n;
22+
};
23+
match &Some(5i32) {
24+
&Some(mut n) => {
25+
n += 1;
26+
let _ = n;
27+
}
28+
None => {}
29+
};
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error: dereferencing `mut` binding
2+
--> $DIR/resetting-mut.rs:5:13
3+
|
4+
LL | let (x, mut y) = &(0, 0);
5+
| ^^^^^ `mut` dereferences the type of this binding
6+
|
7+
help: this will change in edition 2024
8+
--> $DIR/resetting-mut.rs:5:13
9+
|
10+
LL | let (x, mut y) = &(0, 0);
11+
| ^^^^^
12+
note: the lint level is defined here
13+
--> $DIR/resetting-mut.rs:2:9
14+
|
15+
LL | #![deny(dereferencing_mut_binding)]
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
17+
18+
error: dereferencing `mut` binding
19+
--> $DIR/resetting-mut.rs:11:14
20+
|
21+
LL | Some(mut n) => {
22+
| ^^^^^ `mut` dereferences the type of this binding
23+
|
24+
help: this will change in edition 2024
25+
--> $DIR/resetting-mut.rs:11:14
26+
|
27+
LL | Some(mut n) => {
28+
| ^^^^^
29+
30+
error: dereferencing `mut` binding
31+
--> $DIR/resetting-mut.rs:18:17
32+
|
33+
LL | if let Some(mut n) = &Some(5i32) {
34+
| ^^^^^ `mut` dereferences the type of this binding
35+
|
36+
help: this will change in edition 2024
37+
--> $DIR/resetting-mut.rs:18:17
38+
|
39+
LL | if let Some(mut n) = &Some(5i32) {
40+
| ^^^^^
41+
42+
error: aborting due to 3 previous errors
43+

0 commit comments

Comments
 (0)