Skip to content

Commit

Permalink
rustc_typeck: do not mutate tables directly during upvar inference.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jun 9, 2017
1 parent 8b1b05b commit 5175bc1
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 219 deletions.
4 changes: 0 additions & 4 deletions src/librustc/infer/mod.rs
Expand Up @@ -1521,10 +1521,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
}

pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
}

pub fn closure_kind(&self,
def_id: DefId)
-> Option<ty::ClosureKind>
Expand Down
22 changes: 4 additions & 18 deletions src/librustc/middle/expr_use_visitor.rs
Expand Up @@ -270,23 +270,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>)
-> Self
{
ExprUseVisitor::with_options(delegate,
infcx,
param_env,
region_maps,
mc::MemCategorizationOptions::default())
}

pub fn with_options(delegate: &'a mut (Delegate<'tcx>+'a),
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_maps: &'a RegionMaps,
options: mc::MemCategorizationOptions)
-> Self
{
ExprUseVisitor {
mc: mc::MemCategorizationContext::with_options(infcx, region_maps, options),
mc: mc::MemCategorizationContext::new(infcx, region_maps),
delegate,
param_env,
}
Expand Down Expand Up @@ -678,8 +664,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// 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 tables = self.mc.infcx.tables.borrow();
let adjustments = 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);
Expand Down Expand Up @@ -896,7 +882,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
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.infcx.tables.borrow().upvar_capture(upvar_id);
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
fn_decl_span,
freevar.def));
Expand Down
69 changes: 10 additions & 59 deletions src/librustc/middle/mem_categorization.rs
Expand Up @@ -283,18 +283,6 @@ impl ast_node for hir::Pat {
pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
pub region_maps: &'a RegionMaps,
options: MemCategorizationOptions,
}

#[derive(Copy, Clone, Default)]
pub struct MemCategorizationOptions {
// If true, then when analyzing a closure upvar, if the closure
// has a missing kind, we treat it like a Fn closure. When false,
// we ICE if the closure has a missing kind. Should be false
// except during closure kind inference. It is used by the
// mem-categorization code to be able to have stricter assertions
// (which are always true except during upvar inference).
pub during_closure_kind_inference: bool,
}

pub type McResult<T> = Result<T, ()>;
Expand Down Expand Up @@ -400,20 +388,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
region_maps: &'a RegionMaps)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext::with_options(infcx,
region_maps,
MemCategorizationOptions::default())
}

pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
region_maps: &'a RegionMaps,
options: MemCategorizationOptions)
-> MemCategorizationContext<'a, 'gcx, 'tcx> {
MemCategorizationContext {
infcx: infcx,
region_maps: region_maps,
options: options,
}
MemCategorizationContext { infcx, region_maps }
}

fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
Expand Down Expand Up @@ -620,38 +595,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {

Def::Upvar(def_id, _, fn_node_id) => {
let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
let ty = self.node_ty(fn_node_id)?;
match ty.sty {
ty::TyClosure(closure_id, _) => {
match self.infcx.closure_kind(closure_id) {
Some(kind) => {
self.cat_upvar(id, span, var_id, fn_node_id, kind)
}
None => {
if !self.options.during_closure_kind_inference {
span_bug!(
span,
"No closure kind for {:?}",
closure_id);
}

// during closure kind inference, we
// don't know the closure kind yet, but
// it's ok because we detect that we are
// accessing an upvar and handle that
// case specially anyhow. Use Fn
// arbitrarily.
self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn)
}
}
}
_ => {
span_bug!(
span,
"Upvar of non-closure {} - {:?}",
fn_node_id,
ty);
}
let closure_id = self.tcx().hir.local_def_id(fn_node_id);
match self.infcx.closure_kind(closure_id) {
Some(kind) => {
self.cat_upvar(id, span, var_id, fn_node_id, kind)
}
None => {
span_bug!(span, "No closure kind for {:?}", closure_id);
}
}
}

Expand Down Expand Up @@ -743,7 +694,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// for that.
let upvar_id = ty::UpvarId { var_id: var_id,
closure_expr_id: fn_node_id };
let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap();
let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id);
let cmt_result = match upvar_capture {
ty::UpvarCapture::ByValue => {
cmt_result
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/context.rs
Expand Up @@ -376,8 +376,8 @@ impl<'tcx> TypeckTables<'tcx> {
}
}

pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone())
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> {
self.upvar_capture_map[&upvar_id]
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/librustc_mir/build/mod.rs
Expand Up @@ -365,13 +365,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
freevars.iter().map(|fv| {
let var_id = tcx.hir.as_local_node_id(fv.def.def_id()).unwrap();
let by_ref = hir.tables().upvar_capture(ty::UpvarId {
let capture = hir.tables().upvar_capture(ty::UpvarId {
var_id: var_id,
closure_expr_id: fn_id
}).map_or(false, |capture| match capture {
});
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
ty::UpvarCapture::ByRef(..) => true
});
};
let mut decl = UpvarDecl {
debug_name: keywords::Invalid.name(),
by_ref: by_ref
Expand Down
10 changes: 2 additions & 8 deletions src/librustc_mir/hair/cx/expr.rs
Expand Up @@ -758,13 +758,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
var_id: id_var,
closure_expr_id: closure_expr_id,
};
let upvar_capture = match cx.tables().upvar_capture(upvar_id) {
Some(c) => c,
None => {
span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id);
}
};
match upvar_capture {
match cx.tables().upvar_capture(upvar_id) {
ty::UpvarCapture::ByValue => field_kind,
ty::UpvarCapture::ByRef(borrow) => {
ExprKind::Deref {
Expand Down Expand Up @@ -878,7 +872,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
var_id: id_var,
closure_expr_id: closure_expr.id,
};
let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap();
let upvar_capture = cx.tables().upvar_capture(upvar_id);
let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id);
let var_ty = cx.tables().node_id_to_type(id_var);
let captured_var = Expr {
Expand Down
7 changes: 3 additions & 4 deletions src/librustc_typeck/check/regionck.rs
Expand Up @@ -834,8 +834,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
mc.cat_expr_unadjusted(expr)?
};

//NOTE(@jroesch): mixed RefCell borrow causes crash
let adjustments = self.tables.borrow().expr_adjustments(&expr).to_vec();
let tables = self.tables.borrow();
let adjustments = tables.expr_adjustments(&expr);
if adjustments.is_empty() {
return Ok(cmt);
}
Expand Down Expand Up @@ -1215,8 +1215,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// Detect by-ref upvar `x`:
let cause = match note {
mc::NoteUpvarRef(ref upvar_id) => {
let upvar_capture_map = &self.tables.borrow_mut().upvar_capture_map;
match upvar_capture_map.get(upvar_id) {
match self.tables.borrow().upvar_capture_map.get(upvar_id) {
Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => {
// The mutability of the upvar may have been modified
// by the above adjustment, so update our local variable.
Expand Down

0 comments on commit 5175bc1

Please sign in to comment.