def::DefPrimTy(p) => def::DefPrimTy(p),
def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
def::DefUse(did) => def::DefUse(did.tr(dcx)),
- def::DefUpvar(nid1, nid2) => {
- def::DefUpvar(dcx.tr_id(nid1), dcx.tr_id(nid2))
+ def::DefUpvar(nid1, index, nid2) => {
+ def::DefUpvar(dcx.tr_id(nid1), index, dcx.tr_id(nid2))
}
def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
DefTyParam(ParamSpace, u32, DefId, ast::Name),
DefUse(DefId),
DefUpvar(ast::NodeId, // id of closed over local
+ usize, // index in the freevars list of the closure
ast::NodeId), // expr node that creates the closure
/// Note that if it's a tuple struct's definition, the node id of the DefId
id
}
DefLocal(id) |
- DefUpvar(id, _) |
+ DefUpvar(id, _, _) |
DefRegion(id) |
DefLabel(id) |
DefSelfTy(_, Some((_, id))) => {
}))
}
- def::DefUpvar(var_id, fn_node_id) => {
+ def::DefUpvar(var_id, _, fn_node_id) => {
let ty = try!(self.node_ty(fn_node_id));
match ty.sty {
ty::TyClosure(closure_id, _) => {
use rustc::middle::privacy::*;
use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
-use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
+use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use rustc::util::lev_distance::lev_distance;
use syntax::ast;
use rustc_front::util::walk_pat;
use std::collections::{HashMap, HashSet};
-use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::cell::{Cell, RefCell};
use std::fmt;
use std::mem::replace;
def_map: DefMap,
freevars: RefCell<FreevarMap>,
- freevars_seen: RefCell<NodeMap<NodeSet>>,
+ freevars_seen: RefCell<NodeMap<NodeMap<usize>>>,
export_map: ExportMap,
trait_map: TraitMap,
external_exports: ExternalExports,
}
ClosureRibKind(function_id) => {
let prev_def = def;
- def = DefUpvar(node_id, function_id);
let mut seen = self.freevars_seen.borrow_mut();
- let seen = match seen.entry(function_id) {
- Occupied(v) => v.into_mut(),
- Vacant(v) => v.insert(NodeSet()),
- };
- if seen.contains(&node_id) {
+ let seen = seen.entry(function_id).or_insert_with(|| NodeMap());
+ if let Some(&index) = seen.get(&node_id) {
+ def = DefUpvar(node_id, index, function_id);
continue;
}
- match self.freevars.borrow_mut().entry(function_id) {
- Occupied(v) => v.into_mut(),
- Vacant(v) => v.insert(vec![]),
- }.push(Freevar { def: prev_def, span: span });
- seen.insert(node_id);
+ let mut freevars = self.freevars.borrow_mut();
+ let vec = freevars.entry(function_id)
+ .or_insert_with(|| vec![]);
+ let depth = vec.len();
+ vec.push(Freevar { def: prev_def, span: span });
+
+ def = DefUpvar(node_id, depth, function_id);
+ seen.insert(node_id, depth);
}
ItemRibKind | MethodRibKind => {
// This was an attempt to access an upvar inside a
fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
let (vid, field) = match discr.node {
hir::ExprPath(..) => match bcx.def(discr.id) {
- def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None),
+ def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
_ => return false
},
hir::ExprField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
- Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
+ Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _, _)) => vid,
_ => return false
};
(vid, Some(mc::NamedField(field.node.name)))
},
hir::ExprTupField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
- Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
+ Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _, _)) => vid,
_ => return false
};
(vid, Some(mc::PositionalField(field.node)))
let _icx = push_ctxt("trans_local_var");
match def {
- def::DefUpvar(nid, _) => {
+ def::DefUpvar(nid, _, _) => {
// Can't move upvars, so this is never a ZeroMemLastUse.
let local_ty = node_id_type(bcx, nid);
let lval = Lvalue::new_with_hint("expr::trans_local_var (upvar)",
defn: def::Def)
-> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
match defn {
- def::DefLocal(nid) | def::DefUpvar(nid, _) => {
+ def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
let typ = fcx.local_ty(sp, nid);
(ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
ty::GenericPredicates::empty())