Pass one argument instead of fetching two fields of it at every call site

This commit is contained in:
Oli Scherer 2022-06-23 16:08:02 +00:00
parent a034446fae
commit eeb10335ce
7 changed files with 60 additions and 100 deletions

View file

@ -71,7 +71,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>>,
} }
@ -202,10 +202,9 @@ 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>( fn to_upvars_resolved_place_builder<'tcx>(
from_builder: PlaceBuilder<'tcx>, from_builder: PlaceBuilder<'tcx>,
tcx: TyCtxt<'tcx>, cx: &Builder<'_, 'tcx>,
typeck_results: &'a ty::TypeckResults<'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),
@ -220,13 +219,13 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
let Some((capture_index, capture)) = let Some((capture_index, capture)) =
find_capture_matching_projections( find_capture_matching_projections(
typeck_results, cx.typeck_results,
var_hir_id, var_hir_id,
closure_def_id, closure_def_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",
@ -243,8 +242,8 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
}; };
// We won't be building MIR if the closure wasn't local // We won't be building MIR if the closure wasn't local
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); let closure_hir_id = cx.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
let closure_ty = typeck_results.node_type(closure_hir_id); let closure_ty = cx.typeck_results.node_type(closure_hir_id);
let substs = match closure_ty.kind() { let substs = match closure_ty.kind() {
ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
@ -316,24 +315,16 @@ fn strip_prefix<'tcx>(
} }
impl<'tcx> PlaceBuilder<'tcx> { impl<'tcx> PlaceBuilder<'tcx> {
pub(crate) fn into_place<'a>( pub(crate) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
self,
tcx: TyCtxt<'tcx>,
typeck_results: &'a ty::TypeckResults<'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, typeck_results).into_place(tcx, typeck_results) 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>,
typeck_results: &'a ty::TypeckResults<'tcx>,
) -> PlaceBuilder<'tcx> {
to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap()
} }
/// Attempts to resolve the `PlaceBuilder`. /// Attempts to resolve the `PlaceBuilder`.
@ -347,12 +338,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(crate) fn try_upvars_resolved<'a>( pub(crate) fn try_upvars_resolved(
self, self,
tcx: TyCtxt<'tcx>, cx: &Builder<'_, 'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> { ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
to_upvars_resolved_place_builder(self, tcx, typeck_results) to_upvars_resolved_place_builder(self, cx)
} }
pub(crate) fn base(&self) -> PlaceBase { pub(crate) fn base(&self) -> PlaceBase {
@ -412,7 +402,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.typeck_results)) 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
@ -436,7 +426,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.typeck_results)) 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
@ -531,7 +521,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.typeck_results); let place = place_builder.clone().into_place(this);
this.cfg.push( this.cfg.push(
block, block,
Statement { Statement {
@ -683,7 +673,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.typeck_results); 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,
@ -711,12 +701,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.typeck_results)),
);
// lt = idx < len // lt = idx < len
self.cfg.push_assign( self.cfg.push_assign(
block, block,

View file

@ -321,11 +321,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.typeck_results) let mir_place = place_builder_resolved.into_place(this);
{
let mir_place =
place_builder_resolved.into_place(this.tcx, this.typeck_results);
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)),
@ -616,8 +613,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.typeck_results);
match enclosing_upvars_resolved.as_ref() { match enclosing_upvars_resolved.as_ref() {
PlaceRef { PlaceRef {
@ -654,7 +650,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.typeck_results); let arg_place = arg_place_builder.into_place(this);
this.cfg.push_assign( this.cfg.push_assign(
block, block,

View file

@ -365,9 +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 place_builder.field(n, *ty).into_place(this),
.field(n, *ty)
.into_place(this.tcx, this.typeck_results),
) )
} }
}) })

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.typeck_results) let scrutinee_place = scrutinee_builder.into_place(self);
{
let scrutinee_place = scrutinee_builder.into_place(self.tcx, self.typeck_results);
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);
} }
@ -348,12 +346,10 @@ 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) = scrutinee_place_builder if let Ok(scrutinee_builder) =
.clone() scrutinee_place_builder.clone().try_upvars_resolved(this)
.try_upvars_resolved(this.tcx, this.typeck_results)
{ {
scrutinee_place = scrutinee_place = scrutinee_builder.into_place(this);
scrutinee_builder.into_place(this.tcx, this.typeck_results);
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(
@ -602,12 +598,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
@ -622,10 +612,15 @@ 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.typeck_results) let place = match_pair_resolved.into_place(self);
{
let place = match_pair_resolved.into_place(self.tcx, self.typeck_results); 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);
} }
} }
@ -1605,9 +1600,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.typeck_results) match_place.clone().try_upvars_resolved(self)
{ {
let resolved_place = match_place_resolved.into_place(self.tcx, self.typeck_results); let resolved_place = match_place_resolved.into_place(self);
fb.insert(resolved_place); fb.insert(resolved_place);
} }
@ -1799,10 +1794,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) = if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
expr_place_builder.try_upvars_resolved(self.tcx, self.typeck_results) expr_place = expr_builder.into_place(self);
{
expr_place = expr_builder.into_place(self.tcx, self.typeck_results);
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();

View file

@ -156,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.typeck_results)
{
candidate.ascriptions.push(Ascription { candidate.ascriptions.push(Ascription {
annotation: annotation.clone(), annotation: annotation.clone(),
source: place_resolved.into_place(self.tcx, self.typeck_results), source: place_resolved.into_place(self),
variance, variance,
}); });
} }
@ -185,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.typeck_results)
{
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.typeck_results), source: place_resolved.into_place(self),
var_id: var, var_id: var,
binding_mode: mode, binding_mode: mode,
}); });

View file

@ -155,10 +155,8 @@ impl<'a, 'tcx> Builder<'a, '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<'tcx>;
if let Ok(test_place_builder) = if let Ok(test_place_builder) = place_builder.try_upvars_resolved(self) {
place_builder.try_upvars_resolved(self.tcx, self.typeck_results) place = test_place_builder.into_place(self);
{
place = test_place_builder.into_place(self.tcx, self.typeck_results);
} else { } else {
return; return;
} }

View file

@ -31,21 +31,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
suffix: &'pat [Pat<'tcx>], suffix: &'pat [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.typeck_results) 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 ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
.into_place(tcx, self.typeck_results) _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
.ty(&self.local_decls, tcx) }
.ty } else {
.kind() ((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)
};
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
let elem = let elem =
@ -100,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> {