}
fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
- let mir = tcx.mir_validated(def_id);
+ let input_mir = tcx.mir_validated(def_id);
let src = MirSource::from_local_def_id(tcx, def_id);
debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id()));
- let mir: &Mir<'tcx> = &mir.borrow();
if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.debugging_opts.borrowck_mir {
return;
}
- let id = src.item_id();
+ tcx.infer_ctxt().enter(|infcx| {
+ let input_mir: &Mir = &input_mir.borrow();
+ do_mir_borrowck(&infcx, input_mir, def_id, src);
+ });
+ debug!("mir_borrowck done");
+}
+
+fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+ mir: &Mir<'gcx>,
+ def_id: DefId,
+ src: MirSource)
+{
+ let tcx = infcx.tcx;
let attributes = tcx.get_attrs(def_id);
let param_env = tcx.param_env(def_id);
- tcx.infer_ctxt().enter(|_infcx| {
-
- let move_data = match MoveData::gather_moves(mir, tcx, param_env) {
- Ok(move_data) => move_data,
- Err((move_data, move_errors)) => {
- for move_error in move_errors {
- let (span, kind): (Span, IllegalMoveOriginKind) = match move_error {
- MoveError::UnionMove { .. } =>
- unimplemented!("dont know how to report union move errors yet."),
- MoveError::IllegalMove { cannot_move_out_of: o } => (o.span, o.kind),
- };
- let origin = Origin::Mir;
- let mut err = match kind {
- IllegalMoveOriginKind::Static =>
- tcx.cannot_move_out_of(span, "static item", origin),
- IllegalMoveOriginKind::BorrowedContent =>
- tcx.cannot_move_out_of(span, "borrowed_content", origin),
- IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } =>
- tcx.cannot_move_out_of_interior_of_drop(span, ty, origin),
- IllegalMoveOriginKind::InteriorOfSlice { elem_ty: ty, is_index } =>
- tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
- IllegalMoveOriginKind::InteriorOfArray { elem_ty: ty, is_index } =>
- tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
- };
- err.emit();
- }
- move_data
+
+ let id = src.item_id();
+
+ let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx, param_env) {
+ Ok(move_data) => move_data,
+ Err((move_data, move_errors)) => {
+ for move_error in move_errors {
+ let (span, kind): (Span, IllegalMoveOriginKind) = match move_error {
+ MoveError::UnionMove { .. } =>
+ unimplemented!("dont know how to report union move errors yet."),
+ MoveError::IllegalMove { cannot_move_out_of: o } => (o.span, o.kind),
+ };
+ let origin = Origin::Mir;
+ let mut err = match kind {
+ IllegalMoveOriginKind::Static =>
+ tcx.cannot_move_out_of(span, "static item", origin),
+ IllegalMoveOriginKind::BorrowedContent =>
+ tcx.cannot_move_out_of(span, "borrowed_content", origin),
+ IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } =>
+ tcx.cannot_move_out_of_interior_of_drop(span, ty, origin),
+ IllegalMoveOriginKind::InteriorOfSlice { elem_ty: ty, is_index } =>
+ tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
+ IllegalMoveOriginKind::InteriorOfArray { elem_ty: ty, is_index } =>
+ tcx.cannot_move_out_of_interior_noncopy(span, ty, is_index, origin),
+ };
+ err.emit();
}
- };
- let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
- let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
- let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
- Borrows::new(tcx, mir),
- |bd, i| bd.location(i));
- let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
- MaybeInitializedLvals::new(tcx, mir, &mdpe),
- |bd, i| &bd.move_data().move_paths[i]);
- let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
- MaybeUninitializedLvals::new(tcx, mir, &mdpe),
- |bd, i| &bd.move_data().move_paths[i]);
-
- let mut mbcx = MirBorrowckCtxt {
- tcx: tcx,
- mir: mir,
- node_id: id,
- move_data: &mdpe.move_data,
- param_env: param_env,
- fake_infer_ctxt: &_infcx,
- };
+ move_data
+ }
+ };
- let mut state = InProgress::new(flow_borrows,
- flow_inits,
- flow_uninits);
+ let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
+ let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+ let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ Borrows::new(tcx, mir),
+ |bd, i| bd.location(i));
+ let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ MaybeInitializedLvals::new(tcx, mir, &mdpe),
+ |bd, i| &bd.move_data().move_paths[i]);
+ let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+ MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+ |bd, i| &bd.move_data().move_paths[i]);
+
+ let mut mbcx = MirBorrowckCtxt {
+ tcx: tcx,
+ mir: mir,
+ node_id: id,
+ move_data: &mdpe.move_data,
+ param_env: param_env,
+ fake_infer_ctxt: &infcx,
+ };
- mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
- });
+ let mut state = InProgress::new(flow_borrows,
+ flow_inits,
+ flow_uninits);
- debug!("mir_borrowck done");
+ mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer
}
#[allow(dead_code)]
pub struct MirBorrowckCtxt<'c, 'b, 'a: 'b+'c, 'gcx: 'a+'tcx, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'gcx, 'gcx>,
- mir: &'b Mir<'gcx>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ mir: &'b Mir<'tcx>,
node_id: ast::NodeId,
- move_data: &'b MoveData<'gcx>,
+ move_data: &'b MoveData<'tcx>,
param_env: ParamEnv<'tcx>,
fake_infer_ctxt: &'c InferCtxt<'c, 'gcx, 'tcx>,
}
// (forced to be `pub` due to its use as an associated type below.)
-pub struct InProgress<'b, 'tcx: 'b> {
- borrows: FlowInProgress<Borrows<'b, 'tcx>>,
- inits: FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>,
- uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>,
+pub struct InProgress<'b, 'gcx: 'tcx, 'tcx: 'b> {
+ borrows: FlowInProgress<Borrows<'b, 'gcx, 'tcx>>,
+ inits: FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
+ uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>,
}
struct FlowInProgress<BD> where BD: BitDenotation {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
-impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
+impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'tcx>
for MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
{
- type FlowState = InProgress<'b, 'gcx>;
+ type FlowState = InProgress<'b, 'gcx, 'tcx>;
- fn mir(&self) -> &'b Mir<'gcx> { self.mir }
+ fn mir(&self) -> &'b Mir<'tcx> { self.mir }
fn reset_to_entry_of(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) {
flow_state.each_flow(|b| b.reset_to_entry_of(bb),
fn visit_statement_entry(&mut self,
location: Location,
- stmt: &Statement<'gcx>,
+ stmt: &Statement<'tcx>,
flow_state: &Self::FlowState) {
let summary = flow_state.summary();
debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {}", location, stmt, summary);
fn visit_terminator_entry(&mut self,
location: Location,
- term: &Terminator<'gcx>,
+ term: &Terminator<'tcx>,
flow_state: &Self::FlowState) {
let loc = location;
let summary = flow_state.summary();
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
fn access_lvalue(&mut self,
context: Context,
- lvalue_span: (&Lvalue<'gcx>, Span),
+ lvalue_span: (&Lvalue<'tcx>, Span),
kind: (ShallowOrDeep, ReadOrWrite),
- flow_state: &InProgress<'b, 'gcx>) {
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
// FIXME: also need to check permissions (e.g. reject mut
// borrow of immutable ref, moves through non-`Box`-ref)
let (sd, rw) = kind;
fn mutate_lvalue(&mut self,
context: Context,
- lvalue_span: (&Lvalue<'gcx>, Span),
+ lvalue_span: (&Lvalue<'tcx>, Span),
kind: ShallowOrDeep,
mode: MutateMode,
- flow_state: &InProgress<'b, 'gcx>) {
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
// Write of P[i] or *P, or WriteAndRead of any P, requires P init'd.
match mode {
MutateMode::WriteAndRead => {
fn consume_rvalue(&mut self,
context: Context,
- (rvalue, span): (&Rvalue<'gcx>, Span),
+ (rvalue, span): (&Rvalue<'tcx>, Span),
_location: Location,
- flow_state: &InProgress<'b, 'gcx>) {
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
match *rvalue {
Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => {
let access_kind = match bk {
fn consume_operand(&mut self,
context: Context,
consume_via_drop: ConsumeKind,
- (operand, span): (&Operand<'gcx>, Span),
- flow_state: &InProgress<'b, 'gcx>) {
+ (operand, span): (&Operand<'tcx>, Span),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
match *operand {
Operand::Consume(ref lvalue) => {
self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state)
fn consume_lvalue(&mut self,
context: Context,
consume_via_drop: ConsumeKind,
- lvalue_span: (&Lvalue<'gcx>, Span),
- flow_state: &InProgress<'b, 'gcx>) {
+ lvalue_span: (&Lvalue<'tcx>, Span),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
let lvalue = lvalue_span.0;
let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
let moves_by_default =
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
fn check_if_reassignment_to_immutable_state(&mut self,
context: Context,
- (lvalue, span): (&Lvalue<'gcx>, Span),
- flow_state: &InProgress<'b, 'gcx>) {
+ (lvalue, span): (&Lvalue<'tcx>, Span),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
let move_data = self.move_data;
// determine if this path has a non-mut owner (and thus needs checking).
fn check_if_path_is_moved(&mut self,
context: Context,
desired_action: &str,
- lvalue_span: (&Lvalue<'gcx>, Span),
- flow_state: &InProgress<'b, 'gcx>) {
+ lvalue_span: (&Lvalue<'tcx>, Span),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
// FIXME: analogous code in check_loans first maps `lvalue` to
// its base_path ... but is that what we want here?
let lvalue = self.base_path(lvalue_span.0);
/// An Err result includes a tag indicated why the search failed.
/// Currenly this can only occur if the lvalue is built off of a
/// static variable, as we do not track those in the MoveData.
- fn move_path_closest_to(&mut self, lvalue: &Lvalue<'gcx>)
+ fn move_path_closest_to(&mut self, lvalue: &Lvalue<'tcx>)
-> Result<MovePathIndex, NoMovePathFound>
{
let mut last_prefix = lvalue;
}
fn move_path_for_lvalue(&mut self,
- lvalue: &Lvalue<'gcx>)
+ lvalue: &Lvalue<'tcx>)
-> Option<MovePathIndex>
{
// If returns None, then there is no move path corresponding
fn check_if_assigned_path_is_moved(&mut self,
context: Context,
- (lvalue, span): (&Lvalue<'gcx>, Span),
- flow_state: &InProgress<'b, 'gcx>) {
+ (lvalue, span): (&Lvalue<'tcx>, Span),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>) {
// recur down lvalue; dispatch to check_if_path_is_moved when necessary
let mut lvalue = lvalue;
loop {
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {
fn each_borrow_involving_path<F>(&mut self,
_context: Context,
- access_lvalue: (ShallowOrDeep, &Lvalue<'gcx>),
- flow_state: &InProgress<'b, 'gcx>,
+ access_lvalue: (ShallowOrDeep, &Lvalue<'tcx>),
+ flow_state: &InProgress<'b, 'gcx, 'tcx>,
mut op: F)
- where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>, &Lvalue) -> Control
+ where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>, &Lvalue) -> Control
{
let (access, lvalue) = access_lvalue;
}
- pub(super) struct Prefixes<'c, 'tcx: 'c> {
+ pub(super) struct Prefixes<'c, 'gcx: 'tcx, 'tcx: 'c> {
mir: &'c Mir<'tcx>,
- tcx: TyCtxt<'c, 'tcx, 'tcx>,
+ tcx: TyCtxt<'c, 'gcx, 'tcx>,
kind: PrefixSet,
next: Option<&'c Lvalue<'tcx>>,
}
/// (inclusive) from longest to smallest, potentially
/// terminating the iteration early based on `kind`.
pub(super) fn prefixes<'d>(&self,
- lvalue: &'d Lvalue<'gcx>,
+ lvalue: &'d Lvalue<'tcx>,
kind: PrefixSet)
- -> Prefixes<'d, 'gcx> where 'b: 'd
+ -> Prefixes<'d, 'gcx, 'tcx> where 'b: 'd
{
Prefixes { next: Some(lvalue), kind, mir: self.mir, tcx: self.tcx }
}
}
- impl<'c, 'tcx> Iterator for Prefixes<'c, 'tcx> {
+ impl<'c, 'gcx, 'tcx> Iterator for Prefixes<'c, 'gcx, 'tcx> {
type Item = &'c Lvalue<'tcx>;
fn next(&mut self) -> Option<Self::Item> {
let mut cursor = match self.next {
// moves out of a Box. They should be removed when/if we stop
// treating Box specially (e.g. when/if DerefMove is added...)
- fn base_path<'d>(&self, lvalue: &'d Lvalue<'gcx>) -> &'d Lvalue<'gcx> {
+ fn base_path<'d>(&self, lvalue: &'d Lvalue<'tcx>) -> &'d Lvalue<'tcx> {
//! Returns the base of the leftmost (deepest) dereference of an
//! Box in `lvalue`. If there is no dereference of an Box
//! in `lvalue`, then it just returns `lvalue` itself.
fn new(self, loc: Location) -> Context { Context { kind: self, loc: loc } }
}
-impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> {
- pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'tcx>>,
- inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
- uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>)
+impl<'b, 'gcx, 'tcx> InProgress<'b, 'gcx, 'tcx> {
+ pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'gcx, 'tcx>>,
+ inits: DataflowResults<MaybeInitializedLvals<'b, 'gcx, 'tcx>>,
+ uninits: DataflowResults<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>)
-> Self {
InProgress {
borrows: FlowInProgress::new(borrows),
mut xform_borrows: XB,
mut xform_inits: XI,
mut xform_uninits: XU) where
- XB: FnMut(&mut FlowInProgress<Borrows<'b, 'tcx>>),
- XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>),
- XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>),
+ XB: FnMut(&mut FlowInProgress<Borrows<'b, 'gcx, 'tcx>>),
+ XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'gcx, 'tcx>>),
+ XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>>),
{
xform_borrows(&mut self.borrows);
xform_inits(&mut self.inits);
}
}
-impl<'b, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>> {
+impl<'b, 'gcx, 'tcx> FlowInProgress<MaybeUninitializedLvals<'b, 'gcx, 'tcx>> {
fn has_any_child_of(&self, mpi: MovePathIndex) -> Option<MovePathIndex> {
let move_data = self.base_results.operator().move_data();
/// is no need to maintain separate drop flags to track such state.
///
/// FIXME: we have to do something for moving slice patterns.
-fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
- lv: &mir::Lvalue<'tcx>) -> bool {
+fn lvalue_contents_drop_state_cannot_differ<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ mir: &Mir<'tcx>,
+ lv: &mir::Lvalue<'tcx>) -> bool {
let ty = lv.ty(mir, tcx).to_ty(tcx);
match ty.sty {
ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
}
}
-pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_lookup_result_bits<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
lookup_result: LookupResult,
}
}
-pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex,
mut each_child: F)
where F: FnMut(MovePathIndex)
{
- fn is_terminal_path<'a, 'tcx>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ fn is_terminal_path<'a, 'gcx, 'tcx>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
path: MovePathIndex) -> bool
tcx, mir, &move_data.move_paths[path].lvalue)
}
- fn on_all_children_bits<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ fn on_all_children_bits<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex,
on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child);
}
-pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn on_all_drop_children_bits<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
- ctxt: &MoveDataParamEnv<'tcx>,
+ ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
path: MovePathIndex,
mut each_child: F)
where F: FnMut(MovePathIndex)
})
}
-pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn drop_flag_effects_for_function_entry<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
- ctxt: &MoveDataParamEnv<'tcx>,
+ ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
mut callback: F)
where F: FnMut(MovePathIndex, DropFlagState)
{
}
}
-pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub(crate) fn drop_flag_effects_for_location<'a, 'gcx, 'tcx, F>(
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
- ctxt: &MoveDataParamEnv<'tcx>,
+ ctxt: &MoveDataParamEnv<'gcx, 'tcx>,
loc: Location,
mut callback: F)
where F: FnMut(MovePathIndex, DropFlagState)
// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
// uniquely identified in the MIR by the `Location` of the assigment
// statement in which it appears on the right hand side.
-pub struct Borrows<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
location_map: FxHashMap<Location, BorrowIndex>,
}
}
-impl<'a, 'tcx> Borrows<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
+ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
let mut visitor = GatherBorrows { idx_vec: IndexVec::new(),
location_map: FxHashMap(),
region_map: FxHashMap(),
}
}
-impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
type Idx = BorrowIndex;
fn name() -> &'static str { "borrows" }
fn bits_per_block(&self) -> usize {
}
}
-impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> {
#[inline]
fn join(&self, pred1: usize, pred2: usize) -> usize {
pred1 | pred2 // union effects of preds when computing borrows
}
}
-impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for Borrows<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = no Rvalue::Refs are active by default
/// Similarly, at a given `drop` statement, the set-intersection
/// between this data and `MaybeUninitializedLvals` yields the set of
/// l-values that would require a dynamic drop-flag at that statement.
-pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct MaybeInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
-impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx: 'tcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> {
+ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>)
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
}
}
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
}
/// Similarly, at a given `drop` statement, the set-intersection
/// between this data and `MaybeInitializedLvals` yields the set of
/// l-values that would require a dynamic drop-flag at that statement.
-pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct MaybeUninitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
-impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
+ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>)
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
}
}
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
}
/// Similarly, at a given `drop` statement, the set-difference between
/// this data and `MaybeInitializedLvals` yields the set of l-values
/// that would require a dynamic drop-flag at that statement.
-pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct DefinitelyInitializedLvals<'a, 'gcx: 'tcx, 'tcx: 'a> {
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>,
}
-impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
- pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
+ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>)
+ mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>)
-> Self
{
DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
}
}
-impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
}
-impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MaybeInitializedLvals<'a, 'gcx, 'tcx> {
fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-impl<'a, 'tcx> MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
state: DropFlagState)
{
}
}
-impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
type Idx = MovePathIndex;
fn name() -> &'static str { "maybe_init" }
fn bits_per_block(&self) -> usize {
}
}
-impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
type Idx = MovePathIndex;
fn name() -> &'static str { "maybe_uninit" }
fn bits_per_block(&self) -> usize {
}
}
-impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
type Idx = MovePathIndex;
fn name() -> &'static str { "definite_init" }
fn bits_per_block(&self) -> usize {
}
}
-impl<'a, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn join(&self, pred1: usize, pred2: usize) -> usize {
pred1 | pred2 // "maybe" means we union effects of both preds
}
}
-impl<'a, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn join(&self, pred1: usize, pred2: usize) -> usize {
pred1 | pred2 // "maybe" means we union effects of both preds
}
}
-impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn join(&self, pred1: usize, pred2: usize) -> usize {
pred1 & pred2 // "definitely" means we intersect effects of both preds
// propagating, or you start at all-ones and then use Intersect as
// your merge when propagating.
-impl<'a, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = uninitialized
}
}
-impl<'a, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for MaybeUninitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = initialized (start_block_effect counters this at outset)
}
}
-impl<'a, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> DataflowOperator for DefinitelyInitializedLvals<'a, 'gcx, 'tcx> {
#[inline]
fn bottom_value() -> bool {
true // bottom = initialized (start_block_effect counters this at outset)
return None;
}
-pub struct MoveDataParamEnv<'tcx> {
+pub struct MoveDataParamEnv<'gcx, 'tcx> {
pub(crate) move_data: MoveData<'tcx>,
- pub(crate) param_env: ty::ParamEnv<'tcx>,
+ pub(crate) param_env: ty::ParamEnv<'gcx>,
}
-pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- mir: &Mir<'tcx>,
- node_id: ast::NodeId,
- attributes: &[ast::Attribute],
- dead_unwinds: &IdxSet<BasicBlock>,
- bd: BD,
- p: P)
- -> DataflowResults<BD>
+pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ mir: &Mir<'tcx>,
+ node_id: ast::NodeId,
+ attributes: &[ast::Attribute],
+ dead_unwinds: &IdxSet<BasicBlock>,
+ bd: BD,
+ p: P)
+ -> DataflowResults<BD>
where BD: BitDenotation,
P: Fn(&BD, BD::Idx) -> &fmt::Debug
{
dest_lval: &mir::Lvalue);
}
-impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
+impl<'a, 'gcx, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
{
- pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ pub fn new(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
mir: &'a Mir<'tcx>,
dead_unwinds: &'a IdxSet<mir::BasicBlock>,
denotation: D) -> Self {
use super::{MoveError};
use super::IllegalMoveOriginKind::*;
-struct MoveDataBuilder<'a, 'tcx: 'a> {
+struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'gcx>,
data: MoveData<'tcx>,
errors: Vec<MoveError<'tcx>>,
}
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
fn new(mir: &'a Mir<'tcx>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>)
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'gcx>)
-> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
}
}
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
/// This creates a MovePath for a given lvalue, returning an `MovePathError`
/// if that lvalue can't be moved from.
///
}
}
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
debug!("{}", {
debug!("moves for {:?}:", self.mir.span);
}
}
-pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>)
- -> Result<MoveData<'tcx>,
- (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+pub(super) fn gather_moves<'a, 'gcx, 'tcx>(mir: &Mir<'tcx>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'gcx>)
+ -> Result<MoveData<'tcx>,
+ (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
for (bb, block) in mir.basic_blocks().iter_enumerated() {
builder.finalize()
}
-impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
debug!("gather_statement({:?}, {:?})", loc, stmt);
(Gatherer { builder: self, loc }).gather_statement(stmt);
}
}
-struct Gatherer<'b, 'a: 'b, 'tcx: 'a> {
- builder: &'b mut MoveDataBuilder<'a, 'tcx>,
+struct Gatherer<'b, 'a: 'b, 'gcx: 'tcx, 'tcx: 'a> {
+ builder: &'b mut MoveDataBuilder<'a, 'gcx, 'tcx>,
loc: Location,
}
-impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
+impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
match stmt.kind {
StatementKind::Assign(ref lval, ref rval) => {
}
}
-impl<'a, 'tcx> MoveData<'tcx> {
+impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
pub fn gather_moves(mir: &Mir<'tcx>,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParamEnv<'tcx>)
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'gcx>)
-> Result<Self, (Self, Vec<MoveError<'tcx>>)> {
builder::gather_moves(mir, tcx, param_env)
}
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
id: ast::NodeId,
- env: &MoveDataParamEnv<'tcx>)
+ env: &MoveDataParamEnv<'tcx, 'tcx>)
-> IdxSetBuf<BasicBlock>
{
debug!("find_dead_unwinds({:?})", mir.span);
fn apply_location<'a,'tcx>(&mut self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
- env: &MoveDataParamEnv<'tcx>,
+ env: &MoveDataParamEnv<'tcx, 'tcx>,
loc: Location)
{
drop_flag_effects_for_location(tcx, mir, env, loc, |path, df| {
struct ElaborateDropsCtxt<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &'a Mir<'tcx>,
- env: &'a MoveDataParamEnv<'tcx>,
- flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx>>,
- flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx>>,
+ env: &'a MoveDataParamEnv<'tcx, 'tcx>,
+ flow_inits: DataflowResults<MaybeInitializedLvals<'a, 'tcx, 'tcx>>,
+ flow_uninits: DataflowResults<MaybeUninitializedLvals<'a, 'tcx, 'tcx>>,
drop_flags: FxHashMap<MovePathIndex, Local>,
patch: MirPatch<'tcx>,
}