source_info,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatchedPlace,
- scrutinee_place.clone(),
+ box(scrutinee_place.clone()),
),
});
};
// Step 5. Create everything else: the guards and the arms.
+ let match_scope = self.scopes.topmost();
+
let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| {
let arm_source_info = self.source_info(arm.span);
- let region_scope = (arm.scope, arm_source_info);
- self.in_scope(region_scope, arm.lint_level, |this| {
+ let arm_scope = (arm.scope, arm_source_info);
+ self.in_scope(arm_scope, arm.lint_level, |this| {
let body = this.hir.mirror(arm.body.clone());
let scope = this.declare_bindings(
None,
arm.guard.clone(),
&fake_borrow_temps,
scrutinee_span,
- region_scope,
+ match_scope,
);
} else {
arm_block = this.cfg.start_new_block();
arm.guard.clone(),
&fake_borrow_temps,
scrutinee_span,
- region_scope,
+ match_scope,
);
this.cfg.terminate(
binding_end,
block,
Statement {
source_info,
- kind: StatementKind::FakeRead(FakeReadCause::ForLet, place),
+ kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place)),
},
);
block,
Statement {
source_info: pattern_source_info,
- kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
+ kind: StatementKind::FakeRead(FakeReadCause::ForLet, box(place.clone())),
},
);
let ty_source_info = self.source_info(user_ty_span);
- let user_ty = box pat_ascription_ty.user_ty(
+ let user_ty = pat_ascription_ty.user_ty(
&mut self.canonical_user_type_annotations,
place.ty(&self.local_decls, self.hir.tcx()).ty,
ty_source_info.span,
Statement {
source_info: ty_source_info,
kind: StatementKind::AscribeUserType(
- place,
+ box(
+ place,
+ user_ty,
+ ),
// We always use invariant as the variance here. This is because the
// variance field from the ascription refers to the variance to use
// when applying the type to the value being matched, but this
// contrast, is intended to be used to relate `T` to the type of
// `<expr>`.
ty::Variance::Invariant,
- user_ty,
),
},
);
let var_ty = self.local_decls[local_id].ty;
let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
self.schedule_drop(span, region_scope, local_id, var_ty, DropKind::Storage);
- Place::Base(PlaceBase::Local(local_id))
+ Place::from(local_id)
}
pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
}
}
+ PatternKind::Or { ref pats } => {
+ for pat in pats {
+ self.visit_bindings(&pat, pattern_user_ty.clone(), f);
+ }
+ }
}
}
}
for Binding { source, .. }
in matched_candidates.iter().flat_map(|candidate| &candidate.bindings)
{
- let mut cursor = source;
- while let Place::Projection(box Projection { base, elem }) = cursor {
- cursor = base;
- if let ProjectionElem::Deref = elem {
- fake_borrows.insert(cursor.clone());
- break;
- }
+ if let Some(i) =
+ source.projection.iter().rposition(|elem| *elem == ProjectionElem::Deref)
+ {
+ let proj_base = &source.projection[..i];
+
+ fake_borrows.insert(Place {
+ base: source.base.clone(),
+ projection: proj_base.to_vec().into_boxed_slice(),
+ });
}
}
}
&mut self,
fake_borrows: &'b FxHashSet<Place<'tcx>>,
temp_span: Span,
- ) -> Vec<(&'b Place<'tcx>, Local)> {
+ ) -> Vec<(PlaceRef<'b, 'tcx>, Local)> {
let tcx = self.hir.tcx();
debug!("add_fake_borrows fake_borrows = {:?}", fake_borrows);
// Insert a Shallow borrow of the prefixes of any fake borrows.
for place in fake_borrows
{
- let mut prefix_cursor = place;
- while let Place::Projection(box Projection { base, elem }) = prefix_cursor {
+ let mut cursor = &*place.projection;
+ while let [proj_base @ .., elem] = cursor {
+ cursor = proj_base;
+
if let ProjectionElem::Deref = elem {
// Insert a shallow borrow after a deref. For other
// projections the borrow of prefix_cursor will
// conflict with any mutation of base.
- all_fake_borrows.push(base);
+ all_fake_borrows.push(PlaceRef {
+ base: &place.base,
+ projection: proj_base,
+ });
}
- prefix_cursor = base;
}
- all_fake_borrows.push(place);
+ all_fake_borrows.push(place.as_ref());
}
// Deduplicate and ensure a deterministic order.
debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
all_fake_borrows.into_iter().map(|matched_place| {
- let fake_borrow_deref_ty = matched_place.ty(&self.local_decls, tcx).ty;
+ let fake_borrow_deref_ty = Place::ty_from(
+ matched_place.base,
+ matched_place.projection,
+ &self.local_decls,
+ tcx,
+ )
+ .ty;
let fake_borrow_ty = tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
let fake_borrow_temp = self.local_decls.push(
LocalDecl::new_temp(fake_borrow_ty, temp_span)
/// any, and then branches to the arm. Returns the block for the case where
/// the guard fails.
///
- /// Note: we check earlier that if there is a guard, there cannot be move
- /// bindings (unless feature(bind_by_move_pattern_guards) is used). This
- /// isn't really important for the self-consistency of this fn, but the
- /// reason for it should be clear: after we've done the assignments, if
- /// there were move bindings, further tests would be a use-after-move.
- /// bind_by_move_pattern_guards avoids this by only moving the binding once
- /// the guard has evaluated to true (see below).
+ /// Note: we do not check earlier that if there is a guard,
+ /// there cannot be move bindings. We avoid a use-after-move by only
+ /// moving the binding once the guard has evaluated to true (see below).
fn bind_and_guard_matched_candidate<'pat>(
&mut self,
candidate: Candidate<'pat, 'tcx>,
guard: Option<Guard<'tcx>>,
- fake_borrows: &Vec<(&Place<'tcx>, Local)>,
+ fake_borrows: &Vec<(PlaceRef<'_, 'tcx>, Local)>,
scrutinee_span: Span,
- region_scope: (region::Scope, SourceInfo),
+ region_scope: region::Scope,
) -> BasicBlock {
debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
.map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode))
.collect(),
};
- debug!("Entering guard building context: {:?}", guard_frame);
+ debug!("entering guard building context: {:?}", guard_frame);
self.guard_context.push(guard_frame);
let re_erased = tcx.lifetimes.re_erased;
let scrutinee_source_info = self.source_info(scrutinee_span);
- for &(place, temp) in fake_borrows {
+ for (place, temp) in fake_borrows {
let borrow = Rvalue::Ref(
re_erased,
BorrowKind::Shallow,
- place.clone(),
+ Place {
+ base: place.base.clone(),
+ projection: place.projection.to_vec().into_boxed_slice(),
+ },
);
self.cfg.push_assign(
block,
scrutinee_source_info,
- &Place::from(temp),
+ &Place::from(*temp),
borrow,
);
}
source_info: guard_end,
kind: StatementKind::FakeRead(
FakeReadCause::ForMatchGuard,
- Place::from(temp),
+ box(Place::from(temp)),
),
});
}
// place they refer to can't be modified by the guard.
for binding in by_value_bindings.clone() {
let local_id = self.var_local_id(binding.var_id, RefWithinGuard);
- let place = Place::from(local_id);
+ let place = Place::from(local_id);
self.cfg.push(
post_guard_block,
Statement {
source_info: guard_end,
- kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, place),
+ kind: StatementKind::FakeRead(FakeReadCause::ForGuardBinding, box(place)),
},
);
}
ascription.user_ty,
);
- let user_ty = box ascription.user_ty.clone().user_ty(
+ let user_ty = ascription.user_ty.clone().user_ty(
&mut self.canonical_user_type_annotations,
ascription.source.ty(&self.local_decls, self.hir.tcx()).ty,
source_info.span
Statement {
source_info,
kind: StatementKind::AscribeUserType(
- ascription.source.clone(),
+ box(
+ ascription.source.clone(),
+ user_ty,
+ ),
ascription.variance,
- user_ty,
),
},
);