Skip to content

Commit 83f330f

Browse files
Migration lint
Rustfix remains TODO
1 parent ef1d084 commit 83f330f

File tree

6 files changed

+108
-0
lines changed

6 files changed

+108
-0
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
@@ -632,3 +632,11 @@ pub enum SuggestBoxingForReturnImplTrait {
632632
ends: Vec<Span>,
633633
},
634634
}
635+
636+
#[derive(LintDiagnostic)]
637+
#[diag(hir_typeck_dereferencing_mut_binding)]
638+
pub struct DereferencingMutBinding {
639+
#[label]
640+
#[help]
641+
pub span: Span,
642+
}

compiler/rustc_hir_typeck/src/pat.rs

+7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
1010
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
1111
use rustc_infer::infer;
1212
use rustc_infer::infer::type_variable::TypeVariableOrigin;
13+
use rustc_lint as lint;
1314
use rustc_middle::mir::interpret::ErrorHandled;
1415
use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt};
1516
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -639,6 +640,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
639640
&& matches!(def_br, ByRef::Yes(_)) =>
640641
{
641642
// `mut x` resets the binding mode in edition <= 2021.
643+
self.tcx.emit_node_span_lint(
644+
lint::builtin::DEREFERENCING_MUT_BINDING,
645+
pat.hir_id,
646+
pat.span,
647+
errors::DereferencingMutBinding { span: pat.span },
648+
);
642649
BindingAnnotation(ByRef::No, Mutability::Mut)
643650
}
644651
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),

compiler/rustc_lint_defs/src/builtin.rs

+36
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ declare_lint_pass! {
3838
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
3939
DEPRECATED_IN_FUTURE,
4040
DEPRECATED_WHERE_CLAUSE_LOCATION,
41+
DEREFERENCING_MUT_BINDING,
4142
DUPLICATE_MACRO_ATTRIBUTES,
4243
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
4344
ELIDED_LIFETIMES_IN_PATHS,
@@ -1627,6 +1628,41 @@ declare_lint! {
16271628
"detect mut variables which don't need to be mutable"
16281629
}
16291630

1631+
declare_lint! {
1632+
/// The `dereferencing_mut_binding` lint detects a `mut x` pattern that resets the binding mode,
1633+
/// as this behavior will change in rust 2024.
1634+
///
1635+
/// ### Example
1636+
///
1637+
/// ```rust
1638+
/// # #![warn(dereferencing_mut_binding)]
1639+
/// let x = Some(123u32);
1640+
/// let _y = match &x {
1641+
/// Some(mut x) => {
1642+
/// x += 1;
1643+
/// x
1644+
/// }
1645+
/// None => 0,
1646+
/// };
1647+
/// ```
1648+
///
1649+
/// {{produces}}
1650+
///
1651+
/// ### Explanation
1652+
///
1653+
/// Without the `mut`, `x` would have type `&u32`. Pre-2024, adding `mut` makes `x` have type
1654+
/// `u32`, which was deeped surprising. After edition 2024, adding `mut` will not change the
1655+
/// type of `x`. This lint warns users of editions before 2024 to update their code.
1656+
pub DEREFERENCING_MUT_BINDING,
1657+
Allow,
1658+
"detects `mut x` bindings that change the type of `x`",
1659+
@feature_gate = sym::mut_dont_reset_binding_mode_2024;
1660+
@future_incompatible = FutureIncompatibleInfo {
1661+
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
1662+
reference: "123076",
1663+
};
1664+
}
1665+
16301666
declare_lint! {
16311667
/// The `unconditional_recursion` lint detects functions that cannot
16321668
/// return without calling themselves.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ edition: 2021
2+
#![feature(mut_dont_reset_binding_mode_2024)]
3+
#![allow(unused)]
4+
#![forbid(dereferencing_mut_binding)]
5+
6+
struct Foo(u8);
7+
8+
fn main() {
9+
let Foo(mut a) = &Foo(0);
10+
//~^ ERROR: dereferencing `mut` binding
11+
//~| WARN: this changes meaning in Rust 2024
12+
a = 42;
13+
14+
let Foo(mut a) = &mut Foo(0);
15+
//~^ ERROR: dereferencing `mut` binding
16+
//~| WARN: this changes meaning in Rust 2024
17+
a = 42;
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: dereferencing `mut` binding
2+
--> $DIR/mut_dont_reset_binding_mode_2024_lint.rs:9:13
3+
|
4+
LL | let Foo(mut a) = &Foo(0);
5+
| ^^^^^ `mut` dereferences the type of this binding
6+
|
7+
= warning: this changes meaning in Rust 2024
8+
= note: for more information, see 123076
9+
help: this will change in edition 2024
10+
--> $DIR/mut_dont_reset_binding_mode_2024_lint.rs:9:13
11+
|
12+
LL | let Foo(mut a) = &Foo(0);
13+
| ^^^^^
14+
note: the lint level is defined here
15+
--> $DIR/mut_dont_reset_binding_mode_2024_lint.rs:4:11
16+
|
17+
LL | #![forbid(dereferencing_mut_binding)]
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
19+
20+
error: dereferencing `mut` binding
21+
--> $DIR/mut_dont_reset_binding_mode_2024_lint.rs:14:13
22+
|
23+
LL | let Foo(mut a) = &mut Foo(0);
24+
| ^^^^^ `mut` dereferences the type of this binding
25+
|
26+
= warning: this changes meaning in Rust 2024
27+
= note: for more information, see 123076
28+
help: this will change in edition 2024
29+
--> $DIR/mut_dont_reset_binding_mode_2024_lint.rs:14:13
30+
|
31+
LL | let Foo(mut a) = &mut Foo(0);
32+
| ^^^^^
33+
34+
error: aborting due to 2 previous errors
35+

0 commit comments

Comments
 (0)