Skip to content

Commit 42a3b5c

Browse files
authored
Unrolled build for rust-lang#123535
Rollup merge of rust-lang#123535 - Jules-Bertholet:mut_dont_reset_binding_mode_2024, r=Nadrieril Match ergonomics 2024: `mut` doesn't reset binding mode r? ``@Nadrieril`` cc rust-lang#123076 ``@rustbot`` label A-edition-2024 A-patterns
2 parents 1dea922 + 7a32117 commit 42a3b5c

13 files changed

+225
-4
lines changed

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ declare_features! (
533533
(unstable, more_qualified_paths, "1.54.0", Some(86935)),
534534
/// Allows the `#[must_not_suspend]` attribute.
535535
(unstable, must_not_suspend, "1.57.0", Some(83310)),
536+
/// Make `mut` not reset the binding mode on edition >= 2024.
537+
(incomplete, mut_preserve_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
536538
/// Allows `mut ref` and `mut ref mut` identifier patterns.
537539
(incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
538540
/// Allows using `#[naked]` on functions.

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

+19-4
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;
@@ -629,12 +630,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
629630
expected: Ty<'tcx>,
630631
pat_info: PatInfo<'tcx, '_>,
631632
) -> Ty<'tcx> {
632-
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
633+
let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
633634

634635
// Determine the binding mode...
635636
let bm = match ba {
636-
BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
637-
_ => ba,
637+
BindingAnnotation(ByRef::No, Mutability::Mut)
638+
if !(pat.span.at_least_rust_2024()
639+
&& self.tcx.features().mut_preserve_binding_mode_2024)
640+
&& matches!(def_br, ByRef::Yes(_)) =>
641+
{
642+
// `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+
);
649+
BindingAnnotation(ByRef::No, Mutability::Mut)
650+
}
651+
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
652+
BindingAnnotation(ByRef::Yes(_), _) => ba,
638653
};
639654
// ...and store it in a side table:
640655
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@@ -743,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
743758
}
744759
}
745760

746-
// Precondition: pat is a Ref(_) pattern
761+
/// Precondition: pat is a `Ref(_)` pattern
747762
fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
748763
let tcx = self.tcx;
749764
if let PatKind::Ref(inner, mutbl) = pat.kind

compiler/rustc_lint_defs/src/builtin.rs

+37
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,42 @@ 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 deemed 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_preserve_binding_mode_2024;
1660+
// FIXME uncomment below upon stabilization
1661+
/*@future_incompatible = FutureIncompatibleInfo {
1662+
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
1663+
reference: "123076",
1664+
};*/
1665+
}
1666+
16301667
declare_lint! {
16311668
/// The `unconditional_recursion` lint detects functions that cannot
16321669
/// return without calling themselves.

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,7 @@ symbols! {
11941194
multiple_supertrait_upcastable,
11951195
must_not_suspend,
11961196
must_use,
1197+
mut_preserve_binding_mode_2024,
11971198
mut_ref,
11981199
naked,
11991200
naked_functions,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
4+
struct Foo(u8);
5+
6+
fn main() {
7+
let Foo(mut a) = &Foo(0);
8+
a = &42;
9+
//~^ ERROR: mismatched types
10+
11+
let Foo(mut a) = &mut Foo(0);
12+
a = &mut 42;
13+
//~^ ERROR: mismatched types
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:8:9
3+
|
4+
LL | let Foo(mut a) = &Foo(0);
5+
| ----- expected due to the type of this binding
6+
LL | a = &42;
7+
| ^^^ expected `u8`, found `&{integer}`
8+
|
9+
help: consider removing the borrow
10+
|
11+
LL - a = &42;
12+
LL + a = 42;
13+
|
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:12:9
17+
|
18+
LL | let Foo(mut a) = &mut Foo(0);
19+
| ----- expected due to the type of this binding
20+
LL | a = &mut 42;
21+
| ^^^^^^^ expected `u8`, found `&mut {integer}`
22+
|
23+
help: consider removing the borrow
24+
|
25+
LL - a = &mut 42;
26+
LL + a = 42;
27+
|
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ edition: 2021
2+
//@ compile-flags: -Zunstable-options
3+
#![feature(mut_preserve_binding_mode_2024)]
4+
#![allow(incomplete_features)]
5+
6+
struct Foo(u8);
7+
8+
fn main() {
9+
let Foo(mut a) = &Foo(0);
10+
a = &42;
11+
//~^ ERROR: mismatched types
12+
13+
let Foo(mut a) = &mut Foo(0);
14+
a = &mut 42;
15+
//~^ ERROR: mismatched types
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/mut_preserve_binding_mode_2021.rs:10:9
3+
|
4+
LL | let Foo(mut a) = &Foo(0);
5+
| ----- expected due to the type of this binding
6+
LL | a = &42;
7+
| ^^^ expected `u8`, found `&{integer}`
8+
|
9+
help: consider removing the borrow
10+
|
11+
LL - a = &42;
12+
LL + a = 42;
13+
|
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/mut_preserve_binding_mode_2021.rs:14:9
17+
|
18+
LL | let Foo(mut a) = &mut Foo(0);
19+
| ----- expected due to the type of this binding
20+
LL | a = &mut 42;
21+
| ^^^^^^^ expected `u8`, found `&mut {integer}`
22+
|
23+
help: consider removing the borrow
24+
|
25+
LL - a = &mut 42;
26+
LL + a = 42;
27+
|
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-pass
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
4+
#![feature(mut_preserve_binding_mode_2024)]
5+
#![allow(incomplete_features, unused)]
6+
7+
struct Foo(u8);
8+
9+
fn main() {
10+
let Foo(mut a) = &Foo(0);
11+
a = &42;
12+
13+
let Foo(mut a) = &mut Foo(0);
14+
a = &mut 42;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ edition: 2021
2+
#![feature(mut_preserve_binding_mode_2024)]
3+
#![allow(incomplete_features, 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+
a = 42;
12+
13+
let Foo(mut a) = &mut Foo(0);
14+
//~^ ERROR: dereferencing `mut` binding
15+
a = 42;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: dereferencing `mut` binding
2+
--> $DIR/mut_preserve_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+
help: this will change in edition 2024
8+
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
9+
|
10+
LL | let Foo(mut a) = &Foo(0);
11+
| ^^^^^
12+
note: the lint level is defined here
13+
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:4:11
14+
|
15+
LL | #![forbid(dereferencing_mut_binding)]
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
17+
18+
error: dereferencing `mut` binding
19+
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
20+
|
21+
LL | let Foo(mut a) = &mut Foo(0);
22+
| ^^^^^ `mut` dereferences the type of this binding
23+
|
24+
help: this will change in edition 2024
25+
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
26+
|
27+
LL | let Foo(mut a) = &mut Foo(0);
28+
| ^^^^^
29+
30+
error: aborting due to 2 previous errors
31+

0 commit comments

Comments
 (0)