diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:03:36 +0000 |
commit | 17d40c6057c88f4c432b0d7bac88e1b84cb7e67f (patch) | |
tree | 3f66c4a5918660bb8a758ab6cda5ff8ee4f6cdcd /compiler/rustc_mir_build/src/build/matches/mod.rs | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-f7f0cc2a5d72e2c61c1f6900e70eec992bea4273.tar.xz rustc-f7f0cc2a5d72e2c61c1f6900e70eec992bea4273.zip |
Adding upstream version 1.65.0+dfsg1.upstream/1.65.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | compiler/rustc_mir_build/src/build/matches/mod.rs | 157 |
1 files changed, 73 insertions, 84 deletions
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 58b1564cc..93f382cc6 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// * From each pre-binding block to the next pre-binding block. /// * From each otherwise block to the next pre-binding block. - #[tracing::instrument(level = "debug", skip(self, arms))] + #[instrument(level = "debug", skip(self, arms))] pub(crate) fn match_expr( &mut self, destination: Place<'tcx>, @@ -170,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms); - let match_has_guard = arms.iter().copied().any(|arm| self.thir[arm].guard.is_some()); + let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard); let mut candidates = arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>(); @@ -221,9 +221,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = self.source_info(scrutinee_span); if let Ok(scrutinee_builder) = - scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, self.typeck_results) + scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, &self.upvars) { - let scrutinee_place = scrutinee_builder.into_place(self.tcx, self.typeck_results); + let scrutinee_place = scrutinee_builder.into_place(self.tcx, &self.upvars); self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place); } @@ -348,12 +348,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // ``` let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None; let scrutinee_place: Place<'tcx>; - if let Ok(scrutinee_builder) = scrutinee_place_builder - .clone() - .try_upvars_resolved(this.tcx, this.typeck_results) + if let Ok(scrutinee_builder) = + scrutinee_place_builder.clone().try_upvars_resolved(this.tcx, &this.upvars) { - scrutinee_place = - scrutinee_builder.into_place(this.tcx, this.typeck_results); + scrutinee_place = scrutinee_builder.into_place(this.tcx, &this.upvars); opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span)); } let scope = this.declare_bindings( @@ -373,6 +371,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Some(arm.span), Some(arm.scope), Some(match_scope), + false, ); if let Some(source_scope) = scope { @@ -418,6 +417,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm_span: Option<Span>, arm_scope: Option<region::Scope>, match_scope: Option<region::Scope>, + storages_alive: bool, ) -> BasicBlock { if candidate.subcandidates.is_empty() { // Avoid generating another `BasicBlock` when we only have one @@ -431,6 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm_span, match_scope, true, + storages_alive, ) } else { // It's helpful to avoid scheduling drops multiple times to save @@ -468,6 +469,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm_span, match_scope, schedule_drops, + storages_alive, ); if arm_scope.is_none() { schedule_drops = false; @@ -490,10 +492,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(super) fn expr_into_pattern( &mut self, mut block: BasicBlock, - irrefutable_pat: Pat<'tcx>, + irrefutable_pat: &Pat<'tcx>, initializer: &Expr<'tcx>, ) -> BlockAnd<()> { - match *irrefutable_pat.kind { + match irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { let place = @@ -518,17 +520,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // broken. PatKind::AscribeUserType { subpattern: - Pat { + box Pat { kind: - box PatKind::Binding { - mode: BindingMode::ByValue, - var, - subpattern: None, - .. + PatKind::Binding { + mode: BindingMode::ByValue, var, subpattern: None, .. }, .. }, - ascription: thir::Ascription { annotation, variance: _ }, + ascription: thir::Ascription { ref annotation, variance: _ }, } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); @@ -541,7 +540,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty_source_info = self.source_info(annotation.span); - let base = self.canonical_user_type_annotations.push(annotation); + let base = self.canonical_user_type_annotations.push(annotation.clone()); self.cfg.push( block, Statement { @@ -573,7 +572,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => { let place_builder = unpack!(block = self.as_place_builder(block, initializer)); - self.place_into_pattern(block, irrefutable_pat, place_builder, true) + self.place_into_pattern(block, &irrefutable_pat, place_builder, true) } } } @@ -581,7 +580,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub(crate) fn place_into_pattern( &mut self, block: BasicBlock, - irrefutable_pat: Pat<'tcx>, + irrefutable_pat: &Pat<'tcx>, initializer: PlaceBuilder<'tcx>, set_match_place: bool, ) -> BlockAnd<()> { @@ -623,9 +622,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // }; // ``` if let Ok(match_pair_resolved) = - initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results) + initializer.clone().try_upvars_resolved(self.tcx, &self.upvars) { - let place = match_pair_resolved.into_place(self.tcx, self.typeck_results); + let place = match_pair_resolved.into_place(self.tcx, &self.upvars); *match_place = Some(place); } } @@ -646,6 +645,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, None, None, + false, ) .unit() } @@ -702,9 +702,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); - // Altough there is almost always scope for given variable in corner cases + // Although there is almost always scope for given variable in corner cases // like #92893 we might get variable with no scope. - if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) && schedule_drop{ + if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) && schedule_drop { self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } Place::from(local_id) @@ -744,7 +744,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty ); - match *pattern.kind { + match pattern.kind { PatKind::Binding { mutability, name, @@ -767,7 +767,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Slice { ref prefix, ref slice, ref suffix } => { let from = u64::try_from(prefix.len()).unwrap(); let to = u64::try_from(suffix.len()).unwrap(); - for subpattern in prefix { + for subpattern in prefix.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } for subpattern in slice { @@ -777,7 +777,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { f, ); } - for subpattern in suffix { + for subpattern in suffix.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); } } @@ -830,7 +830,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // may not all be in the leftmost subpattern. For example in // `let (x | y) = ...`, the primary binding of `y` occurs in // the right subpattern - for subpattern in pats { + for subpattern in pats.iter() { self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f); } } @@ -982,7 +982,7 @@ enum TestKind<'tcx> { }, /// Test whether the value falls within an inclusive or exclusive range - Range(PatRange<'tcx>), + Range(Box<PatRange<'tcx>>), /// Test that the length of the slice is equal to `len`. Len { len: u64, op: BinOp }, @@ -1330,7 +1330,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // All of the or-patterns have been sorted to the end, so if the first // pattern is an or-pattern we only have or-patterns. - match *first_candidate.match_pairs[0].pattern.kind { + match first_candidate.match_pairs[0].pattern.kind { PatKind::Or { .. } => (), _ => { self.test_candidates( @@ -1350,7 +1350,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut otherwise = None; for match_pair in match_pairs { - let PatKind::Or { ref pats } = &*match_pair.pattern.kind else { + let PatKind::Or { ref pats } = &match_pair.pattern.kind else { bug!("Or-patterns should have been sorted to the end"); }; let or_span = match_pair.pattern.span; @@ -1384,7 +1384,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &mut Candidate<'pat, 'tcx>, otherwise: &mut Option<BasicBlock>, - pats: &'pat [Pat<'tcx>], + pats: &'pat [Box<Pat<'tcx>>], or_span: Span, place: PlaceBuilder<'tcx>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>, @@ -1605,9 +1605,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Insert a Shallow borrow of any places that is switched on. if let Some(fb) = fake_borrows && let Ok(match_place_resolved) = - match_place.clone().try_upvars_resolved(self.tcx, self.typeck_results) + match_place.clone().try_upvars_resolved(self.tcx, &self.upvars) { - let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results); + let resolved_place = match_place_resolved.into_place(self.tcx, &self.upvars); fb.insert(resolved_place); } @@ -1794,10 +1794,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None; let expr_place: Place<'tcx>; - if let Ok(expr_builder) = - expr_place_builder.try_upvars_resolved(self.tcx, self.typeck_results) - { - expr_place = expr_builder.into_place(self.tcx, self.typeck_results); + if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self.tcx, &self.upvars) { + expr_place = expr_builder.into_place(self.tcx, &self.upvars); opt_expr_place = Some((Some(&expr_place), expr_span)); } let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); @@ -1820,6 +1818,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, None, None, + false, ); post_guard_block.unit() @@ -1843,6 +1842,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { arm_span: Option<Span>, match_scope: Option<region::Scope>, schedule_drops: bool, + storages_alive: bool, ) -> BasicBlock { debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate); @@ -1978,7 +1978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut guard_span = rustc_span::DUMMY_SP; let (post_guard_block, otherwise_post_guard_block) = - self.in_if_then_scope(match_scope, |this| match *guard { + self.in_if_then_scope(match_scope, guard_span, |this| match *guard { Guard::If(e) => { let e = &this.thir[e]; guard_span = e.span; @@ -2058,7 +2058,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(local_id)); } assert!(schedule_drops, "patterns with guards must schedule drops"); - self.bind_matched_candidate_for_arm_body(post_guard_block, true, by_value_bindings); + self.bind_matched_candidate_for_arm_body( + post_guard_block, + true, + by_value_bindings, + storages_alive, + ); post_guard_block } else { @@ -2072,6 +2077,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .iter() .flat_map(|(bindings, _)| bindings) .chain(&candidate.bindings), + storages_alive, ); block } @@ -2161,6 +2167,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block: BasicBlock, schedule_drops: bool, bindings: impl IntoIterator<Item = &'b Binding<'tcx>>, + storages_alive: bool, ) where 'tcx: 'b, { @@ -2170,13 +2177,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Assign each of the bindings. This may trigger moves out of the candidate. for binding in bindings { let source_info = self.source_info(binding.span); - let local = self.storage_live_binding( - block, - binding.var_id, - binding.span, - OutsideGuard, - schedule_drops, - ); + let local = if storages_alive { + // Here storages are already alive, probably because this is a binding + // from let-else. + // We just need to schedule drop for the value. + self.var_local_id(binding.var_id, OutsideGuard).into() + } else { + self.storage_live_binding( + block, + binding.var_id, + binding.span, + OutsideGuard, + schedule_drops, + ) + }; if schedule_drops { self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); } @@ -2280,23 +2294,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, init: &Expr<'tcx>, initializer_span: Span, - else_block: &Block, - visibility_scope: Option<SourceScope>, - remainder_scope: region::Scope, - remainder_span: Span, + else_block: BlockId, + let_else_scope: ®ion::Scope, pattern: &Pat<'tcx>, - ) -> BlockAnd<()> { - let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| { + ) -> BlockAnd<BasicBlock> { + let else_block_span = self.thir[else_block].span; + let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| { let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span)); - let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) }; + let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild }; let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false); - this.declare_bindings( - visibility_scope, - remainder_span, - pattern, - ArmHasGuard(false), - Some((None, initializer_span)), - ); let mut candidate = Candidate::new(scrutinee.clone(), pattern, false); let fake_borrow_temps = this.lower_match_tree( block, @@ -2315,10 +2321,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, None, None, + true, ); // This block is for the failure case let failure = this.bind_pattern( - this.source_info(else_block.span), + this.source_info(else_block_span), wildcard, None, &fake_borrow_temps, @@ -2326,29 +2333,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, None, None, + true, ); - this.break_for_else(failure, remainder_scope, this.source_info(initializer_span)); + this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span)); matching.unit() }); - - // This place is not really used because this destination place - // should never be used to take values at the end of the failure - // block. - let dummy_place = Place { local: RETURN_PLACE, projection: ty::List::empty() }; - let failure_block; - unpack!( - failure_block = self.ast_block( - dummy_place, - failure, - else_block, - self.source_info(else_block.span), - ) - ); - self.cfg.terminate( - failure_block, - self.source_info(else_block.span), - TerminatorKind::Unreachable, - ); - matching.unit() + matching.and(failure) } } |