diff options
Diffstat (limited to 'compiler')
31 files changed, 219 insertions, 303 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 915cb386075..aba94f4d817 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<bool> 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 b5b98659e2f..833b0e9b567 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 a70daf1b644..3ea182c5867 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 2aeea1dd341..26bb6800348 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 a70d2ebbd62..a0f86565929 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 f0c15a070b4..548f9b0810f 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 dcabac6d780..3bdb9a214ec 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 36f59b4ac2e..bd528432e70 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 3b6accb92ae..5986b959666 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 f5b6dd162b3..f2425d03449 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 861a00ce874..9d247c46bab 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<DeclOrigin<'a>>, @@ -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 e489b431e81..54344adaabd 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 02af55fbf0e..e5a650c5ac4 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 f684f83a261..367f6b2a304 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<Symbol> { 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 99ab006bcc0..e42b85530b5 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 af594bc5f24..00000000000 --- 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 aad2f6a4cf8..ae531b3aea6 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 f14ca7ae4b7..a62379def53 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 827b7e088ce..d60926bf796 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<Vec<ty::adjustment::Adjustment<'tcx>>>, - /// Stores the actual binding mode for all instances of hir::BindingAnnotation. - pat_binding_modes: ItemLocalMap<BindingMode>, + /// Stores the actual binding mode for all instances of [`BindingAnnotation`]. + pat_binding_modes: ItemLocalMap<BindingAnnotation>, /// 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<BindingMode> { + pub fn extract_binding_mode( + &self, + s: &Session, + id: HirId, + sp: Span, + ) -> Option<BindingAnnotation> { 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 4046122b6fe..6200f4bda6b 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 6d083e66a9b..b4c98834d0a 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 bc6f0a26582..440be873d4e 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 a43aadab478..274edf358e0 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 e04fe31a76f..07dc332b791 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 434ed16d5c6..3a688a14dd5 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 0a7e9653377..a4992da679e 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 16c4248a159..ef15082a481 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 8957d7d1bd3..e2436759c22 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 a6eedabf689..eae2d904c35 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2365,14 +2365,6 @@ pub(crate) struct UnexpectedLifetimeInPattern { } #[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)] #[note(parse_note_mut_pattern_usage)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index de83528b52c..1971591364d 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<Mutability> { 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 fbc28859535..ead00c3f0d4 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<PatternLocation>) -> 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 }; |
