From e0da13f25fd223ee1ec20284ea3f4e88a818b804 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 23 Mar 2024 21:04:45 -0400 Subject: [PATCH] Implement `mut ref`/`mut ref mut` --- compiler/rustc_ast/src/ast.rs | 19 ++-- compiler/rustc_ast_lowering/src/lib.rs | 4 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 9 +- .../src/diagnostics/mutability_errors.rs | 19 ++-- compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_hir_analysis/src/check/errs.rs | 42 ++++----- .../rustc_hir_analysis/src/check/region.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 9 +- .../rustc_hir_typeck/src/expr_use_visitor.rs | 6 +- .../src/mem_categorization.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 54 +++++------ compiler/rustc_hir_typeck/src/upvar.rs | 5 +- compiler/rustc_middle/src/mir/mod.rs | 14 +-- compiler/rustc_middle/src/thir.rs | 39 +++----- compiler/rustc_middle/src/thir/visit.rs | 10 +- compiler/rustc_middle/src/ty/binding.rs | 18 ---- compiler/rustc_middle/src/ty/mod.rs | 3 - .../rustc_middle/src/ty/structural_impls.rs | 1 + .../rustc_middle/src/ty/typeck_results.rs | 25 +++-- compiler/rustc_mir_build/src/build/block.rs | 4 +- .../rustc_mir_build/src/build/matches/mod.rs | 69 +++++++------- .../rustc_mir_build/src/build/matches/util.rs | 18 ++-- compiler/rustc_mir_build/src/build/mod.rs | 14 +-- .../rustc_mir_build/src/check_unsafety.rs | 14 +-- .../src/thir/pattern/check_match.rs | 27 +++--- .../rustc_mir_build/src/thir/pattern/mod.rs | 22 +---- compiler/rustc_mir_build/src/thir/print.rs | 3 +- compiler/rustc_parse/messages.ftl | 3 - compiler/rustc_parse/src/errors.rs | 8 -- compiler/rustc_parse/src/parser/mod.rs | 16 ++-- compiler/rustc_parse/src/parser/pat.rs | 39 ++++---- .../src/functions/misnamed_getters.rs | 4 +- .../clippy_lints/src/index_refutable_slice.rs | 4 +- .../src/iter_without_into_iter.rs | 4 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 8 +- .../matches/infallible_destructuring_match.rs | 4 +- .../clippy_lints/src/matches/match_as_ref.rs | 2 +- .../src/matches/needless_match.rs | 2 +- .../src/matches/redundant_guards.rs | 2 +- .../clippy_lints/src/methods/clone_on_copy.rs | 2 +- .../clippy_lints/src/methods/iter_kv_map.rs | 5 +- src/tools/clippy/clippy_lints/src/misc.rs | 4 +- .../clippy/clippy_lints/src/question_mark.rs | 10 +- .../clippy/clippy_lints/src/utils/author.rs | 2 + src/tools/clippy/clippy_utils/src/lib.rs | 10 +- src/tools/rustfmt/src/patterns.rs | 91 ++++++++++++------- tests/ui/match/mut-ref-mut-2021.rs | 53 +++++++++++ tests/ui/match/mut-ref-mut-2021.stderr | 70 ++++++++++++++ tests/ui/mut/mut-ref.rs | 10 +- tests/ui/mut/mut-ref.stderr | 8 -- tests/ui/thir-print/thir-tree-match.stdout | 3 +- 51 files changed, 442 insertions(+), 378 deletions(-) delete mode 100644 compiler/rustc_middle/src/ty/binding.rs create mode 100644 tests/ui/match/mut-ref-mut-2021.rs create mode 100644 tests/ui/match/mut-ref-mut-2021.stderr delete mode 100644 tests/ui/mut/mut-ref.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 915cb386075d..aba94f4d817d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -702,19 +702,10 @@ pub struct PatField { #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Encodable, Decodable, HashStable_Generic)] pub enum ByRef { - Yes, + Yes(Mutability), No, } -impl From for ByRef { - fn from(b: bool) -> ByRef { - match b { - false => ByRef::No, - true => ByRef::Yes, - } - } -} - /// Explicit binding annotations given in the HIR for a binding. Note /// that this is not the final binding *mode* that we infer after type /// inference. @@ -724,9 +715,11 @@ pub struct BindingAnnotation(pub ByRef, pub Mutability); impl BindingAnnotation { pub const NONE: Self = Self(ByRef::No, Mutability::Not); - pub const REF: Self = Self(ByRef::Yes, Mutability::Not); + pub const REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Not); pub const MUT: Self = Self(ByRef::No, Mutability::Mut); - pub const REF_MUT: Self = Self(ByRef::Yes, Mutability::Mut); + pub const REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Not); + pub const MUT_REF: Self = Self(ByRef::Yes(Mutability::Not), Mutability::Mut); + pub const MUT_REF_MUT: Self = Self(ByRef::Yes(Mutability::Mut), Mutability::Mut); pub fn prefix_str(self) -> &'static str { match self { @@ -734,6 +727,8 @@ impl BindingAnnotation { Self::REF => "ref ", Self::MUT => "mut ", Self::REF_MUT => "ref mut ", + Self::MUT_REF => "mut ref ", + Self::MUT_REF_MUT => "mut ref mut ", } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b5b98659e2fc..833b0e9b5679 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1847,8 +1847,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { - hir::Mutability::Not => hir::ImplicitSelfKind::ImmRef, - hir::Mutability::Mut => hir::ImplicitSelfKind::MutRef, + hir::Mutability::Not => hir::ImplicitSelfKind::RefImm, + hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut, }, _ => hir::ImplicitSelfKind::None, } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a70daf1b644e..3ea182c58675 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1545,12 +1545,15 @@ impl<'a> State<'a> { PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => { - if *by_ref == ByRef::Yes { - self.word_nbsp("ref"); - } if mutbl.is_mut() { self.word_nbsp("mut"); } + if let ByRef::Yes(rmutbl) = by_ref { + self.word_nbsp("ref"); + if rmutbl.is_mut() { + self.word_nbsp("mut"); + } + } self.print_ident(*ident); if let Some(p) = sub { self.space(); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 2aeea1dd341c..26bb68003480 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -4,9 +4,8 @@ use core::ops::ControlFlow; use hir::{ExprKind, Param}; use rustc_errors::{Applicability, Diag}; -use rustc_hir as hir; use rustc_hir::intravisit::Visitor; -use rustc_hir::Node; +use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node}; use rustc_infer::traits; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt}; @@ -304,7 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { match *decl.local_info() { LocalInfo::User(BindingForm::Var(mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(Mutability::Not), + binding_mode: BindingAnnotation(ByRef::No, Mutability::Not), opt_ty_info: Some(sp), opt_match_place: _, pat_span: _, @@ -342,7 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else if decl.mutability.is_not() { if matches!( decl.local_info(), - LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef)) + LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::RefMut)) ) { err.note( "as `Self` may be unsized, this call attempts to take `&mut &mut self`", @@ -407,7 +406,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(fn_decl) = node.fn_decl() { if !matches!( fn_decl.implicit_self, - hir::ImplicitSelfKind::ImmRef | hir::ImplicitSelfKind::MutRef + hir::ImplicitSelfKind::RefImm | hir::ImplicitSelfKind::RefMut ) { err.span_suggestion( upvar_ident.span, @@ -717,7 +716,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { debug!("local_decl: {:?}", local_decl); let pat_span = match *local_decl.local_info() { LocalInfo::User(BindingForm::Var(mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(Mutability::Not), + binding_mode: BindingAnnotation(ByRef::No, Mutability::Not), opt_ty_info: _, opt_match_place: _, pat_span, @@ -1070,7 +1069,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), + binding_mode: BindingAnnotation(ByRef::No, _), opt_ty_info, .. })) => { @@ -1138,7 +1137,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByReference(_), + binding_mode: BindingAnnotation(ByRef::Yes(_), _), .. })) => { let pattern_span: Span = local_decl.source_info.span; @@ -1329,7 +1328,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option< match *local_decl.local_info() { // Check if mutably borrowing a mutable reference. LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(Mutability::Not), + binding_mode: BindingAnnotation(ByRef::No, Mutability::Not), .. })) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)), LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => { @@ -1338,7 +1337,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option< // // Deliberately fall into this case for all implicit self types, // so that we don't fall into the next case with them. - kind == hir::ImplicitSelfKind::MutRef + kind == hir::ImplicitSelfKind::RefMut } _ if Some(kw::SelfLower) == local_name => { // Otherwise, check if the name is the `self` keyword - in which case diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a70d2ebbd620..a0f86565929b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2733,9 +2733,9 @@ pub enum ImplicitSelfKind { /// Represents a `fn x(mut self);`. Mut, /// Represents a `fn x(&self);`. - ImmRef, + RefImm, /// Represents a `fn x(&mut self);`. - MutRef, + RefMut, /// Represents when a function does not have a self argument or /// when a function has a `self: X` argument. None, diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index f0c15a070b48..548f9b0810fa 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -14,14 +14,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { && matches!(borrow_kind, hir::BorrowKind::Ref) && let Some(var) = is_path_static_mut(*expr) { - handle_static_mut_ref( - tcx, - span, - var, - span.edition().at_least_rust_2024(), - matches!(m, Mutability::Mut), - hir_id, - ); + handle_static_mut_ref(tcx, span, var, span.edition().at_least_rust_2024(), m, hir_id); } } @@ -29,7 +22,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind - && matches!(ba.0, rustc_ast::ByRef::Yes) + && let hir::ByRef::Yes(rmutbl) = ba.0 && let Some(init) = loc.init && let Some(var) = is_path_static_mut(*init) { @@ -38,7 +31,7 @@ pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { init.span, var, loc.span.edition().at_least_rust_2024(), - matches!(ba.1, Mutability::Mut), + rmutbl, stmt.hir_id, ); } @@ -60,28 +53,27 @@ fn handle_static_mut_ref( span: Span, var: String, e2024: bool, - mutable: bool, + mutable: Mutability, hir_id: hir::HirId, ) { if e2024 { - let (sugg, shared) = if mutable { + let (sugg, shared) = if mutable == Mutability::Mut { (errors::StaticMutRefSugg::Mut { span, var }, "mutable") } else { (errors::StaticMutRefSugg::Shared { span, var }, "shared") }; tcx.sess.psess.dcx.emit_err(errors::StaticMutRef { span, sugg, shared }); - return; - } - - let (sugg, shared) = if mutable { - (errors::RefOfMutStaticSugg::Mut { span, var }, "mutable") } else { - (errors::RefOfMutStaticSugg::Shared { span, var }, "shared") - }; - tcx.emit_node_span_lint( - STATIC_MUT_REFS, - hir_id, - span, - errors::RefOfMutStatic { span, sugg, shared }, - ); + let (sugg, shared) = if mutable == Mutability::Mut { + (errors::RefOfMutStaticSugg::Mut { span, var }, "mutable") + } else { + (errors::RefOfMutStaticSugg::Shared { span, var }, "shared") + }; + tcx.emit_node_span_lint( + STATIC_MUT_REFS, + hir_id, + span, + errors::RefOfMutStatic { span, sugg, shared }, + ); + } } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index dcabac6d7801..3bdb9a214ecd 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -654,7 +654,7 @@ fn resolve_local<'tcx>( // & expression, and its lifetime would be extended to the end of the block (due // to a different rule, not the below code). match pat.kind { - PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true, + PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes(_), _), ..) => true, PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)), diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 36f59b4ac2e0..bd528432e704 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1721,12 +1721,15 @@ impl<'a> State<'a> { PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Binding(BindingAnnotation(by_ref, mutbl), _, ident, sub) => { - if by_ref == ByRef::Yes { - self.word_nbsp("ref"); - } if mutbl.is_mut() { self.word_nbsp("mut"); } + if let ByRef::Yes(rmutbl) = by_ref { + self.word_nbsp("ref"); + if rmutbl.is_mut() { + self.word_nbsp("mut"); + } + } self.print_ident(ident); if let Some(p) = sub { self.word("@"); diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 3b6accb92ae5..5986b9596663 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -739,12 +739,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // In a cases of pattern like `let pat = upvar`, don't use the span // of the pattern, as this just looks confusing, instead use the span // of the discriminant. - match bm { - ty::BindByReference(m) => { + match bm.0 { + hir::ByRef::Yes(m) => { let bk = ty::BorrowKind::from_mutbl(m); delegate.borrow(place, discr_place.hir_id, bk); } - ty::BindByValue(..) => { + hir::ByRef::No => { debug!("walk_pat binding consuming pat"); delegate_consume(mc, *delegate, place, discr_place.hir_id); } diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index f5b6dd162b39..f2425d034495 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -206,7 +206,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { .get(pat.hir_id) .expect("missing binding mode"); - if let ty::BindByReference(_) = bm { + if matches!(bm.0, hir::ByRef::Yes(_)) { // a bind-by-ref means that the base_ty will be the type of the ident itself, // but what we want here is the type of the underlying value being borrowed. // So peel off one-level, turning the &T into T. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 861a00ce8745..9d247c46bab4 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -5,14 +5,13 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, }; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::{HirId, Pat, PatKind}; +use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId, Mutability, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::mir::interpret::ErrorHandled; -use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, Adt, Ty, TypeVisitableExt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; @@ -79,7 +78,7 @@ struct TopInfo<'tcx> { #[derive(Copy, Clone)] struct PatInfo<'tcx, 'a> { - binding_mode: BindingMode, + binding_mode: BindingAnnotation, top_info: TopInfo<'tcx>, decl_origin: Option>, @@ -124,7 +123,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { } } -const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not); +const INITIAL_BM: BindingAnnotation = BindingAnnotation(ByRef::No, Mutability::Not); /// Mode for adjusting the expected type and binding mode. enum AdjustMode { @@ -269,9 +268,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - def_bm: BindingMode, + def_bm: BindingAnnotation, adjust_mode: AdjustMode, - ) -> (Ty<'tcx>, BindingMode) { + ) -> (Ty<'tcx>, BindingAnnotation) { match adjust_mode { AdjustMode::Pass => (expected, def_bm), AdjustMode::Reset => (expected, INITIAL_BM), @@ -354,8 +353,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, - mut def_bm: BindingMode, - ) -> (Ty<'tcx>, BindingMode) { + mut def_bm: BindingAnnotation, + ) -> (Ty<'tcx>, BindingAnnotation) { let mut expected = self.try_structurally_resolve_type(pat.span, expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches @@ -374,15 +373,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_adjustments.push(expected); expected = self.try_structurally_resolve_type(pat.span, inner_ty); - def_bm = ty::BindByReference(match def_bm { + def_bm.0 = ByRef::Yes(match def_bm.0 { // If default binding mode is by value, make it `ref` or `ref mut` // (depending on whether we observe `&` or `&mut`). - ty::BindByValue(_) | + ByRef::No | // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). - ty::BindByReference(hir::Mutability::Mut) => inner_mutability, + ByRef::Yes(Mutability::Mut) => inner_mutability, // Once a `ref`, always a `ref`. // This is because a `& &mut` cannot mutate the underlying value. - ty::BindByReference(m @ hir::Mutability::Not) => m, + ByRef::Yes(Mutability::Not) => Mutability::Not, }); } @@ -599,7 +598,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ident( &self, pat: &'tcx Pat<'tcx>, - ba: hir::BindingAnnotation, + ba: BindingAnnotation, var_id: HirId, sub: Option<&'tcx Pat<'tcx>>, expected: Ty<'tcx>, @@ -609,8 +608,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Determine the binding mode... let bm = match ba { - hir::BindingAnnotation::NONE => def_bm, - _ => BindingMode::convert(ba), + BindingAnnotation(ByRef::No, Mutability::Not) => def_bm, + _ => ba, }; // ...and store it in a side table: self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm); @@ -618,8 +617,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("check_pat_ident: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); let local_ty = self.local_ty(pat.span, pat.hir_id); - let eq_ty = match bm { - ty::BindByReference(mutbl) => { + let eq_ty = match bm.0 { + ByRef::Yes(mutbl) => { // If the binding is like `ref x | ref mut x`, // then `x` is assigned a value of type `&M T` where M is the // mutability and T is the expected type. @@ -630,10 +629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.new_ref_ty(pat.span, mutbl, expected) } // Otherwise, the type of x is the expected type `T`. - ty::BindByValue(_) => { - // As above, `T <: typeof(x)` is required, but we use equality, see (note_1). - expected - } + ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1). }; self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti); @@ -655,7 +651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// bindings have the same type by comparing them all against the type of that first pat. fn check_binding_alt_eq_ty( &self, - ba: hir::BindingAnnotation, + ba: BindingAnnotation, span: Span, var_id: HirId, ty: Ty<'tcx>, @@ -695,10 +691,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, expected: Ty<'tcx>, actual: Ty<'tcx>, - ba: hir::BindingAnnotation, + ba: BindingAnnotation, ) { match (expected.kind(), actual.kind(), ba) { - (ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE) + (ty::Ref(_, inner_ty, _), _, BindingAnnotation::NONE) if self.can_eq(self.param_env, *inner_ty, actual) => { err.span_suggestion_verbose( @@ -708,7 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - (_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF) + (_, ty::Ref(_, inner_ty, _), BindingAnnotation::REF) if self.can_eq(self.param_env, expected, *inner_ty) => { err.span_suggestion_verbose( @@ -800,7 +796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let PatKind::Ref(the_ref, _) = i.kind && let PatKind::Binding(mt, _, ident, _) = the_ref.kind { - let hir::BindingAnnotation(_, mtblty) = mt; + let BindingAnnotation(_, mtblty) = mt; err.span_suggestion_verbose( i.span, format!("consider removing `&{mutability}` from the pattern"), @@ -2037,7 +2033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat: &'tcx Pat<'tcx>, inner: &'tcx Pat<'tcx>, - mutbl: hir::Mutability, + mutbl: Mutability, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { @@ -2088,7 +2084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Create a reference type with a fresh region variable. - fn new_ref_ty(&self, span: Span, mutbl: hir::Mutability, ty: Ty<'tcx>) -> Ty<'tcx> { + fn new_ref_ty(&self, span: Span, mutbl: Mutability, ty: Ty<'tcx>) -> Ty<'tcx> { let region = self.next_region_var(infer::PatternRegion(span)); Ty::new_ref(self.tcx, region, ty, mutbl) } diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index e489b431e818..54344adaabd2 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1711,10 +1711,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let bm = *typeck_results.pat_binding_modes().get(var_hir_id).expect("missing binding mode"); - let mut is_mutbl = match bm { - ty::BindByValue(mutability) => mutability, - ty::BindByReference(_) => hir::Mutability::Not, - }; + let mut is_mutbl = bm.1; for pointer_ty in place.deref_tys() { match pointer_ty.kind() { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 02af55fbf0e4..e5a650c5ac4a 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -17,8 +17,10 @@ use rustc_data_structures::captures::Captures; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; -use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; -use rustc_hir::{self as hir, HirId}; +use rustc_hir::{ + self as hir, BindingAnnotation, ByRef, CoroutineDesugaring, CoroutineKind, HirId, + ImplicitSelfKind, +}; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_target::abi::{FieldIdx, VariantIdx}; @@ -992,8 +994,8 @@ pub enum LocalKind { #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct VarBindingForm<'tcx> { - /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? - pub binding_mode: ty::BindingMode, + /// Is variable bound via `x`, `mut x`, `ref x`, `ref mut x`, `mut ref x`, or `mut ref mut x`? + pub binding_mode: BindingAnnotation, /// If an explicit type was provided for this variable binding, /// this holds the source Span of that type. /// @@ -1218,7 +1220,7 @@ impl<'tcx> LocalDecl<'tcx> { self.local_info(), LocalInfo::User( BindingForm::Var(VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), + binding_mode: BindingAnnotation(ByRef::No, _), opt_ty_info: _, opt_match_place: _, pat_span: _, @@ -1235,7 +1237,7 @@ impl<'tcx> LocalDecl<'tcx> { self.local_info(), LocalInfo::User( BindingForm::Var(VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), + binding_mode: BindingAnnotation(ByRef::No, _), opt_ty_info: _, opt_match_place: _, pat_span: _, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index f684f83a2612..367f6b2a3043 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -12,12 +12,12 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::RangeEnd; +use rustc_hir::{BindingAnnotation, ByRef, RangeEnd}; use rustc_index::newtype_index; use rustc_index::IndexVec; use rustc_middle::middle::region; use rustc_middle::mir::interpret::{AllocId, Scalar}; -use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp}; +use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ @@ -581,12 +581,6 @@ pub enum InlineAsmOperand<'tcx> { }, } -#[derive(Copy, Clone, Debug, PartialEq, HashStable)] -pub enum BindingMode { - ByValue, - ByRef(BorrowKind), -} - #[derive(Clone, Debug, HashStable, TypeVisitable)] pub struct FieldPat<'tcx> { pub field: FieldIdx, @@ -607,19 +601,22 @@ impl<'tcx> Pat<'tcx> { pub fn simple_ident(&self) -> Option { match self.kind { - PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => { - Some(name) - } + PatKind::Binding { + name, + mode: BindingAnnotation(ByRef::No, _), + subpattern: None, + .. + } => Some(name), _ => None, } } /// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` - pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) { + pub fn each_binding(&self, mut f: impl FnMut(Symbol, ByRef, Ty<'tcx>, Span)) { self.walk_always(|p| { if let PatKind::Binding { name, mode, ty, .. } = p.kind { - f(name, mode, ty, p.span); + f(name, mode.0, ty, p.span); } }); } @@ -730,10 +727,9 @@ pub enum PatKind<'tcx> { /// `x`, `ref x`, `x @ P`, etc. Binding { - mutability: Mutability, name: Symbol, #[type_visitable(ignore)] - mode: BindingMode, + mode: BindingAnnotation, #[type_visitable(ignore)] var: LocalVarId, ty: Ty<'tcx>, @@ -1073,17 +1069,8 @@ impl<'tcx> fmt::Display for Pat<'tcx> { PatKind::Wild => write!(f, "_"), PatKind::Never => write!(f, "!"), PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"), - PatKind::Binding { mutability, name, mode, ref subpattern, .. } => { - let is_mut = match mode { - BindingMode::ByValue => mutability == Mutability::Mut, - BindingMode::ByRef(bk) => { - write!(f, "ref ")?; - matches!(bk, BorrowKind::Mut { .. }) - } - }; - if is_mut { - write!(f, "mut ")?; - } + PatKind::Binding { name, mode, ref subpattern, .. } => { + f.write_str(mode.prefix_str())?; write!(f, "{name}")?; if let Some(ref subpattern) = *subpattern { write!(f, " @ {subpattern}")?; diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 99ab006bcc06..e42b85530b50 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -230,15 +230,7 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( AscribeUserType { subpattern, ascription: _ } | Deref { subpattern } | DerefPattern { subpattern } - | Binding { - subpattern: Some(subpattern), - mutability: _, - mode: _, - var: _, - ty: _, - is_primary: _, - name: _, - } => visitor.visit_pat(subpattern), + | Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern), Binding { .. } | Wild | Never | Error(_) => {} Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { for subpattern in subpatterns { diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs deleted file mode 100644 index af594bc5f24c..000000000000 --- a/compiler/rustc_middle/src/ty/binding.rs +++ /dev/null @@ -1,18 +0,0 @@ -use rustc_hir::{BindingAnnotation, ByRef, Mutability}; - -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)] -pub enum BindingMode { - BindByReference(Mutability), - BindByValue(Mutability), -} - -TrivialTypeTraversalImpls! { BindingMode } - -impl BindingMode { - pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { - match by_ref { - ByRef::No => BindingMode::BindByValue(mutbl), - ByRef::Yes => BindingMode::BindByReference(mutbl), - } - } -} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index aad2f6a4cf8a..ae531b3aea6f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -76,8 +76,6 @@ pub use rustc_type_ir::ConstKind::{ }; pub use rustc_type_ir::*; -pub use self::binding::BindingMode; -pub use self::binding::BindingMode::*; pub use self::closure::{ is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, @@ -123,7 +121,6 @@ pub use self::typeck_results::{ pub mod _match; pub mod abstract_const; pub mod adjustment; -pub mod binding; pub mod cast; pub mod codec; pub mod error; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f14ca7ae4b7a..a62379def534 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -402,6 +402,7 @@ TrivialTypeTraversalImpls! { ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, ::rustc_hir::def_id::LocalDefId, + ::rustc_hir::ByRef, ::rustc_hir::HirId, ::rustc_hir::MatchSource, ::rustc_target::asm::InlineAsmRegOrRegClass, diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 827b7e088ce0..d60926bf796d 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -3,8 +3,8 @@ use crate::{ infer::canonical::Canonical, traits::ObligationCause, ty::{ - self, tls, BindingMode, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, - GenericArgKind, GenericArgs, GenericArgsRef, Ty, UserArgs, + self, tls, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, + GenericArgs, GenericArgsRef, Ty, UserArgs, }, }; use rustc_data_structures::{ @@ -12,12 +12,12 @@ use rustc_data_structures::{ unord::{ExtendUnord, UnordItems, UnordSet}, }; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; use rustc_hir::{ + self as hir, def::{DefKind, Res}, def_id::{DefId, LocalDefId, LocalDefIdMap}, hir_id::OwnerId, - HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, + BindingAnnotation, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability, }; use rustc_index::{Idx, IndexVec}; use rustc_macros::HashStable; @@ -78,8 +78,8 @@ pub struct TypeckResults<'tcx> { adjustments: ItemLocalMap>>, - /// Stores the actual binding mode for all instances of hir::BindingAnnotation. - pat_binding_modes: ItemLocalMap, + /// Stores the actual binding mode for all instances of [`BindingAnnotation`]. + pat_binding_modes: ItemLocalMap, /// Stores the types which were implicitly dereferenced in pattern binding modes /// for later usage in THIR lowering. For example, @@ -408,17 +408,22 @@ impl<'tcx> TypeckResults<'tcx> { matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _)))) } - pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> Option { + pub fn extract_binding_mode( + &self, + s: &Session, + id: HirId, + sp: Span, + ) -> Option { self.pat_binding_modes().get(id).copied().or_else(|| { s.dcx().span_bug(sp, "missing binding mode"); }) } - pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> { + pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingAnnotation> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes } } - pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> { + pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingAnnotation> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes } } @@ -442,7 +447,7 @@ impl<'tcx> TypeckResults<'tcx> { let mut has_ref_mut = false; pat.walk(|pat| { if let hir::PatKind::Binding(_, id, _, _) = pat.kind - && let Some(ty::BindByReference(ty::Mutability::Mut)) = + && let Some(BindingAnnotation(ByRef::Yes(Mutability::Mut), _)) = self.pat_binding_modes().get(id) { has_ref_mut = true; diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 4046122b6fe6..6200f4bda6ba 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -218,7 +218,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.visit_primary_bindings( pattern, UserTypeProjections::none(), - &mut |this, _, _, _, node, span, _, _| { + &mut |this, _, _, node, span, _, _| { this.storage_live_binding( block, node, @@ -308,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.visit_primary_bindings( pattern, UserTypeProjections::none(), - &mut |this, _, _, _, node, span, _, _| { + &mut |this, _, _, node, span, _, _| { this.storage_live_binding(block, node, span, OutsideGuard, true); this.schedule_drop_for_binding(node, span, OutsideGuard); }, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6d083e66a9b2..b4c98834d0af 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -14,6 +14,7 @@ use rustc_data_structures::{ fx::{FxHashSet, FxIndexMap, FxIndexSet}, stack::ensure_sufficient_stack, }; +use rustc_hir::{BindingAnnotation, ByRef}; use rustc_middle::middle::region; use rustc_middle::mir::{self, *}; use rustc_middle::thir::{self, *}; @@ -554,7 +555,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> BlockAnd<()> { match irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` - PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { + PatKind::Binding { + mode: BindingAnnotation(ByRef::No, _), + var, + subpattern: None, + .. + } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); unpack!(block = self.expr_into_dest(place, block, initializer_id)); @@ -580,7 +586,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { box Pat { kind: PatKind::Binding { - mode: BindingMode::ByValue, var, subpattern: None, .. + mode: BindingAnnotation(ByRef::No, _), + var, + subpattern: None, + .. }, .. }, @@ -720,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.visit_primary_bindings( pattern, UserTypeProjections::none(), - &mut |this, mutability, name, mode, var, span, ty, user_ty| { + &mut |this, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { visibility_scope = Some(this.new_source_scope(scope_span, LintLevel::Inherited, None)); @@ -730,7 +739,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.declare_binding( source_info, visibility_scope, - mutability, name, mode, var, @@ -818,9 +826,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pattern_user_ty: UserTypeProjections, f: &mut impl FnMut( &mut Self, - Mutability, Symbol, - BindingMode, + BindingAnnotation, LocalVarId, Span, Ty<'tcx>, @@ -832,18 +839,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pattern, pattern_user_ty ); match pattern.kind { - PatKind::Binding { - mutability, - name, - mode, - var, - ty, - ref subpattern, - is_primary, - .. - } => { + PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => { if is_primary { - f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); + f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); } if let Some(subpattern) = subpattern.as_ref() { self.visit_primary_bindings(subpattern, pattern_user_ty, f); @@ -1079,7 +1077,7 @@ struct Binding<'tcx> { span: Span, source: Place<'tcx>, var_id: LocalVarId, - binding_mode: BindingMode, + binding_mode: BindingAnnotation, } /// Indicates that the type of `source` must be a subtype of the @@ -2097,9 +2095,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings); self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone()); - let guard_frame = GuardFrame { - locals: bindings.map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode)).collect(), - }; + let guard_frame = + GuardFrame { locals: bindings.map(|b| GuardFrameLocal::new(b.var_id)).collect() }; debug!("entering guard building context: {:?}", guard_frame); self.guard_context.push(guard_frame); @@ -2176,7 +2173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .iter() .flat_map(|d| &d.bindings) .chain(&candidate.extra_data.bindings) - .filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue)); + .filter(|binding| matches!(binding.binding_mode.0, ByRef::No)); // Read all of the by reference bindings to ensure that the // place they refer to can't be modified by the guard. for binding in by_value_bindings.clone() { @@ -2263,12 +2260,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { RefWithinGuard, schedule_drops, ); - match binding.binding_mode { - BindingMode::ByValue => { + match binding.binding_mode.0 { + ByRef::No => { let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, binding.source); self.cfg.push_assign(block, source_info, ref_for_guard, rvalue); } - BindingMode::ByRef(borrow_kind) => { + ByRef::Yes(mutbl) => { let value_for_arm = self.storage_live_binding( block, binding.var_id, @@ -2277,7 +2274,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { schedule_drops, ); - let rvalue = Rvalue::Ref(re_erased, borrow_kind, binding.source); + let rvalue = + Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source); self.cfg.push_assign(block, source_info, value_for_arm, rvalue); let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, value_for_arm); self.cfg.push_assign(block, source_info, ref_for_guard, rvalue); @@ -2318,10 +2316,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if schedule_drops { self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); } - let rvalue = match binding.binding_mode { - BindingMode::ByValue => Rvalue::Use(self.consume_by_copy_or_move(binding.source)), - BindingMode::ByRef(borrow_kind) => { - Rvalue::Ref(re_erased, borrow_kind, binding.source) + let rvalue = match binding.binding_mode.0 { + ByRef::No => Rvalue::Use(self.consume_by_copy_or_move(binding.source)), + ByRef::Yes(mutbl) => { + Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source) } }; self.cfg.push_assign(block, source_info, local, rvalue); @@ -2338,9 +2336,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, source_info: SourceInfo, visibility_scope: SourceScope, - mutability: Mutability, name: Symbol, - mode: BindingMode, + mode: BindingAnnotation, var_id: LocalVarId, var_ty: Ty<'tcx>, user_ty: UserTypeProjections, @@ -2350,18 +2347,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let tcx = self.tcx; let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope }; - let binding_mode = match mode { - BindingMode::ByValue => ty::BindingMode::BindByValue(mutability), - BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability), - }; let local = LocalDecl { - mutability, + mutability: mode.1, ty: var_ty, user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) }, source_info, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var( VarBindingForm { - binding_mode, + binding_mode: mode, // hypothetically, `visit_primary_bindings` could try to unzip // an outermost hir::Ty as we descend, matching up // idents in pat; but complex w/ unclear UI payoff. diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index bc6f0a26582c..440be873d4ee 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -154,15 +154,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { TestCase::Irrefutable { ascription, binding: None } } - PatKind::Binding { - name: _, - mutability: _, - mode, - var, - ty: _, - ref subpattern, - is_primary: _, - } => { + PatKind::Binding { mode, var, ref subpattern, .. } => { let binding = place.map(|source| super::Binding { span: pattern.span, source, @@ -347,3 +339,11 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } } } + +#[must_use] +pub fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind { + match ref_mutability { + Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, + Mutability::Not => BorrowKind::Shared, + } +} diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index a43aadab4785..274edf358e0b 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -7,10 +7,9 @@ use rustc_ast::attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::Node; +use rustc_hir::{self as hir, BindingAnnotation, ByRef, Node}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -19,9 +18,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::query::TyCtxtAt; -use rustc_middle::thir::{ - self, BindingMode, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir, -}; +use rustc_middle::thir::{self, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -337,7 +334,7 @@ struct GuardFrameLocal { } impl GuardFrameLocal { - fn new(id: LocalVarId, _binding_mode: BindingMode) -> Self { + fn new(id: LocalVarId) -> Self { GuardFrameLocal { id } } } @@ -967,9 +964,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match pat.kind { // Don't introduce extra copies for simple bindings PatKind::Binding { - mutability, var, - mode: BindingMode::ByValue, + mode: BindingAnnotation(ByRef::No, mutability), subpattern: None, .. } => { @@ -979,7 +975,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(kind) = param.self_kind { LocalInfo::User(BindingForm::ImplicitSelf(kind)) } else { - let binding_mode = ty::BindingMode::BindByValue(mutability); + let binding_mode = BindingAnnotation(ByRef::No, mutability); LocalInfo::User(BindingForm::Var(VarBindingForm { binding_mode, opt_ty_info: param.ty_span, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e04fe31a76f2..07dc332b7914 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,11 +2,11 @@ use std::borrow::Cow; use crate::build::ExprCategory; use crate::errors::*; -use rustc_middle::thir::visit::Visitor; use rustc_errors::DiagArgValue; -use rustc_hir as hir; +use rustc_hir::{self as hir, BindingAnnotation, ByRef, Mutability}; use rustc_middle::mir::BorrowKind; +use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; @@ -289,22 +289,22 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_pat(self, pat); } } - PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => { + PatKind::Binding { mode: BindingAnnotation(ByRef::Yes(rm), _), ty, .. } => { if self.inside_adt { let ty::Ref(_, ty, _) = ty.kind() else { span_bug!( pat.span, - "BindingMode::ByRef in pattern, but found non-reference type {}", + "ByRef::Yes in pattern, but found non-reference type {}", ty ); }; - match borrow_kind { - BorrowKind::Fake | BorrowKind::Shared => { + match rm { + Mutability::Not => { if !ty.is_freeze(self.tcx, self.param_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } - BorrowKind::Mut { .. } => { + Mutability::Mut { .. } => { self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 434ed16d5c6e..3a688a14dd50 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -13,10 +13,9 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, }; -use rustc_hir as hir; use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; -use rustc_hir::HirId; +use rustc_hir::{self as hir, BindingAnnotation, ByRef, HirId}; use rustc_middle::middle::limits::get_limit_size; use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; @@ -723,13 +722,14 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: let sess = cx.tcx.sess; // Get the binding move, extract the mutability if by-ref. - let mut_outer = match mode { - BindingMode::ByValue if is_binding_by_move(ty) => { + let mut_outer = match mode.0 { + ByRef::No if is_binding_by_move(ty) => { // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. let mut conflicts_ref = Vec::new(); - sub.each_binding(|_, mode, _, span| match mode { - BindingMode::ByValue => {} - BindingMode::ByRef(_) => conflicts_ref.push(span), + sub.each_binding(|_, mode, _, span| { + if matches!(mode, ByRef::Yes(_)) { + conflicts_ref.push(span) + } }); if !conflicts_ref.is_empty() { sess.dcx().emit_err(BorrowOfMovedValue { @@ -742,8 +742,8 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: } return; } - BindingMode::ByValue => return, - BindingMode::ByRef(m) => m.mutability(), + ByRef::No => return, + ByRef::Yes(m) => m, }; // We now have `ref $mut_outer binding @ sub` (semantically). @@ -753,7 +753,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: let mut conflicts_mut_ref = Vec::new(); sub.each_binding(|name, mode, ty, span| { match mode { - BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) { + ByRef::Yes(mut_inner) => match (mut_outer, mut_inner) { // Both sides are `ref`. (Mutability::Not, Mutability::Not) => {} // 2x `ref mut`. @@ -767,10 +767,10 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: conflicts_mut_ref.push(Conflict::Ref { span, name }) } }, - BindingMode::ByValue if is_binding_by_move(ty) => { + ByRef::No if is_binding_by_move(ty) => { conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict. } - BindingMode::ByValue => {} // `ref mut?` + by-copy is fine. + ByRef::No => {} // `ref mut?` + by-copy is fine. } }); @@ -813,8 +813,7 @@ fn check_for_bindings_named_same_as_variants( ) { if let PatKind::Binding { name, - mode: BindingMode::ByValue, - mutability: Mutability::Not, + mode: BindingAnnotation(ByRef::No, Mutability::Not), subpattern: None, ty, .. diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0a7e9653377b..a4992da679e8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -9,15 +9,14 @@ use crate::errors::*; use crate::thir::util::UserAnnotatedTyHelpers; use rustc_errors::codes::*; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; -use rustc_hir::RangeEnd; +use rustc_hir::{self as hir, RangeEnd}; use rustc_index::Idx; use rustc_middle::mir::interpret::{ErrorHandled, GlobalId, LitToConstError, LitToConstInput}; -use rustc_middle::mir::{self, BorrowKind, Const, Mutability}; +use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{ - Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, + Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; @@ -281,26 +280,16 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { span = span.with_hi(ident_span.hi()); } - let bm = *self + let mode = *self .typeck_results .pat_binding_modes() .get(pat.hir_id) .expect("missing binding mode"); - let (mutability, mode) = match bm { - ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue), - ty::BindByReference(hir::Mutability::Mut) => ( - Mutability::Not, - BindingMode::ByRef(BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), - ), - ty::BindByReference(hir::Mutability::Not) => { - (Mutability::Not, BindingMode::ByRef(BorrowKind::Shared)) - } - }; // A ref x pattern is the same node used for x, and as such it has // x's type, which is &T, where we want T (the type being matched). let var_ty = ty; - if let ty::BindByReference(_) = bm { + if let hir::ByRef::Yes(_) = mode.0 { if let ty::Ref(_, rty, _) = ty.kind() { ty = *rty; } else { @@ -309,7 +298,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; PatKind::Binding { - mutability, mode, name: ident.name, var: LocalVarId(id), diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16c4248a1596..ef15082a4813 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -635,9 +635,8 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_pat(subpattern, depth_lvl + 3); print_indented!(self, "}", depth_lvl + 1); } - PatKind::Binding { mutability, name, mode, var, ty, subpattern, is_primary } => { + PatKind::Binding { name, mode, var, ty, subpattern, is_primary } => { print_indented!(self, "Binding {", depth_lvl + 1); - print_indented!(self, format!("mutability: {:?}", mutability), depth_lvl + 2); print_indented!(self, format!("name: {:?}", name), depth_lvl + 2); print_indented!(self, format!("mode: {:?}", mode), depth_lvl + 2); print_indented!(self, format!("var: {:?}", var), depth_lvl + 2); diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 8957d7d1bd36..e2436759c22c 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -655,9 +655,6 @@ parse_question_mark_in_type = invalid `?` in type parse_recover_import_as_use = expected item, found {$token_name} .suggestion = items are imported using the `use` keyword -parse_ref_mut_order_incorrect = the order of `mut` and `ref` is incorrect - .suggestion = try switching the order - parse_remove_let = expected pattern, found `let` .suggestion = remove the unnecessary `let` keyword diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index a6eedabf6892..eae2d904c35e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2364,14 +2364,6 @@ pub(crate) struct UnexpectedLifetimeInPattern { pub symbol: Symbol, } -#[derive(Diagnostic)] -#[diag(parse_ref_mut_order_incorrect)] -pub(crate) struct RefMutOrderIncorrect { - #[primary_span] - #[suggestion(code = "ref mut", applicability = "machine-applicable")] - pub span: Span, -} - #[derive(Diagnostic)] pub(crate) enum InvalidMutInPattern { #[diag(parse_mut_on_nested_ident_pattern)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index de83528b52cd..1971591364d3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -24,12 +24,11 @@ use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing}; use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor}; use rustc_ast::util::case::Case; -use rustc_ast::AttrId; -use rustc_ast::CoroutineKind; -use rustc_ast::DUMMY_NODE_ID; -use rustc_ast::{self as ast, AnonConst, Const, DelimArgs, Extern}; -use rustc_ast::{AttrArgs, AttrArgsEq, Expr, ExprKind, Mutability, StrLit}; -use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; +use rustc_ast::{ + self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs, + Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, StrLit, Unsafe, Visibility, + VisibilityKind, DUMMY_NODE_ID, +}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; @@ -1273,6 +1272,11 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Mut) { Mutability::Mut } else { Mutability::Not } } + /// Parses reference binding mode (`ref`, `ref mut`, or nothing). + fn parse_byref(&mut self) -> ByRef { + if self.eat_keyword(kw::Ref) { ByRef::Yes(self.parse_mutability()) } else { ByRef::No } + } + /// Possibly parses mutability (`const` or `mut`). fn parse_const_or_mut(&mut self) -> Option { if self.eat_keyword(kw::Mut) { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index fbc288595355..ead00c3f0d4c 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -4,11 +4,11 @@ use crate::errors::{ DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, - PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern, - SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, - UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, - UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, + PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, + TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, + UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, + UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, + UnexpectedVertVertInPattern, }; use crate::parser::expr::could_be_unclosed_char_literal; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -476,7 +476,7 @@ impl<'a> Parser<'a> { // Parse `_` PatKind::Wild } else if self.eat_keyword(kw::Mut) { - self.parse_pat_ident_mut(syntax_loc)? + self.parse_pat_ident_mut()? } else if self.eat_keyword(kw::Ref) { if self.check_keyword(kw::Box) { // Suggest `box ref`. @@ -486,7 +486,7 @@ impl<'a> Parser<'a> { } // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)? + self.parse_pat_ident(BindingAnnotation(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? } else if self.eat_keyword(kw::Box) { self.parse_pat_box()? } else if self.check_inline_const(0) { @@ -746,13 +746,12 @@ impl<'a> Parser<'a> { } /// Parse a mutable binding with the `mut` token already eaten. - fn parse_pat_ident_mut(&mut self, syntax_loc: Option) -> PResult<'a, PatKind> { + fn parse_pat_ident_mut(&mut self) -> PResult<'a, PatKind> { let mut_span = self.prev_token.span; - if self.eat_keyword(kw::Ref) { - self.dcx().emit_err(RefMutOrderIncorrect { span: mut_span.to(self.prev_token.span) }); - return self.parse_pat_ident(BindingAnnotation::REF_MUT, syntax_loc); - } + self.recover_additional_muts(); + + let byref = self.parse_byref(); self.recover_additional_muts(); @@ -767,10 +766,12 @@ impl<'a> Parser<'a> { let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?; // If we don't have `mut $ident (@ pat)?`, error. - if let PatKind::Ident(BindingAnnotation(ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind + if let PatKind::Ident(BindingAnnotation(br @ ByRef::No, m @ Mutability::Not), ..) = + &mut pat.kind { // Don't recurse into the subpattern. // `mut` on the outer binding doesn't affect the inner bindings. + *br = byref; *m = Mutability::Mut; } else { // Add `mut` to any binding in the parsed pattern. @@ -1390,16 +1391,12 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form `(box) (ref) (mut) fieldname`. let is_box = self.eat_keyword(kw::Box); let boxed_span = self.token.span; - let is_ref = self.eat_keyword(kw::Ref); - let is_mut = self.eat_keyword(kw::Mut); + let mutability = self.parse_mutability(); + let by_ref = self.parse_byref(); + let fieldname = self.parse_field_name()?; hi = self.prev_token.span; - - let mutability = match is_mut { - false => Mutability::Not, - true => Mutability::Mut, - }; - let ann = BindingAnnotation(ByRef::from(is_ref), mutability); + let ann = BindingAnnotation(by_ref, mutability); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname); let subpat = if is_box { self.mk_pat(lo.to(hi), PatKind::Box(fieldpat)) } else { fieldpat }; diff --git a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs index bf96c0d62b05..8ac17e17688d 100644 --- a/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs +++ b/src/tools/clippy/clippy_lints/src/functions/misnamed_getters.rs @@ -24,13 +24,13 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: let name = ident.name.as_str(); let name = match decl.implicit_self { - ImplicitSelfKind::MutRef => { + ImplicitSelfKind::RefMut => { let Some(name) = name.strip_suffix("_mut") else { return; }; name }, - ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::ImmRef => name, + ImplicitSelfKind::Imm | ImplicitSelfKind::Mut | ImplicitSelfKind::RefImm => name, ImplicitSelfKind::None => return, }; diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 5b5eb355f86c..4d1f89b1d9d9 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -97,7 +97,7 @@ fn find_slice_values(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> FxIndexMap, pat: &hir::Pat<'_>) -> FxIndexMap, item: &rustc_hir::ImplItem<'_>) { let item_did = item.owner_id.to_def_id(); let (borrow_prefix, expected_implicit_self) = match item.ident.name { - sym::iter => ("&", ImplicitSelfKind::ImmRef), - sym::iter_mut => ("&mut ", ImplicitSelfKind::MutRef), + sym::iter => ("&", ImplicitSelfKind::RefImm), + sym::iter_mut => ("&mut ", ImplicitSelfKind::RefMut), _ => return, }; diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 27d85cde5320..cae9ada5a33c 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -384,8 +384,8 @@ impl LenOutput { fn expected_sig(self, self_kind: ImplicitSelfKind) -> String { let self_ref = match self_kind { - ImplicitSelfKind::ImmRef => "&", - ImplicitSelfKind::MutRef => "&mut ", + ImplicitSelfKind::RefImm => "&", + ImplicitSelfKind::RefMut => "&mut ", _ => "", }; match self { @@ -411,8 +411,8 @@ fn check_is_empty_sig<'tcx>( [arg, res] if len_output.matches_is_empty_output(cx, *res) => { matches!( (arg.kind(), self_kind), - (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::ImmRef) - | (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::MutRef) + (ty::Ref(_, _, Mutability::Not), ImplicitSelfKind::RefImm) + | (ty::Ref(_, _, Mutability::Mut), ImplicitSelfKind::RefMut) ) || (!arg.is_ref() && matches!(self_kind, ImplicitSelfKind::Imm | ImplicitSelfKind::Mut)) }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs index 0f242e0b9e12..93d7683d2af8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/infallible_destructuring_match.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{path_to_local_id, peel_blocks, strip_pat_refs}; use rustc_errors::Applicability; -use rustc_hir::{ByRef, ExprKind, LetStmt, MatchSource, PatKind, QPath}; +use rustc_hir::{ExprKind, LetStmt, MatchSource, PatKind, QPath}; use rustc_lint::LateContext; use super::INFALLIBLE_DESTRUCTURING_MATCH; @@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, local: &LetStmt<'_>) -> bool { format!( "let {}({}{}) = {};", snippet_with_applicability(cx, variant_name.span, "..", &mut applicability), - if binding.0 == ByRef::Yes { "ref " } else { "" }, + binding.prefix_str(), snippet_with_applicability(cx, local.pat.span, "..", &mut applicability), snippet_with_applicability(cx, target.span, "..", &mut applicability), ), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs index 3f737da92c05..6b484ff2749b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs @@ -67,7 +67,7 @@ fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool { fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option { if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome) - && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind + && let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., ident, _) = first_pat.kind && let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind && is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome) && let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index cee77f62b61e..fe83e784c3c9 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -178,7 +178,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool { }, )), ) => { - return !matches!(annot, BindingAnnotation(ByRef::Yes, _)) && pat_ident.name == first_seg.ident.name; + return !matches!(annot, BindingAnnotation(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name; }, // Example: `Custom::TypeA => Custom::TypeB`, or `None => None` (PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => { diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs index 6bae51b45b8f..50cbccc39683 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs @@ -182,7 +182,7 @@ fn get_pat_binding<'tcx>( if let PatKind::Binding(bind_annot, hir_id, ident, _) = pat.kind && hir_id == local { - if matches!(bind_annot.0, rustc_ast::ByRef::Yes) { + if matches!(bind_annot.0, rustc_ast::ByRef::Yes(_)) { let _ = byref_ident.insert(ident); } // the second call of `replace()` returns a `Some(span)`, meaning a multi-binding pattern diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index d4a5de3d1dea..3e099004c479 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -69,7 +69,7 @@ pub(super) fn check( _ => false, }, // local binding capturing a reference - Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..)) => { + Node::LetStmt(l) if matches!(l.pat.kind, PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..)) => { return; }, _ => false, diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs index 6394f35f8604..1431a5db2d96 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs @@ -60,8 +60,6 @@ pub(super) fn check<'tcx>( applicability, ); } else { - let ref_annotation = if annotation.0 == ByRef::Yes { "ref " } else { "" }; - let mut_annotation = if annotation.1 == Mutability::Mut { "mut " } else { "" }; span_lint_and_sugg( cx, ITER_KV_MAP, @@ -69,7 +67,8 @@ pub(super) fn check<'tcx>( &format!("iterating on a map's {replacement_kind}s"), "try", format!( - "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})", + "{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{}{bound_ident}| {})", + annotation.prefix_str(), snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability) ), applicability, diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index ea6e662b4be3..11fecb7d72e2 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) { return; } - if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind { + if let PatKind::Binding(BindingAnnotation(ByRef::Yes(_), _), ..) = arg.pat.kind { span_lint( cx, TOPLEVEL_REF_ARG, @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.tcx.sess, stmt.span) && let StmtKind::Let(local) = stmt.kind - && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind + && let PatKind::Binding(BindingAnnotation(ByRef::Yes(mutabl), _), .., name, None) = local.pat.kind && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. && is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index f1db571e1137..b57220e6cf0a 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -14,7 +14,7 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, + BindingAnnotation, Block, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt, StmtKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; @@ -283,9 +283,13 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability); let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_)); + let method_call_str = match by_ref { + ByRef::Yes(Mutability::Mut) => ".as_mut()", + ByRef::Yes(Mutability::Not) => ".as_ref()", + ByRef::No => "", + }; let sugg = format!( - "{receiver_str}{}?{}", - if by_ref == ByRef::Yes { ".as_ref()" } else { "" }, + "{receiver_str}{method_call_str}?{}", if requires_semi { ";" } else { "" } ); span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 5319915b2eac..e45beb4910be 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -649,6 +649,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { BindingAnnotation::REF => "REF", BindingAnnotation::MUT => "MUT", BindingAnnotation::REF_MUT => "REF_MUT", + BindingAnnotation::MUT_REF => "MUT_REF", + BindingAnnotation::MUT_REF_MUT => "MUT_REF_MUT", }; kind!("Binding(BindingAnnotation::{ann}, _, {name}, {sub})"); self.ident(name); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8251bdf78fc7..95bab5801d1c 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -97,7 +97,7 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::{ - self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Destination, Expr, + self as hir, def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, ByRef, Closure, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, @@ -107,7 +107,6 @@ use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::Const; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; -use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ @@ -1006,11 +1005,12 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind { .typeck_results() .extract_binding_mode(cx.sess(), id, span) .unwrap() + .0 { - BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => { + ByRef::No if !is_copy(cx, cx.typeck_results().node_type(id)) => { capture = CaptureKind::Value; }, - BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => { + ByRef::Yes(Mutability::Mut) if capture != CaptureKind::Value => { capture = CaptureKind::Ref(Mutability::Mut); }, _ => (), @@ -2035,7 +2035,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { .typeck_results() .pat_binding_modes() .get(pat.hir_id) - .is_some_and(|mode| matches!(mode, BindingMode::BindByReference(_))) + .is_some_and(|mode| matches!(mode.0, ByRef::Yes(_))) { // If a tuple `(x, y)` is of type `&(i32, i32)`, then due to match ergonomics, // the inner patterns become references. Don't consider this the identity function diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 47b48468a24c..820eccb2dc20 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -107,18 +107,19 @@ impl Rewrite for Pat { } PatKind::Box(ref pat) => rewrite_unary_prefix(context, "box ", &**pat, shape), PatKind::Ident(BindingAnnotation(by_ref, mutability), ident, ref sub_pat) => { - let prefix = match by_ref { - ByRef::Yes => "ref", - ByRef::No => "", + let mut_prefix = format_mutability(mutability).trim(); + + let (ref_kw, mut_infix) = match by_ref { + ByRef::Yes(rmutbl) => ("ref", format_mutability(rmutbl).trim()), + ByRef::No => ("", ""), }; - let mut_infix = format_mutability(mutability).trim(); let id_str = rewrite_ident(context, ident); let sub_pat = match *sub_pat { Some(ref p) => { // 2 - `@ `. - let width = shape - .width - .checked_sub(prefix.len() + mut_infix.len() + id_str.len() + 2)?; + let width = shape.width.checked_sub( + mut_prefix.len() + ref_kw.len() + mut_infix.len() + id_str.len() + 2, + )?; let lo = context.snippet_provider.span_after(self.span, "@"); combine_strs_with_missing_comments( context, @@ -132,33 +133,55 @@ impl Rewrite for Pat { None => "".to_owned(), }; - // combine prefix and mut - let (first_lo, first) = if !prefix.is_empty() && !mut_infix.is_empty() { - let hi = context.snippet_provider.span_before(self.span, "mut"); - let lo = context.snippet_provider.span_after(self.span, "ref"); - ( + // combine prefix and ref + let (first_lo, first) = match (mut_prefix.is_empty(), ref_kw.is_empty()) { + (false, false) => { + let lo = context.snippet_provider.span_after(self.span, "mut"); + let hi = context.snippet_provider.span_before(self.span, "ref"); + ( + context.snippet_provider.span_after(self.span, "ref"), + combine_strs_with_missing_comments( + context, + mut_prefix, + ref_kw, + mk_sp(lo, hi), + shape, + true, + )?, + ) + } + (false, true) => ( context.snippet_provider.span_after(self.span, "mut"), - combine_strs_with_missing_comments( - context, - prefix, - mut_infix, - mk_sp(lo, hi), - shape, - true, - )?, - ) - } else if !prefix.is_empty() { - ( + mut_prefix.to_owned(), + ), + (true, false) => ( context.snippet_provider.span_after(self.span, "ref"), - prefix.to_owned(), - ) - } else if !mut_infix.is_empty() { - ( - context.snippet_provider.span_after(self.span, "mut"), - mut_infix.to_owned(), - ) - } else { - (self.span.lo(), "".to_owned()) + ref_kw.to_owned(), + ), + (true, true) => (self.span.lo(), "".to_owned()), + }; + + // combine result of above and mut + let (second_lo, second) = match (first.is_empty(), mut_infix.is_empty()) { + (false, false) => { + let lo = context.snippet_provider.span_after(self.span, "ref"); + let end_span = mk_sp(first_lo, self.span.hi()); + let hi = context.snippet_provider.span_before(end_span, "mut"); + ( + context.snippet_provider.span_after(end_span, "mut"), + combine_strs_with_missing_comments( + context, + &first, + mut_infix, + mk_sp(lo, hi), + shape, + true, + )?, + ) + } + (false, true) => (first_lo, first), + (true, false) => unreachable!("mut_infix necessarily follows a ref"), + (true, true) => (self.span.lo(), "".to_owned()), }; let next = if !sub_pat.is_empty() { @@ -177,9 +200,9 @@ impl Rewrite for Pat { combine_strs_with_missing_comments( context, - &first, + &second, &next, - mk_sp(first_lo, ident.span.lo()), + mk_sp(second_lo, ident.span.lo()), shape, true, ) diff --git a/tests/ui/match/mut-ref-mut-2021.rs b/tests/ui/match/mut-ref-mut-2021.rs new file mode 100644 index 000000000000..48516350d4d7 --- /dev/null +++ b/tests/ui/match/mut-ref-mut-2021.rs @@ -0,0 +1,53 @@ +//@ edition: 2021 + +struct Foo(u8); + +fn main() { + let Foo(a) = Foo(0); + a = 42; //~ ERROR [E0384] + + let Foo(mut a) = Foo(0); + a = 42; + + let Foo(ref a) = Foo(0); + a = &42; //~ ERROR [E0384] + + let Foo(mut ref a) = Foo(0); + a = &42; + + let Foo(ref mut a) = Foo(0); + a = &mut 42; //~ ERROR [E0384] + + let Foo(mut ref mut a) = Foo(0); + a = &mut 42; + + let Foo(a) = &Foo(0); + a = &42; //~ ERROR [E0384] + + let Foo(mut a) = &Foo(0); + a = 42; + + let Foo(ref a) = &Foo(0); + a = &42; //~ ERROR [E0384] + + let Foo(mut ref a) = &Foo(0); + a = &42; + + let Foo(a) = &mut Foo(0); + a = &mut 42; //~ ERROR [E0384] + + let Foo(mut a) = &mut Foo(0); + a = 42; + + let Foo(ref a) = &mut Foo(0); + a = &42; //~ ERROR [E0384] + + let Foo(mut ref a) = &mut Foo(0); + a = &42; + + let Foo(ref mut a) = &mut Foo(0); + a = &mut 42; //~ ERROR [E0384] + + let Foo(mut ref mut a) = &mut Foo(0); + a = &mut 42; +} diff --git a/tests/ui/match/mut-ref-mut-2021.stderr b/tests/ui/match/mut-ref-mut-2021.stderr new file mode 100644 index 000000000000..9210ce23784f --- /dev/null +++ b/tests/ui/match/mut-ref-mut-2021.stderr @@ -0,0 +1,70 @@ +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:7:5 + | +LL | let Foo(a) = Foo(0); + | - + | | + | first assignment to `a` + | help: consider making this binding mutable: `mut a` +LL | a = 42; + | ^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:13:5 + | +LL | let Foo(ref a) = Foo(0); + | ----- first assignment to `a` +LL | a = &42; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:19:5 + | +LL | let Foo(ref mut a) = Foo(0); + | --------- first assignment to `a` +LL | a = &mut 42; + | ^^^^^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:25:5 + | +LL | let Foo(a) = &Foo(0); + | - first assignment to `a` +LL | a = &42; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:31:5 + | +LL | let Foo(ref a) = &Foo(0); + | ----- first assignment to `a` +LL | a = &42; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:37:5 + | +LL | let Foo(a) = &mut Foo(0); + | - first assignment to `a` +LL | a = &mut 42; + | ^^^^^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:43:5 + | +LL | let Foo(ref a) = &mut Foo(0); + | ----- first assignment to `a` +LL | a = &42; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/mut-ref-mut-2021.rs:49:5 + | +LL | let Foo(ref mut a) = &mut Foo(0); + | --------- first assignment to `a` +LL | a = &mut 42; + | ^^^^^^^^^^^ cannot assign twice to immutable variable + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/mut/mut-ref.rs b/tests/ui/mut/mut-ref.rs index 80990b2bfdef..813c7f02df15 100644 --- a/tests/ui/mut/mut-ref.rs +++ b/tests/ui/mut/mut-ref.rs @@ -1,4 +1,10 @@ +//@ check-pass + fn main() { - let mut ref x = 10; //~ ERROR the order of `mut` and `ref` is incorrect - let ref mut y = 11; + let mut ref x = 10; + x = &11; + let ref mut y = 12; + *y = 13; + let mut ref mut z = 14; + z = &mut 15; } diff --git a/tests/ui/mut/mut-ref.stderr b/tests/ui/mut/mut-ref.stderr deleted file mode 100644 index b91392f223a8..000000000000 --- a/tests/ui/mut/mut-ref.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: the order of `mut` and `ref` is incorrect - --> $DIR/mut-ref.rs:2:9 - | -LL | let mut ref x = 10; - | ^^^^^^^ help: try switching the order: `ref mut` - -error: aborting due to 1 previous error - diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index a17592fd2521..b248d2a82684 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -11,9 +11,8 @@ params: [ span: $DIR/thir-tree-match.rs:15:14: 15:17 (#0) kind: PatKind { Binding { - mutability: Not name: "foo" - mode: ByValue + mode: BindingAnnotation(No, Not) var: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2)) ty: Foo is_primary: true