diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 808c6e3ff64..ae4d6b56152 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -94,6 +94,14 @@ fn ast_block_stmts( ) ); } + // ROX: + // + // Where the handling of destructure patterns start + // + // let (a, b, c, _ ) = something + // + // (a, b, c, _) is the pattern + // something is the initializer StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => { let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild); this.block_context.push(BlockFrame::Statement { ignores_expr_result }); @@ -125,6 +133,8 @@ fn ast_block_stmts( ArmHasGuard(false), Some((None, initializer_span)), ); + // This is where we get into pattern handling of the let + // statement this.expr_into_pattern(block, pattern.clone(), init) }) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 109a6521128..f819a638c7a 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -10,6 +10,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::AssertKind::BoundsCheck; use rustc_middle::mir::*; +use rustc_middle::ty::AdtDef; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; use rustc_target::abi::VariantIdx; @@ -17,7 +18,7 @@ use rustc_index::vec::Idx; /// The "outermost" place that holds this value. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] crate enum PlaceBase { /// Denotes the start of a `Place`. Local(Local), @@ -67,7 +68,7 @@ /// /// This is used internally when building a place for an expression like `a.b.c`. The fields `b` /// and `c` can be progressively pushed onto the place builder that is created when converting `a`. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] crate struct PlaceBuilder<'tcx> { base: PlaceBase, projection: Vec>, @@ -292,6 +293,7 @@ impl<'tcx> PlaceBuilder<'tcx> { } } + /// ROX: Function that will be called when we really do need a place fn expect_upvars_resolved<'a>( self, tcx: TyCtxt<'tcx>, @@ -319,15 +321,22 @@ fn try_upvars_resolved<'a>( self.project(PlaceElem::Field(f, ty)) } - fn deref(self) -> Self { + crate fn deref(self) -> Self { self.project(PlaceElem::Deref) } + crate fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Self { + self.project(PlaceElem::Downcast( + Some(adt_def.variants[variant_index].ident.name), + variant_index, + )) + } + fn index(self, index: Local) -> Self { self.project(PlaceElem::Index(index)) } - fn project(mut self, elem: PlaceElem<'tcx>) -> Self { + crate fn project(mut self, elem: PlaceElem<'tcx>) -> Self { self.projection.push(elem); self } @@ -367,6 +376,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(place_builder.into_place(self.tcx, self.typeck_results)) } + // ROX: As place builder /// This is used when constructing a compound `Place`, so that we can avoid creating /// intermediate `Place` values until we know the full set of projections. crate fn as_place_builder( @@ -613,13 +623,7 @@ fn lower_index_expression( // The "retagging" transformation (for Stacked Borrows) relies on this. let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,)); - block = self.bounds_check( - block, - base_place.clone().into_place(self.tcx, self.typeck_results), - idx, - expr_span, - source_info, - ); + block = self.bounds_check(block, base_place.clone(), idx, expr_span, source_info); if is_outermost_index { self.read_fake_borrows(block, fake_borrow_temps, source_info) @@ -640,7 +644,7 @@ fn lower_index_expression( fn bounds_check( &mut self, block: BasicBlock, - slice: Place<'tcx>, + slice: PlaceBuilder<'tcx>, index: Local, expr_span: Span, source_info: SourceInfo, @@ -652,7 +656,12 @@ fn bounds_check( let lt = self.temp(bool_ty, expr_span); // len = len(slice) - self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice)); + self.cfg.push_assign( + block, + source_info, + len, + Rvalue::Len(slice.clone().into_place(self.tcx, self.typeck_results)), + ); // lt = idx < len self.cfg.push_assign( block, diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index b2e8b2de1bc..e0ad34e08ef 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -280,6 +280,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let field_names: Vec<_> = (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect(); + // ROX: This is probably here the function record/struct update pattern is done. let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base { let place_builder = unpack!(block = this.as_place_builder(block, base)); diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index 07338928eb8..539de80cab7 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -62,7 +62,7 @@ mod as_constant; mod as_operand; -mod as_place; +pub mod as_place; mod as_rvalue; mod as_temp; mod category; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6c31528be73..7285cf75623 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1,3 +1,6 @@ +// ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc. +// We want to be careful ^^' + //! Code related to match expressions. These are sufficiently complex to //! warrant their own module and submodules. :) This main module includes the //! high-level algorithm, the submodules contain the details. @@ -5,6 +8,7 @@ //! This also includes code for pattern bindings in `let` statements and //! function parameters. +use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; @@ -96,7 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scrutinee_place = unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,)); - let mut arm_candidates = self.create_match_candidates(scrutinee_place, &arms); + let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms); let match_has_guard = arms.iter().any(|arm| arm.guard.is_some()); let mut candidates = @@ -121,8 +125,10 @@ fn lower_scrutinee( mut block: BasicBlock, scrutinee: &Expr<'_, 'tcx>, scrutinee_span: Span, - ) -> BlockAnd> { - let scrutinee_place = unpack!(block = self.as_place(block, scrutinee)); + ) -> BlockAnd> { + let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee)); + let scrutinee_place = + scrutinee_place_builder.clone().into_place(self.tcx, self.typeck_results); // Matching on a `scrutinee_place` with an uninhabited type doesn't // generate any memory reads by itself, and so if the place "expression" // contains unsafe operations like raw pointer dereferences or union @@ -142,13 +148,13 @@ fn lower_scrutinee( let source_info = self.source_info(scrutinee_span); self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place); - block.and(scrutinee_place) + block.and(scrutinee_place_builder) } /// Create the initial `Candidate`s for a `match` expression. fn create_match_candidates<'pat>( &mut self, - scrutinee: Place<'tcx>, + scrutinee: PlaceBuilder<'tcx>, arms: &'pat [Arm<'pat, 'tcx>], ) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> { // Assemble a list of candidates: there is one candidate per pattern, @@ -156,7 +162,7 @@ fn create_match_candidates<'pat>( arms.iter() .map(|arm| { let arm_has_guard = arm.guard.is_some(); - let arm_candidate = Candidate::new(scrutinee, &arm.pattern, arm_has_guard); + let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard); (arm, arm_candidate) }) .collect() @@ -222,7 +228,7 @@ fn lower_match_tree<'pat>( fn lower_match_arms( &mut self, destination: Place<'tcx>, - scrutinee_place: Place<'tcx>, + scrutinee_place: PlaceBuilder<'tcx>, scrutinee_span: Span, arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>, outer_source_info: SourceInfo, @@ -241,7 +247,12 @@ fn lower_match_arms( arm.span, &arm.pattern, ArmHasGuard(arm.guard.is_some()), - Some((Some(&scrutinee_place), scrutinee_span)), + Some(( + Some( + &scrutinee_place.clone().into_place(this.tcx, this.typeck_results), + ), + scrutinee_span, + )), ); let arm_block = this.bind_pattern( @@ -446,8 +457,17 @@ pub(super) fn expr_into_pattern( } _ => { - let place = unpack!(block = self.as_place(block, initializer)); - self.place_into_pattern(block, irrefutable_pat, place, true) + // Converts the destruct pattern into a place + // + // We don't want to convert to a place right away + // because in case of such pattern inside a closure, the projections matching a + // captured place might have not been applied. + // [FIXME] Need to find where this is happening and make the necessary changes there once + // Candidate is modified + // + // We want to use a place builder; Maybe use `as_place_builder` + let place_builder = unpack!(block = self.as_place_builder(block, initializer)); + self.place_into_pattern(block, irrefutable_pat, place_builder, true) } } } @@ -456,9 +476,10 @@ pub(super) fn expr_into_pattern( &mut self, block: BasicBlock, irrefutable_pat: Pat<'tcx>, - initializer: Place<'tcx>, + initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { + let place = initializer.clone().into_place(self.tcx, self.typeck_results); let mut candidate = Candidate::new(initializer, &irrefutable_pat, false); let fake_borrow_temps = @@ -478,7 +499,7 @@ pub(super) fn expr_into_pattern( VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, )))) = self.local_decls[local].local_info { - *match_place = Some(initializer); + *match_place = Some(place); } else { bug!("Let binding to non-user variable.") } @@ -717,7 +738,7 @@ struct Candidate<'pat, 'tcx> { } impl<'tcx, 'pat> Candidate<'pat, 'tcx> { - fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self { + fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self { Candidate { span: pattern.span, has_guard, @@ -791,7 +812,7 @@ struct Ascription<'tcx> { #[derive(Clone, Debug)] crate struct MatchPair<'pat, 'tcx> { // this place... - place: Place<'tcx>, + place: PlaceBuilder<'tcx>, // ... must match this pattern. pattern: &'pat Pat<'tcx>, @@ -1198,7 +1219,7 @@ fn test_candidates_with_or( &mut otherwise, pats, or_span, - place, + place.clone(), fake_borrows, ); }); @@ -1224,12 +1245,14 @@ fn test_or_pattern<'pat>( otherwise: &mut Option, pats: &'pat [Pat<'tcx>], or_span: Span, - place: Place<'tcx>, + place: PlaceBuilder<'tcx>, fake_borrows: &mut Option>>, ) { debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats); - let mut or_candidates: Vec<_> = - pats.iter().map(|pat| Candidate::new(place, pat, candidate.has_guard)).collect(); + let mut or_candidates: Vec<_> = pats + .iter() + .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard)) + .collect(); let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect(); let otherwise = if candidate.otherwise_block.is_some() { &mut candidate.otherwise_block @@ -1412,7 +1435,7 @@ fn test_candidates<'pat, 'b, 'c>( // extract the match-pair from the highest priority candidate let match_pair = &candidates.first().unwrap().match_pairs[0]; let mut test = self.test(match_pair); - let match_place = match_pair.place; + let match_place = match_pair.place.clone(); // most of the time, the test to perform is simply a function // of the main candidate; but for a test like SwitchInt, we @@ -1428,7 +1451,7 @@ fn test_candidates<'pat, 'b, 'c>( } TestKind::Switch { adt_def: _, ref mut variants } => { for candidate in candidates.iter() { - if !self.add_variants_to_switch(&match_place, candidate, variants) { + if !self.add_variants_to_switch(&match_place.clone(), candidate, variants) { break; } } @@ -1438,7 +1461,7 @@ fn test_candidates<'pat, 'b, 'c>( // Insert a Shallow borrow of any places that is switched on. if let Some(fb) = fake_borrows { - fb.insert(match_place); + fb.insert(match_place.clone().into_place(self.tcx, self.typeck_results)); } // perform the test, branching to one of N blocks. For each of @@ -1456,7 +1479,7 @@ fn test_candidates<'pat, 'b, 'c>( // encounter a candidate where the test is not relevant; at // that point, we stop sorting. while let Some(candidate) = candidates.first_mut() { - if let Some(idx) = self.sort_candidate(&match_place, &test, candidate) { + if let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) { let (candidate, rest) = candidates.split_first_mut().unwrap(); target_candidates[idx].push(candidate); candidates = rest; @@ -1519,7 +1542,7 @@ fn test_candidates<'pat, 'b, 'c>( target_blocks }; - self.perform_test(block, match_place, &test, make_target_blocks); + self.perform_test(block, match_place.clone(), &test, make_target_blocks); } /// Determine the fake borrows that are needed from a set of places that @@ -1753,11 +1776,13 @@ fn bind_and_guard_matched_candidate<'pat>( } Guard::IfLet(pat, scrutinee) => { let scrutinee_span = scrutinee.span; - let scrutinee_place = - unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span)); - let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false); + let scrutinee_place = unpack!( + block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span) + ); + let mut guard_candidate = Candidate::new(scrutinee_place.clone(), &pat, false); let wildcard = Pat::wildcard_from_ty(pat.ty); - let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false); + let mut otherwise_candidate = + Candidate::new(scrutinee_place.clone(), &wildcard, false); let fake_borrow_temps = self.lower_match_tree( block, pat.span, @@ -1769,7 +1794,10 @@ fn bind_and_guard_matched_candidate<'pat>( pat.span.to(arm_span.unwrap()), pat, ArmHasGuard(false), - Some((Some(&scrutinee_place), scrutinee.span)), + Some(( + Some(&scrutinee_place.clone().into_place(tcx, self.typeck_results)), + scrutinee.span, + )), ); let post_guard_block = self.bind_pattern( self.source_info(pat.span), diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 9931cdf3b9e..d9c1d4abf07 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -12,11 +12,11 @@ //! sort of test: for example, testing which variant an enum is, or //! testing a value against a constant. +use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Ascription, Binding, Candidate, MatchPair}; use crate::build::Builder; use crate::thir::{self, *}; use rustc_hir::RangeEnd; -use rustc_middle::mir::Place; use rustc_middle::ty; use rustc_middle::ty::layout::IntegerExt; use rustc_target::abi::{Integer, Size}; @@ -68,11 +68,12 @@ pub(super) fn simplify_candidate<'pat>( let match_pairs = mem::take(&mut candidate.match_pairs); if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] = - *match_pairs + &*match_pairs.clone() { existing_bindings.extend_from_slice(&new_bindings); mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); + candidate.subcandidates = + self.create_or_subcandidates(candidate, place.clone(), pats); return true; } @@ -125,12 +126,12 @@ pub(super) fn simplify_candidate<'pat>( fn create_or_subcandidates<'pat>( &mut self, candidate: &Candidate<'pat, 'tcx>, - place: Place<'tcx>, + place: PlaceBuilder<'tcx>, pats: &'pat [Pat<'tcx>], ) -> Vec> { pats.iter() .map(|pat| { - let mut candidate = Candidate::new(place, pat, candidate.has_guard); + let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard); self.simplify_candidate(&mut candidate); candidate }) @@ -148,6 +149,9 @@ fn simplify_match_pair<'pat>( candidate: &mut Candidate<'pat, 'tcx>, ) -> Result<(), MatchPair<'pat, 'tcx>> { let tcx = self.tcx; + // Generate place to be used in Ascription + // Generate place to be used in Binding + let place = match_pair.place.clone().into_place(tcx, self.typeck_results); match *match_pair.pattern.kind { PatKind::AscribeUserType { ref subpattern, @@ -158,7 +162,7 @@ fn simplify_match_pair<'pat>( candidate.ascriptions.push(Ascription { span: user_ty_span, user_ty, - source: match_pair.place, + source: place, variance, }); @@ -177,7 +181,7 @@ fn simplify_match_pair<'pat>( name, mutability, span: match_pair.pattern.span, - source: match_pair.place, + source: place, var_id: var, var_ty: ty, binding_mode: mode, @@ -264,8 +268,10 @@ fn simplify_match_pair<'pat>( }) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { - let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index); - candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns)); + let place_builder = match_pair.place.downcast(adt_def, variant_index); + candidate + .match_pairs + .extend(self.field_match_pairs(place_builder, subpatterns)); Ok(()) } else { Err(match_pair) @@ -290,8 +296,8 @@ fn simplify_match_pair<'pat>( } PatKind::Deref { ref subpattern } => { - let place = tcx.mk_place_deref(match_pair.place); - candidate.match_pairs.push(MatchPair::new(place, subpattern)); + let place_builder = match_pair.place.deref(); + candidate.match_pairs.push(MatchPair::new(place_builder, subpattern)); Ok(()) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 48abaa8d35f..b804cd4574f 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -5,6 +5,7 @@ // identify what tests are needed, perform the tests, and then filter // the candidates based on the result. +use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Candidate, MatchPair, Test, TestKind}; use crate::build::Builder; use crate::thir::pattern::compare_const_vals; @@ -81,7 +82,7 @@ pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test< pub(super) fn add_cases_to_switch<'pat>( &mut self, - test_place: &Place<'tcx>, + test_place: &PlaceBuilder<'tcx>, candidate: &Candidate<'pat, 'tcx>, switch_ty: Ty<'tcx>, options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>, @@ -123,7 +124,7 @@ pub(super) fn add_cases_to_switch<'pat>( pub(super) fn add_variants_to_switch<'pat>( &mut self, - test_place: &Place<'tcx>, + test_place: &PlaceBuilder<'tcx>, candidate: &Candidate<'pat, 'tcx>, variants: &mut BitSet, ) -> bool { @@ -151,10 +152,11 @@ pub(super) fn add_variants_to_switch<'pat>( pub(super) fn perform_test( &mut self, block: BasicBlock, - place: Place<'tcx>, + place_builder: PlaceBuilder<'tcx>, test: &Test<'tcx>, make_target_blocks: impl FnOnce(&mut Self) -> Vec, ) { + let place = place_builder.clone().into_place(self.tcx, self.typeck_results); debug!( "perform_test({:?}, {:?}: {:?}, {:?})", block, @@ -481,7 +483,7 @@ fn non_scalar_compare( /// tighter match code if we do something a bit different. pub(super) fn sort_candidate<'pat>( &mut self, - test_place: &Place<'tcx>, + test_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, candidate: &mut Candidate<'pat, 'tcx>, ) -> Option { @@ -728,7 +730,6 @@ fn candidate_after_variant_switch<'pat>( candidate: &mut Candidate<'pat, 'tcx>, ) { let match_pair = candidate.match_pairs.remove(match_pair_index); - let tcx = self.tcx; // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`, // we want to create a set of derived match-patterns like @@ -737,10 +738,10 @@ fn candidate_after_variant_switch<'pat>( Some(adt_def.variants[variant_index].ident.name), variant_index, ); - let downcast_place = tcx.mk_place_elem(match_pair.place, elem); // `(x as Variant)` + let downcast_place = match_pair.place.project(elem); // `(x as Variant)` let consequent_match_pairs = subpatterns.iter().map(|subpattern| { // e.g., `(x as Variant).0` - let place = tcx.mk_place_field(downcast_place, subpattern.field, subpattern.pattern.ty); + let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty); // e.g., `(x as Variant).0 @ P1` MatchPair::new(place, &subpattern.pattern) }); diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 15aca0203aa..d49a00a5660 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -1,3 +1,4 @@ +use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::MatchPair; use crate::build::Builder; use crate::thir::*; @@ -9,13 +10,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn field_match_pairs<'pat>( &mut self, - place: Place<'tcx>, + place: PlaceBuilder<'tcx>, subpatterns: &'pat [FieldPat<'tcx>], ) -> Vec> { subpatterns .iter() .map(|fieldpat| { - let place = self.tcx.mk_place_field(place, fieldpat.field, fieldpat.pattern.ty); + let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty); MatchPair::new(place, &fieldpat.pattern) }) .collect() @@ -24,13 +25,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn prefix_slice_suffix<'pat>( &mut self, match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>, - place: &Place<'tcx>, + place: &PlaceBuilder<'tcx>, prefix: &'pat [Pat<'tcx>], opt_slice: Option<&'pat Pat<'tcx>>, suffix: &'pat [Pat<'tcx>], ) { let tcx = self.tcx; - let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() { + let (min_length, exact_size) = match place + .clone() + .into_place(tcx, self.typeck_results) + .ty(&self.local_decls, tcx) + .ty + .kind() + { ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), }; @@ -38,20 +45,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; - let place = tcx.mk_place_elem(*place, elem); + let place = place.clone().project(elem); MatchPair::new(place, subpattern) })); if let Some(subslice_pat) = opt_slice { let suffix_len = suffix.len() as u64; - let subslice = tcx.mk_place_elem( - *place, - ProjectionElem::Subslice { - from: prefix.len() as u64, - to: if exact_size { min_length - suffix_len } else { suffix_len }, - from_end: !exact_size, - }, - ); + let subslice = place.clone().project(ProjectionElem::Subslice { + from: prefix.len() as u64, + to: if exact_size { min_length - suffix_len } else { suffix_len }, + from_end: !exact_size, + }); match_pairs.push(MatchPair::new(subslice, subslice_pat)); } @@ -62,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { min_length, from_end: !exact_size, }; - let place = tcx.mk_place_elem(*place, elem); + let place = place.clone().project(elem); MatchPair::new(place, subpattern) })); } @@ -91,7 +95,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { - crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> { + crate fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> { MatchPair { place, pattern } } } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9c83c0d09aa..4bc497f5ce2 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,4 +1,5 @@ use crate::build; +use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; use crate::thir::{build_thir, Arena, BindingMode, Expr, LintLevel, Pat, PatKind}; use rustc_attr::{self as attr, UnwindAttr}; @@ -1004,7 +1005,10 @@ fn args_and_body( matches::ArmHasGuard(false), Some((Some(&place), span)), ); - unpack!(block = self.place_into_pattern(block, pattern, place, false)); + let place_builder = PlaceBuilder::from(local); + unpack!( + block = self.place_into_pattern(block, pattern, place_builder, false) + ); } } self.source_scope = original_source_scope;