1
Fork 0

Merge two arguments into one

This commit is contained in:
Oli Scherer 2022-09-13 08:51:45 +00:00
parent 22f6aec42d
commit 5d664f7a8f
11 changed files with 92 additions and 127 deletions

View file

@ -69,7 +69,7 @@ pub(crate) enum PlaceBase {
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b` /// 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`. /// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub(crate) struct PlaceBuilder<'tcx> { pub(in crate::build) struct PlaceBuilder<'tcx> {
base: PlaceBase, base: PlaceBase,
projection: Vec<PlaceElem<'tcx>>, projection: Vec<PlaceElem<'tcx>>,
} }
@ -168,22 +168,22 @@ fn find_capture_matching_projections<'a, 'tcx>(
/// `PlaceBuilder` now starts from `PlaceBase::Local`. /// `PlaceBuilder` now starts from `PlaceBase::Local`.
/// ///
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found. /// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
fn to_upvars_resolved_place_builder<'a, 'tcx>( #[instrument(level = "trace", skip(cx))]
fn to_upvars_resolved_place_builder<'tcx>(
from_builder: PlaceBuilder<'tcx>, from_builder: PlaceBuilder<'tcx>,
tcx: TyCtxt<'tcx>, cx: &Builder<'_, 'tcx>,
upvars: &'a CaptureMap<'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> { ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
match from_builder.base { match from_builder.base {
PlaceBase::Local(_) => Ok(from_builder), PlaceBase::Local(_) => Ok(from_builder),
PlaceBase::Upvar { var_hir_id, closure_def_id } => { PlaceBase::Upvar { var_hir_id, closure_def_id } => {
let Some((capture_index, capture)) = let Some((capture_index, capture)) =
find_capture_matching_projections( find_capture_matching_projections(
upvars, &cx.upvars,
var_hir_id, var_hir_id,
&from_builder.projection, &from_builder.projection,
) else { ) else {
let closure_span = tcx.def_span(closure_def_id); let closure_span = cx.tcx.def_span(closure_def_id);
if !enable_precise_capture(tcx, closure_span) { if !enable_precise_capture(cx.tcx, closure_span) {
bug!( bug!(
"No associated capture found for {:?}[{:#?}] even though \ "No associated capture found for {:?}[{:#?}] even though \
capture_disjoint_fields isn't enabled", capture_disjoint_fields isn't enabled",
@ -200,18 +200,20 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
}; };
// Access the capture by accessing the field within the Closure struct. // Access the capture by accessing the field within the Closure struct.
let capture_info = &upvars[capture_index]; let capture_info = &cx.upvars[capture_index];
let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place); let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
// We used some of the projections to build the capture itself, // We used some of the projections to build the capture itself,
// now we apply the remaining to the upvar resolved place. // now we apply the remaining to the upvar resolved place.
trace!(?capture.captured_place, ?from_builder.projection);
let remaining_projections = strip_prefix( let remaining_projections = strip_prefix(
capture.captured_place.place.base_ty, capture.captured_place.place.base_ty,
from_builder.projection, from_builder.projection,
&capture.captured_place.place.projections, &capture.captured_place.place.projections,
); );
upvar_resolved_place_builder.projection.extend(remaining_projections); upvar_resolved_place_builder.projection.extend(remaining_projections);
trace!(?upvar_resolved_place_builder);
Ok(upvar_resolved_place_builder) Ok(upvar_resolved_place_builder)
} }
@ -251,24 +253,16 @@ fn strip_prefix<'tcx>(
} }
impl<'tcx> PlaceBuilder<'tcx> { impl<'tcx> PlaceBuilder<'tcx> {
pub(in crate::build) fn into_place<'a>( pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
self,
tcx: TyCtxt<'tcx>,
upvars: &'a CaptureMap<'tcx>,
) -> Place<'tcx> {
if let PlaceBase::Local(local) = self.base { if let PlaceBase::Local(local) = self.base {
Place { local, projection: tcx.intern_place_elems(&self.projection) } Place { local, projection: cx.tcx.intern_place_elems(&self.projection) }
} else { } else {
self.expect_upvars_resolved(tcx, upvars).into_place(tcx, upvars) self.expect_upvars_resolved(cx).into_place(cx)
} }
} }
fn expect_upvars_resolved<'a>( fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
self, to_upvars_resolved_place_builder(self, cx).unwrap()
tcx: TyCtxt<'tcx>,
upvars: &'a CaptureMap<'tcx>,
) -> PlaceBuilder<'tcx> {
to_upvars_resolved_place_builder(self, tcx, upvars).unwrap()
} }
/// Attempts to resolve the `PlaceBuilder`. /// Attempts to resolve the `PlaceBuilder`.
@ -282,12 +276,11 @@ impl<'tcx> PlaceBuilder<'tcx> {
/// not captured. This can happen because the final mir that will be /// not captured. This can happen because the final mir that will be
/// generated doesn't require a read for this place. Failures will only /// generated doesn't require a read for this place. Failures will only
/// happen inside closures. /// happen inside closures.
pub(in crate::build) fn try_upvars_resolved<'a>( pub(in crate::build) fn try_upvars_resolved(
self, self,
tcx: TyCtxt<'tcx>, cx: &Builder<'_, 'tcx>,
upvars: &'a CaptureMap<'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> { ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
to_upvars_resolved_place_builder(self, tcx, upvars) to_upvars_resolved_place_builder(self, cx)
} }
pub(crate) fn base(&self) -> PlaceBase { pub(crate) fn base(&self) -> PlaceBase {
@ -353,7 +346,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> { ) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_place_builder(block, expr)); let place_builder = unpack!(block = self.as_place_builder(block, expr));
block.and(place_builder.into_place(self.tcx, &self.upvars)) block.and(place_builder.into_place(self))
} }
/// This is used when constructing a compound `Place`, so that we can avoid creating /// This is used when constructing a compound `Place`, so that we can avoid creating
@ -377,7 +370,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> { ) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
block.and(place_builder.into_place(self.tcx, &self.upvars)) block.and(place_builder.into_place(self))
} }
/// This is used when constructing a compound `Place`, so that we can avoid creating /// This is used when constructing a compound `Place`, so that we can avoid creating
@ -472,7 +465,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
inferred_ty: expr.ty, inferred_ty: expr.ty,
}); });
let place = place_builder.clone().into_place(this.tcx, &this.upvars); let place = place_builder.clone().into_place(this);
this.cfg.push( this.cfg.push(
block, block,
Statement { Statement {
@ -610,7 +603,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if is_outermost_index { if is_outermost_index {
self.read_fake_borrows(block, fake_borrow_temps, source_info) self.read_fake_borrows(block, fake_borrow_temps, source_info)
} else { } else {
base_place = base_place.expect_upvars_resolved(self.tcx, &self.upvars); base_place = base_place.expect_upvars_resolved(self);
self.add_fake_borrows_of_base( self.add_fake_borrows_of_base(
&base_place, &base_place,
block, block,
@ -638,12 +631,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let lt = self.temp(bool_ty, expr_span); let lt = self.temp(bool_ty, expr_span);
// len = len(slice) // len = len(slice)
self.cfg.push_assign( self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
block,
source_info,
len,
Rvalue::Len(slice.into_place(self.tcx, &self.upvars)),
);
// lt = idx < len // lt = idx < len
self.cfg.push_assign( self.cfg.push_assign(
block, block,

View file

@ -329,10 +329,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let place_builder = let place_builder =
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place])); unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
if let Ok(place_builder_resolved) = if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
place_builder.try_upvars_resolved(this.tcx, &this.upvars) let mir_place = place_builder_resolved.into_place(this);
{
let mir_place = place_builder_resolved.into_place(this.tcx, &this.upvars);
this.cfg.push_fake_read( this.cfg.push_fake_read(
block, block,
this.source_info(this.tcx.hir().span(*hir_id)), this.source_info(this.tcx.hir().span(*hir_id)),
@ -623,8 +621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// by the parent itself. The mutability of the current capture // by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure. // is same as that of the capture in the parent closure.
PlaceBase::Upvar { .. } => { PlaceBase::Upvar { .. } => {
let enclosing_upvars_resolved = let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
arg_place_builder.clone().into_place(this.tcx, &this.upvars);
match enclosing_upvars_resolved.as_ref() { match enclosing_upvars_resolved.as_ref() {
PlaceRef { PlaceRef {
@ -661,7 +658,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
}; };
let arg_place = arg_place_builder.into_place(this.tcx, &this.upvars); let arg_place = arg_place_builder.into_place(this);
this.cfg.push_assign( this.cfg.push_assign(
block, block,

View file

@ -23,6 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability)) ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
} }
#[instrument(skip(self), level = "debug")]
fn as_temp_inner( fn as_temp_inner(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
@ -30,10 +31,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
mutability: Mutability, mutability: Mutability,
) -> BlockAnd<Local> { ) -> BlockAnd<Local> {
debug!(
"as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
block, temp_lifetime, expr, mutability
);
let this = self; let this = self;
let expr_span = expr.span; let expr_span = expr.span;

View file

@ -15,14 +15,13 @@ use std::iter;
impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which /// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized. /// is assumed to be uninitialized.
#[instrument(level = "debug", skip(self))]
pub(crate) fn expr_into_dest( pub(crate) fn expr_into_dest(
&mut self, &mut self,
destination: Place<'tcx>, destination: Place<'tcx>,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
// since we frequently have to reference `self` from within a // since we frequently have to reference `self` from within a
// closure, where `self` would be shadowed, it's easier to // closure, where `self` would be shadowed, it's easier to
// just use the name `this` uniformly // just use the name `this` uniformly
@ -366,7 +365,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None => { None => {
let place_builder = place_builder.clone(); let place_builder = place_builder.clone();
this.consume_by_copy_or_move( this.consume_by_copy_or_move(
place_builder.field(n, *ty).into_place(this.tcx, &this.upvars), place_builder.field(n, *ty).into_place(this),
) )
} }
}) })

View file

@ -220,10 +220,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let cause_matched_place = FakeReadCause::ForMatchedPlace(None); let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
let source_info = self.source_info(scrutinee_span); let source_info = self.source_info(scrutinee_span);
if let Ok(scrutinee_builder) = if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, &self.upvars) let scrutinee_place = scrutinee_builder.into_place(self);
{
let scrutinee_place = scrutinee_builder.into_place(self.tcx, &self.upvars);
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place); self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
} }
@ -349,9 +347,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None; let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
let scrutinee_place: Place<'tcx>; let scrutinee_place: Place<'tcx>;
if let Ok(scrutinee_builder) = if let Ok(scrutinee_builder) =
scrutinee_place_builder.clone().try_upvars_resolved(this.tcx, &this.upvars) scrutinee_place_builder.clone().try_upvars_resolved(this)
{ {
scrutinee_place = scrutinee_builder.into_place(this.tcx, &this.upvars); scrutinee_place = scrutinee_builder.into_place(this);
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span)); opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
} }
let scope = this.declare_bindings( let scope = this.declare_bindings(
@ -597,12 +595,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
while let Some(next) = { while let Some(next) = {
for binding in &candidate_ref.bindings { for binding in &candidate_ref.bindings {
let local = self.var_local_id(binding.var_id, OutsideGuard); let local = self.var_local_id(binding.var_id, OutsideGuard);
let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
)))) = self.local_decls[local].local_info else {
bug!("Let binding to non-user variable.")
};
// `try_upvars_resolved` may fail if it is unable to resolve the given // `try_upvars_resolved` may fail if it is unable to resolve the given
// `PlaceBuilder` inside a closure. In this case, we don't want to include // `PlaceBuilder` inside a closure. In this case, we don't want to include
// a scrutinee place. `scrutinee_place_builder` will fail for destructured // a scrutinee place. `scrutinee_place_builder` will fail for destructured
@ -617,10 +609,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let (v1, v2) = foo; // let (v1, v2) = foo;
// }; // };
// ``` // ```
if let Ok(match_pair_resolved) = if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
initializer.clone().try_upvars_resolved(self.tcx, &self.upvars) let place = match_pair_resolved.into_place(self);
{
let place = match_pair_resolved.into_place(self.tcx, &self.upvars); let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
)))) = self.local_decls[local].local_info else {
bug!("Let binding to non-user variable.")
};
*match_place = Some(place); *match_place = Some(place);
} }
} }
@ -649,6 +645,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// scope for the bindings in these patterns, if such a scope had to be /// scope for the bindings in these patterns, if such a scope had to be
/// created. NOTE: Declaring the bindings should always be done in their /// created. NOTE: Declaring the bindings should always be done in their
/// drop scope. /// drop scope.
#[instrument(skip(self), level = "debug")]
pub(crate) fn declare_bindings( pub(crate) fn declare_bindings(
&mut self, &mut self,
mut visibility_scope: Option<SourceScope>, mut visibility_scope: Option<SourceScope>,
@ -657,7 +654,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
has_guard: ArmHasGuard, has_guard: ArmHasGuard,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> { ) -> Option<SourceScope> {
debug!("declare_bindings: pattern={:?}", pattern);
self.visit_primary_bindings( self.visit_primary_bindings(
&pattern, &pattern,
UserTypeProjections::none(), UserTypeProjections::none(),
@ -867,7 +863,7 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
Candidate { Candidate {
span: pattern.span, span: pattern.span,
has_guard, has_guard,
match_pairs: smallvec![MatchPair { place, pattern }], match_pairs: smallvec![MatchPair::new(place, pattern)],
bindings: Vec::new(), bindings: Vec::new(),
ascriptions: Vec::new(), ascriptions: Vec::new(),
subcandidates: Vec::new(), subcandidates: Vec::new(),
@ -1043,6 +1039,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// if `x.0` matches `false` (for the third arm). In the (impossible at /// if `x.0` matches `false` (for the third arm). In the (impossible at
/// runtime) case when `x.0` is now `true`, we branch to /// runtime) case when `x.0` is now `true`, we branch to
/// `otherwise_block`. /// `otherwise_block`.
#[instrument(skip(self, fake_borrows), level = "debug")]
fn match_candidates<'pat>( fn match_candidates<'pat>(
&mut self, &mut self,
span: Span, span: Span,
@ -1052,11 +1049,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidates: &mut [&mut Candidate<'pat, 'tcx>], candidates: &mut [&mut Candidate<'pat, 'tcx>],
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
debug!(
"matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
span, candidates, start_block, otherwise_block,
);
// Start by simplifying candidates. Once this process is complete, all // Start by simplifying candidates. Once this process is complete, all
// the match pairs which remain require some form of test, whether it // the match pairs which remain require some form of test, whether it
// be a switch or pattern comparison. // be a switch or pattern comparison.
@ -1375,6 +1367,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
) )
} }
#[instrument(
skip(self, otherwise, or_span, place, fake_borrows, candidate, pats),
level = "debug"
)]
fn test_or_pattern<'pat>( fn test_or_pattern<'pat>(
&mut self, &mut self,
candidate: &mut Candidate<'pat, 'tcx>, candidate: &mut Candidate<'pat, 'tcx>,
@ -1384,7 +1380,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
place: PlaceBuilder<'tcx>, place: PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats); debug!("candidate={:#?}\npats={:#?}", candidate, pats);
let mut or_candidates: Vec<_> = pats let mut or_candidates: Vec<_> = pats
.iter() .iter()
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard)) .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
@ -1600,9 +1596,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Insert a Shallow borrow of any places that is switched on. // Insert a Shallow borrow of any places that is switched on.
if let Some(fb) = fake_borrows && let Ok(match_place_resolved) = if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
match_place.clone().try_upvars_resolved(self.tcx, &self.upvars) match_place.clone().try_upvars_resolved(self)
{ {
let resolved_place = match_place_resolved.into_place(self.tcx, &self.upvars); let resolved_place = match_place_resolved.into_place(self);
fb.insert(resolved_place); fb.insert(resolved_place);
} }
@ -1629,9 +1625,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidates = rest; candidates = rest;
} }
// at least the first candidate ought to be tested // at least the first candidate ought to be tested
assert!(total_candidate_count > candidates.len()); assert!(
debug!("test_candidates: tested_candidates: {}", total_candidate_count - candidates.len()); total_candidate_count > candidates.len(),
debug!("test_candidates: untested_candidates: {}", candidates.len()); "{}, {:#?}",
total_candidate_count,
candidates
);
debug!("tested_candidates: {}", total_candidate_count - candidates.len());
debug!("untested_candidates: {}", candidates.len());
// HACK(matthewjasper) This is a closure so that we can let the test // HACK(matthewjasper) This is a closure so that we can let the test
// create its blocks before the rest of the match. This currently // create its blocks before the rest of the match. This currently
@ -1789,8 +1790,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
); );
let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None; let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
let expr_place: Place<'tcx>; let expr_place: Place<'tcx>;
if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self.tcx, &self.upvars) { if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
expr_place = expr_builder.into_place(self.tcx, &self.upvars); expr_place = expr_builder.into_place(self);
opt_expr_place = Some((Some(&expr_place), expr_span)); opt_expr_place = Some((Some(&expr_place), expr_span));
} }
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
@ -2188,6 +2189,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// first local is a binding for occurrences of `var` in the guard, which /// first local is a binding for occurrences of `var` in the guard, which
/// will have type `&T`. The second local is a binding for occurrences of /// will have type `&T`. The second local is a binding for occurrences of
/// `var` in the arm body, which will have type `T`. /// `var` in the arm body, which will have type `T`.
#[instrument(skip(self), level = "debug")]
fn declare_binding( fn declare_binding(
&mut self, &mut self,
source_info: SourceInfo, source_info: SourceInfo,
@ -2202,19 +2204,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place: Option<(Option<Place<'tcx>>, Span)>, opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
pat_span: Span, pat_span: Span,
) { ) {
debug!(
"declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
visibility_scope={:?}, source_info={:?})",
var_id, name, mode, var_ty, visibility_scope, source_info
);
let tcx = self.tcx; let tcx = self.tcx;
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope }; let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
let binding_mode = match mode { let binding_mode = match mode {
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability), BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability), BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
}; };
debug!("declare_binding: user_ty={:?}", user_ty);
let local = LocalDecl::<'tcx> { let local = LocalDecl::<'tcx> {
mutability, mutability,
ty: var_ty, ty: var_ty,
@ -2264,7 +2259,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else { } else {
LocalsForNode::One(for_arm_body) LocalsForNode::One(for_arm_body)
}; };
debug!("declare_binding: vars={:?}", locals); debug!(?locals);
self.var_indices.insert(var_id, locals); self.var_indices.insert(var_id, locals);
} }

View file

@ -37,12 +37,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// ///
/// only generates a single switch. If this happens this method returns /// only generates a single switch. If this happens this method returns
/// `true`. /// `true`.
#[instrument(skip(self, candidate), level = "debug")]
pub(super) fn simplify_candidate<'pat>( pub(super) fn simplify_candidate<'pat>(
&mut self, &mut self,
candidate: &mut Candidate<'pat, 'tcx>, candidate: &mut Candidate<'pat, 'tcx>,
) -> bool { ) -> bool {
// repeatedly simplify match pairs until fixed point is reached // repeatedly simplify match pairs until fixed point is reached
debug!(?candidate, "simplify_candidate"); debug!("{candidate:#?}");
// existing_bindings and new_bindings exists to keep the semantics in order. // existing_bindings and new_bindings exists to keep the semantics in order.
// Reversing the binding order for bindings after `@` changes the binding order in places // Reversing the binding order for bindings after `@` changes the binding order in places
@ -155,12 +156,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ascription: thir::Ascription { ref annotation, variance }, ascription: thir::Ascription { ref annotation, variance },
} => { } => {
// Apply the type ascription to the value at `match_pair.place`, which is the // Apply the type ascription to the value at `match_pair.place`, which is the
if let Ok(place_resolved) = if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
{
candidate.ascriptions.push(Ascription { candidate.ascriptions.push(Ascription {
annotation: annotation.clone(), annotation: annotation.clone(),
source: place_resolved.into_place(self.tcx, &self.upvars), source: place_resolved.into_place(self),
variance, variance,
}); });
} }
@ -184,12 +183,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ref subpattern, ref subpattern,
is_primary: _, is_primary: _,
} => { } => {
if let Ok(place_resolved) = if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
{
candidate.bindings.push(Binding { candidate.bindings.push(Binding {
span: match_pair.pattern.span, span: match_pair.pattern.span,
source: place_resolved.into_place(self.tcx, &self.upvars), source: place_resolved.into_place(self),
var_id: var, var_id: var,
binding_mode: mode, binding_mode: mode,
}); });

View file

@ -144,6 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
} }
#[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
pub(super) fn perform_test( pub(super) fn perform_test(
&mut self, &mut self,
match_start_span: Span, match_start_span: Span,
@ -153,19 +154,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
test: &Test<'tcx>, test: &Test<'tcx>,
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>, make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
) { ) {
let place: Place<'tcx>; let place = place_builder.into_place(self);
if let Ok(test_place_builder) = place_builder.try_upvars_resolved(self.tcx, &self.upvars) { let place_ty = place.ty(&self.local_decls, self.tcx);
place = test_place_builder.into_place(self.tcx, &self.upvars); debug!(?place, ?place_ty,);
} else {
return;
}
debug!(
"perform_test({:?}, {:?}: {:?}, {:?})",
block,
place,
place.ty(&self.local_decls, self.tcx),
test
);
let source_info = self.source_info(test.span); let source_info = self.source_info(test.span);
match test.kind { match test.kind {
@ -733,9 +724,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`, // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
// we want to create a set of derived match-patterns like // we want to create a set of derived match-patterns like
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`. // `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
let elem = let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| { let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0` // e.g., `(x as Variant).0`
let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty); let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);

View file

@ -31,17 +31,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
suffix: &'pat [Box<Pat<'tcx>>], suffix: &'pat [Box<Pat<'tcx>>],
) { ) {
let tcx = self.tcx; let tcx = self.tcx;
let (min_length, exact_size) = if let Ok(place_resolved) = let (min_length, exact_size) =
place.clone().try_upvars_resolved(tcx, &self.upvars) if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
{ match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
match place_resolved.into_place(tcx, &self.upvars).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),
ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), }
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), } else {
} ((prefix.len() + suffix.len()).try_into().unwrap(), false)
} else { };
((prefix.len() + suffix.len()).try_into().unwrap(), false)
};
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
let elem = let elem =
@ -96,7 +94,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
pub(crate) fn new( pub(in crate::build) fn new(
place: PlaceBuilder<'tcx>, place: PlaceBuilder<'tcx>,
pattern: &'pat Pat<'tcx>, pattern: &'pat Pat<'tcx>,
) -> MatchPair<'pat, 'tcx> { ) -> MatchPair<'pat, 'tcx> {

View file

@ -553,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Convenience wrapper that pushes a scope and then executes `f` /// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards. /// to build its contents, popping the scope afterwards.
#[instrument(skip(self, f), level = "debug")]
pub(crate) fn in_scope<F, R>( pub(crate) fn in_scope<F, R>(
&mut self, &mut self,
region_scope: (region::Scope, SourceInfo), region_scope: (region::Scope, SourceInfo),
@ -562,7 +563,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
where where
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>, F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
{ {
debug!("in_scope(region_scope={:?})", region_scope);
let source_scope = self.source_scope; let source_scope = self.source_scope;
let tcx = self.tcx; let tcx = self.tcx;
if let LintLevel::Explicit(current_hir_id) = lint_level { if let LintLevel::Explicit(current_hir_id) = lint_level {
@ -589,7 +589,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let rv = unpack!(block = f(self)); let rv = unpack!(block = f(self));
unpack!(block = self.pop_scope(region_scope, block)); unpack!(block = self.pop_scope(region_scope, block));
self.source_scope = source_scope; self.source_scope = source_scope;
debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block); debug!(?block);
block.and(rv) block.and(rv)
} }

View file

@ -48,6 +48,8 @@ impl<'tcx> Cx<'tcx> {
_ => None, _ => None,
}; };
trace!(?expr.ty);
// Now apply adjustments, if any. // Now apply adjustments, if any.
for adjustment in self.typeck_results.expr_adjustments(hir_expr) { for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
trace!(?expr, ?adjustment); trace!(?expr, ?adjustment);
@ -56,6 +58,8 @@ impl<'tcx> Cx<'tcx> {
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span)); self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
} }
trace!(?expr.ty, "after adjustments");
// Next, wrap this up in the expr's scope. // Next, wrap this up in the expr's scope.
expr = Expr { expr = Expr {
temp_lifetime, temp_lifetime,

View file

@ -200,6 +200,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
} }
} }
#[instrument(skip(self), level = "debug")]
fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> { fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
let mut ty = self.typeck_results.node_type(pat.hir_id); let mut ty = self.typeck_results.node_type(pat.hir_id);
let mut span = pat.span; let mut span = pat.span;