mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Rollup merge of #123535 - Jules-Bertholet:mut_dont_reset_binding_mode_2024, r=Nadrieril
Match ergonomics 2024: `mut` doesn't reset binding mode r? ``@Nadrieril`` cc https://github.com/rust-lang/rust/issues/123076 ``@rustbot`` label A-edition-2024 A-patterns
This commit is contained in:
commit
dc40da83e3
@ -533,6 +533,8 @@ declare_features! (
|
||||
(unstable, more_qualified_paths, "1.54.0", Some(86935)),
|
||||
/// Allows the `#[must_not_suspend]` attribute.
|
||||
(unstable, must_not_suspend, "1.57.0", Some(83310)),
|
||||
/// Make `mut` not reset the binding mode on edition >= 2024.
|
||||
(incomplete, mut_preserve_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows `mut ref` and `mut ref mut` identifier patterns.
|
||||
(incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
|
||||
/// Allows using `#[naked]` on functions.
|
||||
|
@ -46,6 +46,10 @@ hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
|
||||
|
||||
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
|
||||
|
||||
hir_typeck_dereferencing_mut_binding = dereferencing `mut` binding
|
||||
.label = `mut` dereferences the type of this binding
|
||||
.help = this will change in edition 2024
|
||||
|
||||
hir_typeck_expected_default_return_type = expected `()` because of default return type
|
||||
|
||||
hir_typeck_expected_return_type = expected `{$expected}` because of return type
|
||||
|
@ -632,3 +632,11 @@ pub enum SuggestBoxingForReturnImplTrait {
|
||||
ends: Vec<Span>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(hir_typeck_dereferencing_mut_binding)]
|
||||
pub struct DereferencingMutBinding {
|
||||
#[label]
|
||||
#[help]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
|
||||
use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind};
|
||||
use rustc_infer::infer;
|
||||
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc_lint as lint;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt};
|
||||
use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
@ -629,12 +630,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected: Ty<'tcx>,
|
||||
pat_info: PatInfo<'tcx, '_>,
|
||||
) -> Ty<'tcx> {
|
||||
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
|
||||
let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
|
||||
|
||||
// Determine the binding mode...
|
||||
let bm = match ba {
|
||||
BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
|
||||
_ => ba,
|
||||
BindingAnnotation(ByRef::No, Mutability::Mut)
|
||||
if !(pat.span.at_least_rust_2024()
|
||||
&& self.tcx.features().mut_preserve_binding_mode_2024)
|
||||
&& matches!(def_br, ByRef::Yes(_)) =>
|
||||
{
|
||||
// `mut x` resets the binding mode in edition <= 2021.
|
||||
self.tcx.emit_node_span_lint(
|
||||
lint::builtin::DEREFERENCING_MUT_BINDING,
|
||||
pat.hir_id,
|
||||
pat.span,
|
||||
errors::DereferencingMutBinding { span: pat.span },
|
||||
);
|
||||
BindingAnnotation(ByRef::No, Mutability::Mut)
|
||||
}
|
||||
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
|
||||
BindingAnnotation(ByRef::Yes(_), _) => ba,
|
||||
};
|
||||
// ...and store it in a side table:
|
||||
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
|
||||
@ -743,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition: pat is a Ref(_) pattern
|
||||
/// Precondition: pat is a `Ref(_)` pattern
|
||||
fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
|
||||
let tcx = self.tcx;
|
||||
if let PatKind::Ref(inner, mutbl) = pat.kind
|
||||
|
@ -38,6 +38,7 @@ declare_lint_pass! {
|
||||
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
|
||||
DEPRECATED_IN_FUTURE,
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION,
|
||||
DEREFERENCING_MUT_BINDING,
|
||||
DUPLICATE_MACRO_ATTRIBUTES,
|
||||
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
|
||||
ELIDED_LIFETIMES_IN_PATHS,
|
||||
@ -1627,6 +1628,42 @@ declare_lint! {
|
||||
"detect mut variables which don't need to be mutable"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `dereferencing_mut_binding` lint detects a `mut x` pattern that resets the binding mode,
|
||||
/// as this behavior will change in rust 2024.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![warn(dereferencing_mut_binding)]
|
||||
/// let x = Some(123u32);
|
||||
/// let _y = match &x {
|
||||
/// Some(mut x) => {
|
||||
/// x += 1;
|
||||
/// x
|
||||
/// }
|
||||
/// None => 0,
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Without the `mut`, `x` would have type `&u32`. Pre-2024, adding `mut` makes `x` have type
|
||||
/// `u32`, which was deemed surprising. After edition 2024, adding `mut` will not change the
|
||||
/// type of `x`. This lint warns users of editions before 2024 to update their code.
|
||||
pub DEREFERENCING_MUT_BINDING,
|
||||
Allow,
|
||||
"detects `mut x` bindings that change the type of `x`",
|
||||
@feature_gate = sym::mut_preserve_binding_mode_2024;
|
||||
// FIXME uncomment below upon stabilization
|
||||
/*@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
|
||||
reference: "123076",
|
||||
};*/
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unconditional_recursion` lint detects functions that cannot
|
||||
/// return without calling themselves.
|
||||
|
@ -1194,6 +1194,7 @@ symbols! {
|
||||
multiple_supertrait_upcastable,
|
||||
must_not_suspend,
|
||||
must_use,
|
||||
mut_preserve_binding_mode_2024,
|
||||
mut_ref,
|
||||
naked,
|
||||
naked_functions,
|
||||
|
@ -0,0 +1,14 @@
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Zunstable-options
|
||||
|
||||
struct Foo(u8);
|
||||
|
||||
fn main() {
|
||||
let Foo(mut a) = &Foo(0);
|
||||
a = &42;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
let Foo(mut a) = &mut Foo(0);
|
||||
a = &mut 42;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:8:9
|
||||
|
|
||||
LL | let Foo(mut a) = &Foo(0);
|
||||
| ----- expected due to the type of this binding
|
||||
LL | a = &42;
|
||||
| ^^^ expected `u8`, found `&{integer}`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - a = &42;
|
||||
LL + a = 42;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:12:9
|
||||
|
|
||||
LL | let Foo(mut a) = &mut Foo(0);
|
||||
| ----- expected due to the type of this binding
|
||||
LL | a = &mut 42;
|
||||
| ^^^^^^^ expected `u8`, found `&mut {integer}`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - a = &mut 42;
|
||||
LL + a = 42;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
16
tests/ui/pattern/mut_preserve_binding_mode_2021.rs
Normal file
16
tests/ui/pattern/mut_preserve_binding_mode_2021.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ edition: 2021
|
||||
//@ compile-flags: -Zunstable-options
|
||||
#![feature(mut_preserve_binding_mode_2024)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
struct Foo(u8);
|
||||
|
||||
fn main() {
|
||||
let Foo(mut a) = &Foo(0);
|
||||
a = &42;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
let Foo(mut a) = &mut Foo(0);
|
||||
a = &mut 42;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
31
tests/ui/pattern/mut_preserve_binding_mode_2021.stderr
Normal file
31
tests/ui/pattern/mut_preserve_binding_mode_2021.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mut_preserve_binding_mode_2021.rs:10:9
|
||||
|
|
||||
LL | let Foo(mut a) = &Foo(0);
|
||||
| ----- expected due to the type of this binding
|
||||
LL | a = &42;
|
||||
| ^^^ expected `u8`, found `&{integer}`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - a = &42;
|
||||
LL + a = 42;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/mut_preserve_binding_mode_2021.rs:14:9
|
||||
|
|
||||
LL | let Foo(mut a) = &mut Foo(0);
|
||||
| ----- expected due to the type of this binding
|
||||
LL | a = &mut 42;
|
||||
| ^^^^^^^ expected `u8`, found `&mut {integer}`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - a = &mut 42;
|
||||
LL + a = 42;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
15
tests/ui/pattern/mut_preserve_binding_mode_2024.rs
Normal file
15
tests/ui/pattern/mut_preserve_binding_mode_2024.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ run-pass
|
||||
//@ edition: 2024
|
||||
//@ compile-flags: -Zunstable-options
|
||||
#![feature(mut_preserve_binding_mode_2024)]
|
||||
#![allow(incomplete_features, unused)]
|
||||
|
||||
struct Foo(u8);
|
||||
|
||||
fn main() {
|
||||
let Foo(mut a) = &Foo(0);
|
||||
a = &42;
|
||||
|
||||
let Foo(mut a) = &mut Foo(0);
|
||||
a = &mut 42;
|
||||
}
|
16
tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
Normal file
16
tests/ui/pattern/mut_preserve_binding_mode_2024_lint.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//@ edition: 2021
|
||||
#![feature(mut_preserve_binding_mode_2024)]
|
||||
#![allow(incomplete_features, unused)]
|
||||
#![forbid(dereferencing_mut_binding)]
|
||||
|
||||
struct Foo(u8);
|
||||
|
||||
fn main() {
|
||||
let Foo(mut a) = &Foo(0);
|
||||
//~^ ERROR: dereferencing `mut` binding
|
||||
a = 42;
|
||||
|
||||
let Foo(mut a) = &mut Foo(0);
|
||||
//~^ ERROR: dereferencing `mut` binding
|
||||
a = 42;
|
||||
}
|
31
tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
Normal file
31
tests/ui/pattern/mut_preserve_binding_mode_2024_lint.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error: dereferencing `mut` binding
|
||||
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
|
||||
|
|
||||
LL | let Foo(mut a) = &Foo(0);
|
||||
| ^^^^^ `mut` dereferences the type of this binding
|
||||
|
|
||||
help: this will change in edition 2024
|
||||
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:9:13
|
||||
|
|
||||
LL | let Foo(mut a) = &Foo(0);
|
||||
| ^^^^^
|
||||
note: the lint level is defined here
|
||||
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:4:11
|
||||
|
|
||||
LL | #![forbid(dereferencing_mut_binding)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: dereferencing `mut` binding
|
||||
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
|
||||
|
|
||||
LL | let Foo(mut a) = &mut Foo(0);
|
||||
| ^^^^^ `mut` dereferences the type of this binding
|
||||
|
|
||||
help: this will change in edition 2024
|
||||
--> $DIR/mut_preserve_binding_mode_2024_lint.rs:13:13
|
||||
|
|
||||
LL | let Foo(mut a) = &mut Foo(0);
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user