///////////////////////////////////////////////////////////////////////////
// The ExprUseVisitor type
//
-// This is the code that actually walks the tree. Like
-// mem_categorization, it requires a TYPER, which is a type that
-// supplies types from the tree. After type checking is complete, you
-// can just use the tcx as the typer.
+// This is the code that actually walks the tree.
pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
delegate: &'a mut Delegate<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
}
-// If the TYPER results in an error, it's because the type check
+// If the MC results in an error, it's because the type check
// failed (or will fail, when the error is uncovered and reported
// during writeback). In this case, we just ignore this part of the
// code.
impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
+ infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
region_maps: &'a RegionMaps,
- infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
- -> Self
- {
- ExprUseVisitor::with_options(delegate,
- infcx,
- region_maps,
- mc::MemCategorizationOptions::default())
- }
-
- pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
- infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
- region_maps: &'a RegionMaps,
- options: mc::MemCategorizationOptions)
+ tables: &'a ty::TypeckTables<'tcx>)
-> Self
{
ExprUseVisitor {
- mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options),
- delegate: delegate
+ mc: mc::MemCategorizationContext::new(infcx, region_maps, tables),
+ delegate,
+ param_env,
}
}
debug!("consume_body(body={:?})", body);
for arg in &body.arguments {
- let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
+ let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id));
let fn_body_scope_r = self.tcx().node_scope_region(body.value.id);
let arg_cmt = self.mc.cat_rvalue(
arg.id,
arg.pat.span,
fn_body_scope_r, // Args live only as long as the fn body.
- fn_body_scope_r,
arg_ty);
self.walk_irrefutable_pat(arg_cmt, &arg.pat);
debug!("delegate_consume(consume_id={}, cmt={:?})",
consume_id, cmt);
- let mode = copy_or_move(self.mc.infcx, &cmt, DirectRefMove);
+ let mode = copy_or_move(self.mc.infcx, self.param_env, &cmt, DirectRefMove);
self.delegate.consume(consume_id, consume_span, cmt, mode);
}
hir::ExprAddrOf(m, ref base) => { // &base
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
- let expr_ty = return_if_err!(self.mc.infcx.node_ty(expr.id));
+ let expr_ty = return_if_err!(self.mc.expr_ty(expr));
if let ty::TyRef(r, _) = expr_ty.sty {
let bk = ty::BorrowKind::from_mutbl(m);
self.borrow_expr(&base, r, bk, AddrOf);
}
hir::ExprAssignOp(_, ref lhs, ref rhs) => {
- if self.mc.infcx.tables.borrow().is_method_call(expr) {
+ if self.mc.tables.is_method_call(expr) {
self.consume_expr(lhs);
} else {
self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead);
}
fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
- let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee));
+ let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee));
debug!("walk_callee: callee={:?} callee_ty={:?}",
callee, callee_ty);
match callee_ty.sty {
}
ty::TyError => { }
_ => {
- let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id();
+ let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id();
match OverloadedCallType::from_method_id(self.tcx(), def_id) {
FnMutOverloadedCall => {
let call_scope_r = self.tcx().node_scope_region(call.id);
// consumed or borrowed as part of the automatic adjustment
// process.
fn walk_adjustment(&mut self, expr: &hir::Expr) {
- //NOTE(@jroesch): mixed RefCell borrow causes crash
- let adjustments = self.mc.infcx.tables.borrow().expr_adjustments(expr).to_vec();
+ let adjustments = self.mc.tables.expr_adjustments(expr);
let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr));
for adjustment in adjustments {
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
mode: &mut TrackMatchMode) {
debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
pat);
- return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
+ return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| {
match pat.node {
PatKind::Binding(hir::BindByRef(..), ..) =>
mode.lub(BorrowingMatch),
PatKind::Binding(hir::BindByValue(..), ..) => {
- match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) {
+ match copy_or_move(self.mc.infcx, self.param_env, &cmt_pat, PatBindingMove) {
Copy => mode.lub(CopyingMatch),
Move(..) => mode.lub(MovingMatch),
}
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
- let tcx = &self.tcx();
- let mc = &self.mc;
+ let tcx = self.tcx();
let infcx = self.mc.infcx;
- let delegate = &mut self.delegate;
- return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
+ let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
+ return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
// pat_ty: the type of the binding being produced.
- let pat_ty = return_if_err!(infcx.node_ty(pat.id));
+ let pat_ty = return_if_err!(mc.node_ty(pat.id));
// Each match binding is effectively an assignment to the
// binding being produced.
}
}
hir::BindByValue(..) => {
- let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
+ let mode = copy_or_move(infcx, param_env, &cmt_pat, PatBindingMove);
debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode);
}
// the interior nodes (enum variants and structs), as opposed
// to the above loop's visit of than the bindings that form
// the leaves of the pattern tree structure.
- return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
+ return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| {
let qpath = match pat.node {
PatKind::Path(ref qpath) |
PatKind::TupleStruct(ref qpath, ..) |
PatKind::Struct(ref qpath, ..) => qpath,
_ => return
};
- let def = infcx.tables.borrow().qpath_def(qpath, pat.id);
+ let def = mc.tables.qpath_def(qpath, pat.id);
match def {
Def::Variant(variant_did) |
Def::VariantCtor(variant_did, ..) => {
let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap();
let upvar_id = ty::UpvarId { var_id: id_var,
closure_expr_id: closure_expr.id };
- let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap();
+ let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
fn_decl_span,
freevar.def));
match upvar_capture {
ty::UpvarCapture::ByValue => {
- let mode = copy_or_move(self.mc.infcx, &cmt_var, CaptureMove);
+ let mode = copy_or_move(self.mc.infcx,
+ self.param_env,
+ &cmt_var,
+ CaptureMove);
self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
}
ty::UpvarCapture::ByRef(upvar_borrow) => {
// Create the cmt for the variable being borrowed, from the
// caller's perspective
let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap();
- let var_ty = self.mc.infcx.node_ty(var_id)?;
+ let var_ty = self.mc.node_ty(var_id)?;
self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
}
}
fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
cmt: &mc::cmt<'tcx>,
move_reason: MoveReason)
-> ConsumeMode
{
- if infcx.type_moves_by_default(cmt.ty, cmt.span) {
+ if infcx.type_moves_by_default(param_env, cmt.ty, cmt.span) {
Move(move_reason)
} else {
Copy