diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index bb454e07fc158..4ff9133c8a534 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -17,7 +17,7 @@ use lint; use llvm::{ContextRef, ModuleRef}; use metadata::common::LinkMeta; use metadata::creader; -use middle::{trans, freevars, stability, kind, ty, typeck, reachable}; +use middle::{trans, stability, kind, ty, typeck, reachable}; use middle::dependency_format; use middle; use plugin::load::Plugins; @@ -378,11 +378,13 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, middle::lang_items::collect_language_items(krate, &sess)); let middle::resolve::CrateMap { - def_map: def_map, - exp_map2: exp_map2, - trait_map: trait_map, - external_exports: external_exports, - last_private_map: last_private_map + def_map, + freevars, + capture_mode_map, + exp_map2, + trait_map, + external_exports, + last_private_map } = time(time_passes, "resolution", (), |_| middle::resolve::resolve_crate(&sess, &lang_items, krate)); @@ -401,10 +403,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, plugin::build::find_plugin_registrar( sess.diagnostic(), krate))); - let (freevars, capture_modes) = - time(time_passes, "freevar finding", (), |_| - freevars::annotate_freevars(&def_map, krate)); - let region_map = time(time_passes, "region resolution", (), |_| middle::region::resolve_crate(&sess, krate)); @@ -423,7 +421,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session, named_region_map, ast_map, freevars, - capture_modes, + capture_mode_map, region_map, lang_items, stability_index); diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c5b9f33be2858..2994954c3d727 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -29,7 +29,7 @@ This API is completely unstable and subject to change. html_root_url = "http://doc.rust-lang.org/master/")] #![allow(deprecated)] -#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)] +#![feature(macro_rules, globs, struct_variant, quote)] #![feature(default_type_params, phase, unsafe_destructor)] #![allow(unknown_features)] // NOTE: Remove after next snapshot @@ -93,7 +93,6 @@ pub mod middle { pub mod effect; pub mod entry; pub mod expr_use_visitor; - pub mod freevars; pub mod graph; pub mod intrinsicck; pub mod kind; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 473c3935769be..3456e449a49f4 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -954,8 +954,7 @@ impl LintPass for NonSnakeCase { match &p.node { &ast::PatIdent(_, ref path1, _) => { match cx.tcx.def_map.borrow().find(&p.id) { - Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) | - Some(&def::DefArg(_, _)) => { + Some(&def::DefLocal(_)) => { self.check_snake_case(cx, "variable", path1.node, p.span); } _ => {} diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 399313ddd8ea9..feef7ffe847de 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -18,13 +18,12 @@ use driver::session::Session; use metadata::decoder; use middle::def; use metadata::encoder as e; -use middle::freevars::{CaptureMode, freevar_entry}; -use middle::freevars; use middle::region; use metadata::tydecode; use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter}; use metadata::tydecode::{RegionParameter}; use metadata::tyencode; +use middle::mem_categorization::Typer; use middle::subst; use middle::subst::VecPerParamSpace; use middle::typeck::{MethodCall, MethodCallee, MethodOrigin}; @@ -42,7 +41,6 @@ use syntax; use libc; use std::io::Seek; use std::mem; -use std::gc::GC; use std::rc::Rc; use rbml::io::SeekableMemWriter; @@ -462,8 +460,7 @@ impl tr for def::Def { def::DefMod(did) => { def::DefMod(did.tr(dcx)) } def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) } def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) } - def::DefArg(nid, b) => { def::DefArg(dcx.tr_id(nid), b) } - def::DefLocal(nid, b) => { def::DefLocal(dcx.tr_id(nid), b) } + def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) } def::DefVariant(e_did, v_did, is_s) => { def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s) }, @@ -472,11 +469,9 @@ impl tr for def::Def { def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)), def::DefPrimTy(p) => def::DefPrimTy(p), def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v), - def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm), def::DefUse(did) => def::DefUse(did.tr(dcx)), - def::DefUpvar(nid1, def, nid2, nid3) => { + def::DefUpvar(nid1, nid2, nid3) => { def::DefUpvar(dcx.tr_id(nid1), - box(GC) (*def).tr(dcx), dcx.tr_id(nid2), dcx.tr_id(nid3)) } @@ -541,36 +536,36 @@ impl tr for ty::TraitStore { // ______________________________________________________________________ // Encoding and decoding of freevar information -fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &freevar_entry) { +fn encode_freevar_entry(rbml_w: &mut Encoder, fv: &ty::Freevar) { (*fv).encode(rbml_w).unwrap(); } -fn encode_capture_mode(rbml_w: &mut Encoder, cm: CaptureMode) { +fn encode_capture_mode(rbml_w: &mut Encoder, cm: ast::CaptureClause) { cm.encode(rbml_w).unwrap(); } trait rbml_decoder_helper { fn read_freevar_entry(&mut self, dcx: &DecodeContext) - -> freevar_entry; - fn read_capture_mode(&mut self) -> CaptureMode; + -> ty::Freevar; + fn read_capture_mode(&mut self) -> ast::CaptureClause; } impl<'a> rbml_decoder_helper for reader::Decoder<'a> { fn read_freevar_entry(&mut self, dcx: &DecodeContext) - -> freevar_entry { - let fv: freevar_entry = Decodable::decode(self).unwrap(); + -> ty::Freevar { + let fv: ty::Freevar = Decodable::decode(self).unwrap(); fv.tr(dcx) } - fn read_capture_mode(&mut self) -> CaptureMode { - let cm: CaptureMode = Decodable::decode(self).unwrap(); + fn read_capture_mode(&mut self) -> ast::CaptureClause { + let cm: ast::CaptureClause = Decodable::decode(self).unwrap(); cm } } -impl tr for freevar_entry { - fn tr(&self, dcx: &DecodeContext) -> freevar_entry { - freevar_entry { +impl tr for ty::Freevar { + fn tr(&self, dcx: &DecodeContext) -> ty::Freevar { + ty::Freevar { def: self.def.tr(dcx), span: self.span.tr(dcx), } @@ -1292,8 +1287,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, }); for freevar in fv.iter() { - match freevars::get_capture_mode(tcx, id) { - freevars::CaptureByRef => { + match tcx.capture_mode(id) { + ast::CaptureByRef => { rbml_w.tag(c::tag_table_upvar_borrow_map, |rbml_w| { rbml_w.id(id); rbml_w.tag(c::tag_table_val, |rbml_w| { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index df637e7a052dd..95009bc2dbfc0 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -514,9 +514,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { true } - pub fn is_local_variable_or_arg(&self, cmt: mc::cmt) -> bool { + fn is_local_variable_or_arg(&self, cmt: mc::cmt) -> bool { match cmt.cat { - mc::cat_local(_) | mc::cat_arg(_) => true, + mc::cat_local(_) => true, _ => false } } @@ -775,7 +775,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { debug!("mark_variable_as_used_mut(cmt={})", cmt.repr(this.tcx())); match cmt.cat.clone() { mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) | - mc::cat_local(id) | mc::cat_arg(id) => { + mc::cat_local(id) => { this.tcx().used_mut_nodes.borrow_mut().insert(id); return; } diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index f58cc95038382..25439fce68c9f 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -147,8 +147,7 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt, } mc::cat_rvalue(..) | - mc::cat_local(..) | - mc::cat_arg(..) => { + mc::cat_local(..) => { None } diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index e13717e5abd31..c07123325253b 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -69,7 +69,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { mc::cat_rvalue(..) | mc::cat_copied_upvar(..) | // L-Local mc::cat_local(..) | // L-Local - mc::cat_arg(..) | // L-Local mc::cat_upvar(..) | mc::cat_deref(_, _, mc::BorrowedPtr(..)) | // L-Deref-Borrowed mc::cat_deref(_, _, mc::Implicit(..)) | @@ -174,8 +173,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { mc::cat_static_item => { ty::ReStatic } - mc::cat_local(local_id) | - mc::cat_arg(local_id) => { + mc::cat_local(local_id) => { ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id)) } mc::cat_deref(_, _, mc::UnsafePtr(..)) => { diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 90e17e4d79cbb..e0018919b9823 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -66,8 +66,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { Safe } - mc::cat_local(local_id) | - mc::cat_arg(local_id) => { + mc::cat_local(local_id) => { // R-Variable, locally declared let lp = Rc::new(LpVar(local_id)); SafeIf(lp.clone(), vec![lp]) diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 0d584a7664f67..38b5c5f330270 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -321,8 +321,7 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option> { None } - mc::cat_local(id) | - mc::cat_arg(id) => { + mc::cat_local(id) => { Some(Rc::new(LpVar(id))) } diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs index ae45d827def50..1863a19b56d02 100644 --- a/src/librustc/middle/def.rs +++ b/src/librustc/middle/def.rs @@ -12,8 +12,6 @@ use middle::subst::ParamSpace; use syntax::ast; use syntax::ast_util::local_def; -use std::gc::Gc; - #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Def { DefFn(ast::DefId, ast::FnStyle), @@ -22,20 +20,18 @@ pub enum Def { DefMod(ast::DefId), DefForeignMod(ast::DefId), DefStatic(ast::DefId, bool /* is_mutbl */), - DefArg(ast::NodeId, ast::BindingMode), - DefLocal(ast::NodeId, ast::BindingMode), + DefLocal(ast::NodeId), DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */), DefTy(ast::DefId, bool /* is_enum */), DefAssociatedTy(ast::DefId), DefTrait(ast::DefId), DefPrimTy(ast::PrimTy), DefTyParam(ParamSpace, ast::DefId, uint), - DefBinding(ast::NodeId, ast::BindingMode), DefUse(ast::DefId), - DefUpvar(ast::NodeId, // id of closed over var - Gc, // closed over def + DefUpvar(ast::NodeId, // id of closed over local ast::NodeId, // expr node that creates the closure - ast::NodeId), // id for the block/body of the closure expr + ast::NodeId), // block node for the closest enclosing proc + // or unboxed closure, DUMMY_NODE_ID otherwise /// Note that if it's a tuple struct's definition, the node id of the ast::DefId /// may either refer to the item definition's id or the StructDef.ctor_id. @@ -68,11 +64,9 @@ impl Def { DefMethod(id, _) => { id } - DefArg(id, _) | - DefLocal(id, _) | + DefLocal(id) | DefSelfTy(id) | - DefUpvar(id, _, _, _) | - DefBinding(id, _) | + DefUpvar(id, _, _) | DefRegion(id) | DefTyParamBinder(id) | DefLabel(id) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c8c5284022d99..0a61911dfc908 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -16,7 +16,7 @@ use middle::mem_categorization as mc; use middle::def; -use middle::freevars; +use middle::mem_categorization::Typer; use middle::pat_util; use middle::ty; use middle::typeck::{MethodCall, MethodObject, MethodOrigin, MethodParam}; @@ -911,12 +911,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> { debug!("walk_captures({})", closure_expr.repr(self.tcx())); let tcx = self.typer.tcx(); - freevars::with_freevars(tcx, closure_expr.id, |freevars| { - match freevars::get_capture_mode(self.tcx(), closure_expr.id) { - freevars::CaptureByRef => { + ty::with_freevars(tcx, closure_expr.id, |freevars| { + match self.tcx().capture_mode(closure_expr.id) { + ast::CaptureByRef => { self.walk_by_ref_captures(closure_expr, freevars); } - freevars::CaptureByValue => { + ast::CaptureByValue => { self.walk_by_value_captures(closure_expr, freevars); } } @@ -925,7 +925,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> { fn walk_by_ref_captures(&mut self, closure_expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { + freevars: &[ty::Freevar]) { for freevar in freevars.iter() { let id_var = freevar.def.def_id().node; let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, @@ -950,7 +950,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> { fn walk_by_value_captures(&mut self, closure_expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { + freevars: &[ty::Freevar]) { for freevar in freevars.iter() { let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, closure_expr.span, diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs deleted file mode 100644 index 5b7c72208ea7d..0000000000000 --- a/src/librustc/middle/freevars.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// A pass that annotates for each loops and functions with the free -// variables that they contain. - -#![allow(non_camel_case_types)] - -use middle::def; -use middle::mem_categorization::Typer; -use middle::resolve; -use middle::ty; -use util::nodemap::{NodeMap, NodeSet}; - -use syntax::ast; -use syntax::codemap::Span; -use syntax::visit::Visitor; -use syntax::visit; - -#[deriving(Clone, Decodable, Encodable, Show)] -pub enum CaptureMode { - /// Copy/move the value from this llvm ValueRef into the environment. - CaptureByValue, - - /// Access by reference (used for stack closures). - CaptureByRef -} - -// A vector of defs representing the free variables referred to in a function. -// (The def_upvar will already have been stripped). -#[deriving(Encodable, Decodable)] -pub struct freevar_entry { - pub def: def::Def, //< The variable being accessed free. - pub span: Span //< First span where it is accessed (there can be multiple) -} - -pub type freevar_map = NodeMap>; - -pub type CaptureModeMap = NodeMap; - -struct CollectFreevarsVisitor<'a> { - seen: NodeSet, - refs: Vec, - def_map: &'a resolve::DefMap, - capture_mode_map: &'a mut CaptureModeMap, - depth: uint -} - -impl<'a, 'v> Visitor<'v> for CollectFreevarsVisitor<'a> { - fn visit_item(&mut self, _: &ast::Item) { - // ignore_item - } - - fn visit_expr(&mut self, expr: &ast::Expr) { - match expr.node { - ast::ExprProc(..) => { - self.capture_mode_map.insert(expr.id, CaptureByValue); - self.depth += 1; - visit::walk_expr(self, expr); - self.depth -= 1; - } - ast::ExprFnBlock(_, _, _) => { - // NOTE(stage0): After snapshot, change to: - // - //let capture_mode = match capture_clause { - // ast::CaptureByValue => CaptureByValue, - // ast::CaptureByRef => CaptureByRef, - //}; - let capture_mode = CaptureByRef; - self.capture_mode_map.insert(expr.id, capture_mode); - self.depth += 1; - visit::walk_expr(self, expr); - self.depth -= 1; - } - ast::ExprUnboxedFn(capture_clause, _, _, _) => { - let capture_mode = match capture_clause { - ast::CaptureByValue => CaptureByValue, - ast::CaptureByRef => CaptureByRef, - }; - self.capture_mode_map.insert(expr.id, capture_mode); - self.depth += 1; - visit::walk_expr(self, expr); - self.depth -= 1; - } - ast::ExprPath(..) => { - let mut def = *self.def_map.borrow().find(&expr.id) - .expect("path not found"); - let mut i = 0; - while i < self.depth { - match def { - def::DefUpvar(_, inner, _, _) => { def = *inner; } - _ => break - } - i += 1; - } - if i == self.depth { // Made it to end of loop - let dnum = def.def_id().node; - if !self.seen.contains(&dnum) { - self.refs.push(freevar_entry { - def: def, - span: expr.span, - }); - self.seen.insert(dnum); - } - } - } - _ => visit::walk_expr(self, expr) - } - } -} - -// Searches through part of the AST for all references to locals or -// upvars in this frame and returns the list of definition IDs thus found. -// Since we want to be able to collect upvars in some arbitrary piece -// of the AST, we take a walker function that we invoke with a visitor -// in order to start the search. -fn collect_freevars(def_map: &resolve::DefMap, - blk: &ast::Block, - capture_mode_map: &mut CaptureModeMap) - -> Vec { - let mut v = CollectFreevarsVisitor { - seen: NodeSet::new(), - refs: Vec::new(), - def_map: def_map, - capture_mode_map: &mut *capture_mode_map, - depth: 1 - }; - - v.visit_block(blk); - - v.refs -} - -struct AnnotateFreevarsVisitor<'a> { - def_map: &'a resolve::DefMap, - freevars: freevar_map, - capture_mode_map: CaptureModeMap, -} - -impl<'a, 'v> Visitor<'v> for AnnotateFreevarsVisitor<'a> { - fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl, - blk: &'v ast::Block, s: Span, nid: ast::NodeId) { - let vars = collect_freevars(self.def_map, - blk, - &mut self.capture_mode_map); - self.freevars.insert(nid, vars); - visit::walk_fn(self, fk, fd, blk, s); - } -} - -// Build a map from every function and for-each body to a set of the -// freevars contained in it. The implementation is not particularly -// efficient as it fully recomputes the free variables at every -// node of interest rather than building up the free variables in -// one pass. This could be improved upon if it turns out to matter. -pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate) - -> (freevar_map, CaptureModeMap) { - let mut visitor = AnnotateFreevarsVisitor { - def_map: def_map, - freevars: NodeMap::new(), - capture_mode_map: NodeMap::new(), - }; - visit::walk_crate(&mut visitor, krate); - - let AnnotateFreevarsVisitor { - freevars, - capture_mode_map, - .. - } = visitor; - (freevars, capture_mode_map) -} - -pub fn with_freevars(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T { - match tcx.freevars.borrow().find(&fid) { - None => fail!("with_freevars: {} has no freevars", fid), - Some(d) => f(d.as_slice()) - } -} - -pub fn get_capture_mode<'tcx, T:Typer<'tcx>>(tcx: &T, closure_expr_id: ast::NodeId) - -> CaptureMode { - tcx.capture_mode(closure_expr_id) -} diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index aeb0c155a3f48..ad275e6e84cde 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::freevars::freevar_entry; -use middle::freevars; use middle::mem_categorization::Typer; use middle::subst; use middle::ty; @@ -146,10 +144,10 @@ fn check_item(cx: &mut Context, item: &Item) { fn with_appropriate_checker(cx: &Context, id: NodeId, fn_span: Span, - b: |checker: |&Context, &freevar_entry||) { + b: |checker: |&Context, &ty::Freevar||) { fn check_for_uniq(cx: &Context, fn_span: Span, - fv: &freevar_entry, + fv: &ty::Freevar, bounds: ty::BuiltinBounds) { // all captured data must be owned, regardless of whether it is // moved in or copied in. @@ -162,7 +160,7 @@ fn with_appropriate_checker(cx: &Context, fn check_for_block(cx: &Context, fn_span: Span, fn_id: NodeId, - fv: &freevar_entry, + fv: &ty::Freevar, bounds: ty::BuiltinBounds) { let id = fv.def.def_id().node; let var_t = ty::node_id_to_type(cx.tcx, id); @@ -177,7 +175,7 @@ fn with_appropriate_checker(cx: &Context, bounds, Some(var_t)); } - fn check_for_bare(cx: &Context, fv: &freevar_entry) { + fn check_for_bare(cx: &Context, fv: &ty::Freevar) { span_err!(cx.tcx.sess, fv.span, E0143, "can't capture dynamic environment in a fn item; \ use the || {} closure form instead", "{ ... }"); @@ -227,7 +225,7 @@ fn check_fn( // Option { - match def { - DefBinding(nid, _) | - DefArg(nid, _) | - DefLocal(nid, _) => Some(nid), - - _ => None - } -} - fn visit_expr(ir: &mut IrMaps, expr: &Expr) { match expr.node { // live nodes required for uses or definitions of variables: ExprPath(_) => { let def = ir.tcx.def_map.borrow().get_copy(&expr.id); debug!("expr {}: path that leads to {:?}", expr.id, def); - if moved_variable_node_id_from_def(def).is_some() { - ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); + match def { + DefLocal(..) => ir.add_live_node_for_node(expr.id, ExprNode(expr.span)), + _ => {} } visit::walk_expr(ir, expr); } @@ -468,15 +458,15 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { // in better error messages than just pointing at the closure // construction site. let mut call_caps = Vec::new(); - freevars::with_freevars(ir.tcx, expr.id, |freevars| { + ty::with_freevars(ir.tcx, expr.id, |freevars| { for fv in freevars.iter() { - match moved_variable_node_id_from_def(fv.def) { - Some(rv) => { + match fv.def { + DefLocal(rv) => { let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); call_caps.push(CaptureInfo {ln: fv_ln, var_nid: rv}); } - None => {} + _ => {} } } }); @@ -1296,9 +1286,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint) -> LiveNode { - let def = self.ir.tcx.def_map.borrow().get_copy(&expr.id); - match moved_variable_node_id_from_def(def) { - Some(nid) => { + match self.ir.tcx.def_map.borrow().get_copy(&expr.id) { + DefLocal(nid) => { let ln = self.live_node(expr.id, expr.span); if acc != 0u { self.init_from_succ(ln, succ); @@ -1307,7 +1296,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } ln } - None => succ + _ => succ } } @@ -1537,7 +1526,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match expr.node { ExprPath(_) => { match self.ir.tcx.def_map.borrow().get_copy(&expr.id) { - DefLocal(nid, _) => { + DefLocal(nid) => { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability @@ -1546,16 +1535,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let var = self.variable(nid, expr.span); self.warn_about_dead_assign(expr.span, expr.id, ln, var); } - def => { - match moved_variable_node_id_from_def(def) { - Some(nid) => { - let ln = self.live_node(expr.id, expr.span); - let var = self.variable(nid, expr.span); - self.warn_about_dead_assign(expr.span, expr.id, ln, var); - } - None => {} - } - } + _ => {} } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 17d941b5958a7..653b24f02558a 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -63,7 +63,6 @@ #![allow(non_camel_case_types)] use middle::def; -use middle::freevars; use middle::ty; use middle::typeck; use util::nodemap::{DefIdMap, NodeMap}; @@ -71,6 +70,7 @@ use util::ppaux::{ty_to_string, Repr}; use syntax::ast::{MutImmutable, MutMutable}; use syntax::ast; +use syntax::ast_map; use syntax::codemap::Span; use syntax::print::pprust; use syntax::parse::token; @@ -85,7 +85,6 @@ pub enum categorization { cat_copied_upvar(CopiedUpvar), // upvar copied into proc env cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure cat_local(ast::NodeId), // local variable - cat_arg(ast::NodeId), // formal argument cat_deref(cmt, uint, PointerKind), // deref of a ptr cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc cat_downcast(cmt), // selects a particular enum variant (*1) @@ -273,7 +272,7 @@ pub trait Typer<'tcx> { fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option; fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow; fn capture_mode(&self, closure_expr_id: ast::NodeId) - -> freevars::CaptureMode; + -> ast::CaptureClause; fn unboxed_closures<'a>(&'a self) -> &'a RefCell>; } @@ -312,28 +311,19 @@ impl MutabilityCategory { } } - fn from_def(def: &def::Def) -> MutabilityCategory { - match *def { - def::DefFn(..) | def::DefStaticMethod(..) | def::DefSelfTy(..) | - def::DefMod(..) | def::DefForeignMod(..) | def::DefVariant(..) | - def::DefTy(..) | def::DefTrait(..) | def::DefPrimTy(..) | - def::DefTyParam(..) | def::DefUse(..) | def::DefStruct(..) | - def::DefTyParamBinder(..) | def::DefRegion(..) | def::DefLabel(..) | - def::DefMethod(..) | def::DefAssociatedTy(..) => { - fail!("no MutabilityCategory for def: {}", *def) - } - - def::DefStatic(_, false) => McImmutable, - def::DefStatic(_, true) => McDeclared, - - def::DefArg(_, binding_mode) | - def::DefBinding(_, binding_mode) | - def::DefLocal(_, binding_mode) => match binding_mode { - ast::BindByValue(ast::MutMutable) => McDeclared, - _ => McImmutable + fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory { + match tcx.map.get(id) { + ast_map::NodeLocal(p) | ast_map::NodeArg(p) => match p.node { + ast::PatIdent(bind_mode, _, _) => { + if bind_mode == ast::BindByValue(ast::MutMutable) { + McDeclared + } else { + McImmutable + } + } + _ => tcx.sess.span_bug(p.span, "expected identifier pattern") }, - - def::DefUpvar(_, def, _, _) => MutabilityCategory::from_def(&*def) + _ => tcx.sess.span_bug(tcx.map.span(id), "expected identifier pattern") } } @@ -546,30 +536,17 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { })) } - def::DefStatic(_, _) => { + def::DefStatic(_, mutbl) => { Ok(Rc::new(cmt_ { id:id, span:span, cat:cat_static_item, - mutbl: MutabilityCategory::from_def(&def), + mutbl: if mutbl { McDeclared } else { McImmutable}, ty:expr_ty })) } - def::DefArg(vid, _) => { - // Idea: make this could be rewritten to model by-ref - // stuff as `&const` and `&mut`? - - Ok(Rc::new(cmt_ { - id: id, - span: span, - cat: cat_arg(vid), - mutbl: MutabilityCategory::from_def(&def), - ty:expr_ty - })) - } - - def::DefUpvar(var_id, _, fn_node_id, _) => { + def::DefUpvar(var_id, fn_node_id, _) => { let ty = if_ok!(self.node_ty(fn_node_id)); match ty::get(ty).sty { ty::ty_closure(ref closure_ty) => { @@ -597,7 +574,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { onceness: closure_ty.onceness, capturing_proc: fn_node_id, }), - mutbl: MutabilityCategory::from_def(&def), + mutbl: MutabilityCategory::from_local(self.tcx(), var_id), ty:expr_ty })) } @@ -620,7 +597,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { onceness: onceness, capturing_proc: fn_node_id, }), - mutbl: MutabilityCategory::from_def(&def), + mutbl: MutabilityCategory::from_local(self.tcx(), var_id), ty: expr_ty })) } @@ -634,14 +611,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } } - def::DefLocal(vid, _) | - def::DefBinding(vid, _) => { - // by-value/by-ref bindings are local variables + def::DefLocal(vid) => { Ok(Rc::new(cmt_ { id: id, span: span, cat: cat_local(vid), - mutbl: MutabilityCategory::from_def(&def), + mutbl: MutabilityCategory::from_local(self.tcx(), vid), ty: expr_ty })) } @@ -1196,11 +1171,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { cat_rvalue(..) => { "non-lvalue".to_string() } - cat_local(_) => { - "local variable".to_string() - } - cat_arg(..) => { - "argument".to_string() + cat_local(vid) => { + match self.tcx().map.find(vid) { + Some(ast_map::NodeArg(_)) => { + "argument".to_string() + } + _ => "local variable".to_string() + } } cat_deref(ref base, _, pk) => { match base.cat { @@ -1267,7 +1244,6 @@ impl cmt_ { cat_static_item | cat_copied_upvar(..) | cat_local(..) | - cat_arg(..) | cat_deref(_, _, UnsafePtr(..)) | cat_deref(_, _, GcPtr(..)) | cat_deref(_, _, BorrowedPtr(..)) | @@ -1311,7 +1287,6 @@ impl cmt_ { cat_rvalue(..) | cat_local(..) | cat_upvar(..) | - cat_arg(_) | cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but... None } @@ -1363,8 +1338,7 @@ impl Repr for categorization { cat_rvalue(..) | cat_copied_upvar(..) | cat_local(..) | - cat_upvar(..) | - cat_arg(..) => { + cat_upvar(..) => { format!("{:?}", *self) } cat_deref(ref cmt, derefs, ptr) => { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 6fa33f4b5aa03..2e198d8afb0fa 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -19,7 +19,8 @@ use middle::lang_items::LanguageItems; use middle::pat_util::pat_bindings; use middle::subst::{ParamSpace, FnSpace, TypeSpace}; use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory}; -use util::nodemap::{NodeMap, DefIdSet, FnvHashMap}; +use middle::ty::{CaptureModeMap, Freevar, FreevarMap}; +use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap}; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField}; @@ -59,7 +60,6 @@ use syntax::visit::Visitor; use std::collections::{HashMap, HashSet}; use std::cell::{Cell, RefCell}; -use std::gc::GC; use std::mem::replace; use std::rc::{Rc, Weak}; use std::uint; @@ -270,16 +270,16 @@ enum TypeParameters<'a> { RibKind) } -// The rib kind controls the translation of argument or local definitions -// (`def_arg` or `def_local`) to upvars (`def_upvar`). +// The rib kind controls the translation of local +// definitions (`DefLocal`) to upvars (`DefUpvar`). enum RibKind { // No translation needs to be applied. NormalRibKind, - // We passed through a function scope at the given node ID. Translate - // upvars as appropriate. - FunctionRibKind(NodeId /* func id */, NodeId /* body id */), + // We passed through a closure scope at the given node ID. + // Translate upvars as appropriate. + ClosureRibKind(NodeId /* func id */, NodeId /* body id if proc or unboxed */), // We passed through an impl or trait and are now in one of its // methods. Allow references to ty params that impl or trait @@ -891,6 +891,9 @@ struct Resolver<'a> { primitive_type_table: PrimitiveTypeTable, def_map: DefMap, + freevars: RefCell, + freevars_seen: RefCell>, + capture_mode_map: RefCell, export_map2: ExportMap2, trait_map: TraitMap, external_exports: ExternalExports, @@ -996,6 +999,9 @@ impl<'a> Resolver<'a> { primitive_type_table: PrimitiveTypeTable::new(), def_map: RefCell::new(NodeMap::new()), + freevars: RefCell::new(NodeMap::new()), + freevars_seen: RefCell::new(NodeMap::new()), + capture_mode_map: RefCell::new(NodeMap::new()), export_map2: RefCell::new(NodeMap::new()), trait_map: NodeMap::new(), used_imports: HashSet::new(), @@ -1895,8 +1901,7 @@ impl<'a> Resolver<'a> { ignoring {:?}", def); // Ignored; handled elsewhere. } - DefArg(..) | DefLocal(..) | DefPrimTy(..) | - DefTyParam(..) | DefBinding(..) | + DefLocal(..) | DefPrimTy(..) | DefTyParam(..) | DefUse(..) | DefUpvar(..) | DefRegion(..) | DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => { fail!("didn't expect `{:?}`", def); @@ -3828,130 +3833,143 @@ impl<'a> Resolver<'a> { self.current_module = orig_module; } - /// Wraps the given definition in the appropriate number of `def_upvar` + /// Wraps the given definition in the appropriate number of `DefUpvar` /// wrappers. fn upvarify(&self, ribs: &[Rib], - rib_index: uint, def_like: DefLike, span: Span) -> Option { - let mut def; - let is_ty_param; - match def_like { - DlDef(d @ DefLocal(..)) | DlDef(d @ DefUpvar(..)) | - DlDef(d @ DefArg(..)) | DlDef(d @ DefBinding(..)) => { - def = d; - is_ty_param = false; - } - DlDef(d @ DefTyParam(..)) | - DlDef(d @ DefSelfTy(..)) => { - def = d; - is_ty_param = true; - } - _ => { - return Some(def_like); - } - } + DlDef(d @ DefUpvar(..)) => { + self.session.span_bug(span, + format!("unexpected {} in bindings", d).as_slice()) + } + DlDef(d @ DefLocal(_)) => { + let node_id = d.def_id().node; + let mut def = d; + let mut last_proc_body_id = ast::DUMMY_NODE_ID; + for rib in ribs.iter() { + match rib.kind { + NormalRibKind => { + // Nothing to do. Continue. + } + ClosureRibKind(function_id, maybe_proc_body) => { + let prev_def = def; + if maybe_proc_body != ast::DUMMY_NODE_ID { + last_proc_body_id = maybe_proc_body; + } + def = DefUpvar(node_id, function_id, last_proc_body_id); - let mut rib_index = rib_index + 1; - while rib_index < ribs.len() { - match ribs[rib_index].kind { - NormalRibKind => { - // Nothing to do. Continue. - } - FunctionRibKind(function_id, body_id) => { - if !is_ty_param { - def = DefUpvar(def.def_id().node, - box(GC) def, - function_id, - body_id); - } - } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - DefTyParam(_, did, _) if { - self.def_map.borrow().find(&did.node).map(|x| *x) - == Some(DefTyParamBinder(item_id)) - } => { - // ok - } + let mut seen = self.freevars_seen.borrow_mut(); + let seen = seen.find_or_insert(function_id, NodeSet::new()); + if seen.contains(&node_id) { + continue; + } + self.freevars.borrow_mut().find_or_insert(function_id, vec![]) + .push(Freevar { def: prev_def, span: span }); + seen.insert(node_id); + } + MethodRibKind(item_id, _) => { + // If the def is a ty param, and came from the parent + // item, it's ok + match def { + DefTyParam(_, did, _) if { + self.def_map.borrow().find_copy(&did.node) + == Some(DefTyParamBinder(item_id)) + } => {} // ok + DefSelfTy(did) if did == item_id => {} // ok + _ => { + // This was an attempt to access an upvar inside a + // named function item. This is not allowed, so we + // report an error. - DefSelfTy(did) if { - did == item_id - } => { - // ok - } + self.resolve_error( + span, + "can't capture dynamic environment in a fn item; \ + use the || { ... } closure form instead"); - _ => { - if !is_ty_param { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. + return None; + } + } + } + ItemRibKind => { + // This was an attempt to access an upvar inside a + // named function item. This is not allowed, so we + // report an error. - self.resolve_error( - span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - } else { - // This was an attempt to use a type parameter outside - // its scope. + self.resolve_error( + span, + "can't capture dynamic environment in a fn item; \ + use the || { ... } closure form instead"); - self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - } + return None; + } + ConstantItemRibKind => { + // Still doesn't deal with upvars + self.resolve_error(span, + "attempt to use a non-constant \ + value in a constant"); - return None; + } } - } } - ItemRibKind => { - if !is_ty_param { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. + Some(DlDef(def)) + } + DlDef(def @ DefTyParam(..)) | + DlDef(def @ DefSelfTy(..)) => { + for rib in ribs.iter() { + match rib.kind { + NormalRibKind | ClosureRibKind(..) => { + // Nothing to do. Continue. + } + MethodRibKind(item_id, _) => { + // If the def is a ty param, and came from the parent + // item, it's ok + match def { + DefTyParam(_, did, _) if { + self.def_map.borrow().find_copy(&did.node) + == Some(DefTyParamBinder(item_id)) + } => {} // ok + DefSelfTy(did) if did == item_id => {} // ok - self.resolve_error( - span, - "can't capture dynamic environment in a fn item; \ - use the || { ... } closure form instead"); - } else { - // This was an attempt to use a type parameter outside - // its scope. + _ => { + // This was an attempt to use a type parameter outside + // its scope. - self.resolve_error(span, - "can't use type parameters from \ - outer function; try using a local \ - type parameter instead"); - } + self.resolve_error(span, + "can't use type parameters from \ + outer function; try using a local \ + type parameter instead"); - return None; - } - ConstantItemRibKind => { - if is_ty_param { - // see #9186 - self.resolve_error(span, - "cannot use an outer type \ - parameter in this context"); - } else { - // Still doesn't deal with upvars - self.resolve_error(span, - "attempt to use a non-constant \ - value in a constant"); - } + return None; + } + } + } + ItemRibKind => { + // This was an attempt to use a type parameter outside + // its scope. + self.resolve_error(span, + "can't use type parameters from \ + outer function; try using a local \ + type parameter instead"); + + return None; + } + ConstantItemRibKind => { + // see #9186 + self.resolve_error(span, + "cannot use an outer type \ + parameter in this context"); + + } + } } + Some(DlDef(def)) } - - rib_index += 1; + _ => Some(def_like) } - - return Some(DlDef(def)); } fn search_ribs(&self, @@ -3959,16 +3977,12 @@ impl<'a> Resolver<'a> { name: Name, span: Span) -> Option { - // FIXME #4950: This should not use a while loop. // FIXME #4950: Try caching? - let mut i = ribs.len(); - while i != 0 { - i -= 1; - let binding_opt = ribs[i].bindings.borrow().find_copy(&name); - match binding_opt { + for (i, rib) in ribs.iter().enumerate().rev() { + match rib.bindings.borrow().find_copy(&name) { Some(def_like) => { - return self.upvarify(ribs, i, def_like, span); + return self.upvarify(ribs.slice_from(i + 1), def_like, span); } None => { // Continue. @@ -3976,7 +3990,7 @@ impl<'a> Resolver<'a> { } } - return None; + None } fn resolve_crate(&mut self, krate: &ast::Crate) { @@ -4942,22 +4956,7 @@ impl<'a> Resolver<'a> { debug!("(resolving pattern) binding `{}`", token::get_name(renamed)); - let def = match mode { - RefutableMode => { - // For pattern arms, we must use - // `def_binding` definitions. - - DefBinding(pattern.id, binding_mode) - } - LocalIrrefutableMode => { - // But for locals, we use `def_local`. - DefLocal(pattern.id, binding_mode) - } - ArgumentIrrefutableMode => { - // And for function arguments, `def_arg`. - DefArg(pattern.id, binding_mode) - } - }; + let def = DefLocal(pattern.id); // Record the definition so that later passes // will be able to distinguish variants from @@ -5775,10 +5774,24 @@ impl<'a> Resolver<'a> { visit::walk_expr(self, expr); } - ExprFnBlock(_, ref fn_decl, ref block) | - ExprProc(ref fn_decl, ref block) | - ExprUnboxedFn(_, _, ref fn_decl, ref block) => { - self.resolve_function(FunctionRibKind(expr.id, block.id), + ExprFnBlock(_, ref fn_decl, ref block) => { + // NOTE(stage0): After snapshot, change to: + // + //self.capture_mode_map.borrow_mut().insert(expr.id, capture_clause); + self.capture_mode_map.borrow_mut().insert(expr.id, ast::CaptureByRef); + self.resolve_function(ClosureRibKind(expr.id, ast::DUMMY_NODE_ID), + Some(&**fn_decl), NoTypeParameters, + &**block); + } + ExprProc(ref fn_decl, ref block) => { + self.capture_mode_map.borrow_mut().insert(expr.id, ast::CaptureByValue); + self.resolve_function(ClosureRibKind(expr.id, block.id), + Some(&**fn_decl), NoTypeParameters, + &**block); + } + ExprUnboxedFn(capture_clause, _, ref fn_decl, ref block) => { + self.capture_mode_map.borrow_mut().insert(expr.id, capture_clause); + self.resolve_function(ClosureRibKind(expr.id, block.id), Some(&**fn_decl), NoTypeParameters, &**block); } @@ -6209,6 +6222,8 @@ impl<'a> Resolver<'a> { pub struct CrateMap { pub def_map: DefMap, + pub freevars: RefCell, + pub capture_mode_map: RefCell, pub exp_map2: ExportMap2, pub trait_map: TraitMap, pub external_exports: ExternalExports, @@ -6222,13 +6237,13 @@ pub fn resolve_crate(session: &Session, -> CrateMap { let mut resolver = Resolver::new(session, krate.span); resolver.resolve(krate); - let Resolver { def_map, export_map2, trait_map, last_private, - external_exports, .. } = resolver; CrateMap { - def_map: def_map, - exp_map2: export_map2, - trait_map: trait_map, - external_exports: external_exports, - last_private_map: last_private, + def_map: resolver.def_map, + freevars: resolver.freevars, + capture_mode_map: resolver.capture_mode_map, + exp_map2: resolver.export_map2, + trait_map: resolver.trait_map, + external_exports: resolver.external_exports, + last_private_map: resolver.last_private, } } diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs index cab83f4cda244..a2debe61e5f60 100644 --- a/src/librustc/middle/save/mod.rs +++ b/src/librustc/middle/save/mod.rs @@ -230,11 +230,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefAssociatedTy(..) | def::DefTrait(_) => Some(recorder::TypeRef), def::DefStatic(_, _) | - def::DefBinding(_, _) | - def::DefArg(_, _) | - def::DefLocal(_, _) | + def::DefLocal(_) | def::DefVariant(_, _, _) | - def::DefUpvar(_, _, _, _) => Some(recorder::VarRef), + def::DefUpvar(..) => Some(recorder::VarRef), def::DefFn(_, _) => Some(recorder::FnRef), @@ -739,20 +737,14 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { let def = def_map.get(&ex.id); let sub_span = self.span.span_for_last_ident(ex.span); match *def { - def::DefLocal(id, _) | - def::DefArg(id, _) | - def::DefUpvar(id, _, _, _) | - def::DefBinding(id, _) => self.fmt.ref_str(recorder::VarRef, - ex.span, - sub_span, - ast_util::local_def(id), - self.cur_scope), - def::DefStatic(def_id,_) | - def::DefVariant(_, def_id, _) => self.fmt.ref_str(recorder::VarRef, - ex.span, - sub_span, - def_id, - self.cur_scope), + def::DefUpvar(..) | + def::DefLocal(..) | + def::DefStatic(..) | + def::DefVariant(..) => self.fmt.ref_str(recorder::VarRef, + ex.span, + sub_span, + def.def_id(), + self.cur_scope), def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef, ex.span, sub_span, @@ -813,8 +805,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { def::DefStaticMethod(_, _, _) => { self.write_sub_path_trait_truncated(path); }, - def::DefLocal(_, _) | - def::DefArg(_, _) | + def::DefLocal(_) | def::DefStatic(_,_) | def::DefStruct(_) | def::DefFn(_, _) => self.write_sub_paths_truncated(path), @@ -1382,12 +1373,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { } let def = def_map.get(&id); match *def { - def::DefBinding(id, _) => self.fmt.variable_str(p.span, - sub_span, - id, - path_to_string(p).as_slice(), - value.as_slice(), - ""), + def::DefLocal(id) => self.fmt.variable_str(p.span, + sub_span, + id, + path_to_string(p).as_slice(), + value.as_slice(), + ""), def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind, p.span, sub_span, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 51023d03c23b0..68d0bb2d8b498 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -1226,8 +1226,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool { match discr.node { ast::ExprPath(..) => match bcx.def(discr.id) { - def::DefArg(vid, _) | def::DefBinding(vid, _) | - def::DefLocal(vid, _) | def::DefUpvar(vid, _, _, _) => { + def::DefLocal(vid) | def::DefUpvar(vid, _, _) => { let mut rc = ReassignmentChecker { node: vid, reassigned: false @@ -1259,7 +1258,7 @@ impl euv::Delegate for ReassignmentChecker { fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) { match cmt.cat { mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: vid, .. }) | - mc::cat_arg(vid) | mc::cat_local(vid) => self.reassigned = self.node == vid, + mc::cat_local(vid) => self.reassigned = self.node == vid, _ => {} } } @@ -1391,13 +1390,6 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, return bcx; } -enum IrrefutablePatternBindingMode { - // Stores the association between node ID and LLVM value in `lllocals`. - BindLocal, - // Stores the association between node ID and LLVM value in `llargs`. - BindArgument -} - pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &ast::Local) -> Block<'blk, 'tcx> { @@ -1419,7 +1411,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| { let scope = cleanup::var_scope(tcx, p_id); bcx = mk_binding_alloca( - bcx, p_id, &path1.node, BindLocal, scope, (), + bcx, p_id, &path1.node, scope, (), |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx }); }); bcx @@ -1441,7 +1433,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Some(ident) => { let var_scope = cleanup::var_scope(tcx, local.id); return mk_binding_alloca( - bcx, pat.id, ident, BindLocal, var_scope, (), + bcx, pat.id, ident, var_scope, (), |(), bcx, v, _| expr::trans_into(bcx, &**init_expr, expr::SaveIn(v))); } @@ -1459,7 +1451,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, add_comment(bcx, "creating zeroable ref llval"); } let var_scope = cleanup::var_scope(tcx, local.id); - bind_irrefutable_pat(bcx, pat, init_datum.val, BindLocal, var_scope) + bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope) } } None => { @@ -1475,7 +1467,7 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, -> Block<'blk, 'tcx> { /*! * Generates code for argument patterns like `fn foo(: T)`. - * Creates entries in the `llargs` map for each of the bindings + * Creates entries in the `lllocals` map for each of the bindings * in `pat`. * * # Arguments @@ -1499,12 +1491,12 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // already put it in a temporary alloca and gave it up, unless // we emit extra-debug-info, which requires local allocas :(. let arg_val = arg.add_clean(bcx.fcx, arg_scope); - bcx.fcx.llargs.borrow_mut() + bcx.fcx.lllocals.borrow_mut() .insert(pat.id, Datum::new(arg_val, arg_ty, Lvalue)); bcx } else { mk_binding_alloca( - bcx, pat.id, ident, BindArgument, arg_scope, arg, + bcx, pat.id, ident, arg_scope, arg, |arg, bcx, llval, _| arg.store_to(bcx, llval)) } } @@ -1514,8 +1506,7 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // pattern. let arg = unpack_datum!( bcx, arg.to_lvalue_datum_in_scope(bcx, "__arg", arg_scope)); - bind_irrefutable_pat(bcx, pat, arg.val, - BindArgument, arg_scope) + bind_irrefutable_pat(bcx, pat, arg.val, arg_scope) } } } @@ -1541,13 +1532,12 @@ pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } // General path. Copy out the values that are used in the pattern. - bind_irrefutable_pat(bcx, pat, llvalue, BindLocal, body_scope) + bind_irrefutable_pat(bcx, pat, llvalue, body_scope) } fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, p_id: ast::NodeId, ident: &ast::Ident, - binding_mode: IrrefutablePatternBindingMode, cleanup_scope: cleanup::ScopeId, arg: A, populate: |A, Block<'blk, 'tcx>, ValueRef, ty::t| @@ -1567,18 +1557,13 @@ fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, // Now that memory is initialized and has cleanup scheduled, // create the datum and insert into the local variable map. let datum = Datum::new(llval, var_ty, Lvalue); - let mut llmap = match binding_mode { - BindLocal => bcx.fcx.lllocals.borrow_mut(), - BindArgument => bcx.fcx.llargs.borrow_mut() - }; - llmap.insert(p_id, datum); + bcx.fcx.lllocals.borrow_mut().insert(p_id, datum); bcx } fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, val: ValueRef, - binding_mode: IrrefutablePatternBindingMode, cleanup_scope: cleanup::ScopeId) -> Block<'blk, 'tcx> { /*! @@ -1594,13 +1579,11 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, * - bcx: starting basic block context * - pat: the irrefutable pattern being matched. * - val: the value being matched -- must be an lvalue (by ref, with cleanup) - * - binding_mode: is this for an argument or a local variable? */ - debug!("bind_irrefutable_pat(bcx={}, pat={}, binding_mode={:?})", + debug!("bind_irrefutable_pat(bcx={}, pat={})", bcx.to_str(), - pat.repr(bcx.tcx()), - binding_mode); + pat.repr(bcx.tcx())); if bcx.sess().asm_comments() { add_comment(bcx, format!("bind_irrefutable_pat(pat={})", @@ -1620,7 +1603,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // binding will live and place it into the appropriate // map. bcx = mk_binding_alloca( - bcx, pat.id, &path1.node, binding_mode, cleanup_scope, (), + bcx, pat.id, &path1.node, cleanup_scope, (), |(), bcx, llval, ty| { match pat_binding_mode { ast::BindByValue(_) => { @@ -1641,8 +1624,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } for inner_pat in inner.iter() { - bcx = bind_irrefutable_pat(bcx, &**inner_pat, val, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, &**inner_pat, val, cleanup_scope); } } ast::PatEnum(_, ref sub_pats) => { @@ -1660,8 +1642,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, for sub_pat in sub_pats.iter() { for (i, &argval) in args.vals.iter().enumerate() { bcx = bind_irrefutable_pat(bcx, &**sub_pat.get(i), - argval, binding_mode, - cleanup_scope); + argval, cleanup_scope); } } } @@ -1678,8 +1659,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i); bcx = bind_irrefutable_pat(bcx, &**elem, - fldptr, binding_mode, - cleanup_scope); + fldptr, cleanup_scope); } } } @@ -1698,8 +1678,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys); let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val, discr, ix); - bcx = bind_irrefutable_pat(bcx, &*f.pat, fldptr, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, &*f.pat, fldptr, cleanup_scope); } }) } @@ -1707,17 +1686,16 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let repr = adt::represent_node(bcx, pat.id); for (i, elem) in elems.iter().enumerate() { let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i); - bcx = bind_irrefutable_pat(bcx, &**elem, fldptr, - binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, &**elem, fldptr, cleanup_scope); } } ast::PatBox(ref inner) => { let llbox = Load(bcx, val); - bcx = bind_irrefutable_pat(bcx, &**inner, llbox, binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, &**inner, llbox, cleanup_scope); } ast::PatRegion(ref inner) => { let loaded_val = Load(bcx, val); - bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, binding_mode, cleanup_scope); + bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, cleanup_scope); } ast::PatVec(ref before, ref slice, ref after) => { let pat_ty = node_id_type(bcx, pat.id); @@ -1737,7 +1715,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, .chain(after.iter()) .zip(extracted.vals.into_iter()) .fold(bcx, |bcx, (inner, elem)| - bind_irrefutable_pat(bcx, &**inner, elem, binding_mode, cleanup_scope) + bind_irrefutable_pat(bcx, &**inner, elem, cleanup_scope) ); } ast::PatMac(..) => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a814c9d624cfa..3e8b7c267bd25 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1468,7 +1468,6 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, needs_ret_allocas: nested_returns, personality: Cell::new(None), caller_expects_out_pointer: uses_outptr, - llargs: RefCell::new(NodeMap::new()), lllocals: RefCell::new(NodeMap::new()), llupvars: RefCell::new(NodeMap::new()), id: id, diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index c54a446c455c7..bcf7a08de354f 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -196,9 +196,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } def::DefStatic(..) | - def::DefArg(..) | def::DefLocal(..) | - def::DefBinding(..) | def::DefUpvar(..) => { datum_callee(bcx, ref_expr) } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 6ab344ff69e93..fa8c6b8b4482f 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -14,7 +14,7 @@ use back::link::mangle_internal_name_by_path_and_seq; use driver::config::FullDebugInfo; use llvm::ValueRef; use middle::def; -use middle::freevars; +use middle::mem_categorization::Typer; use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; @@ -100,7 +100,7 @@ use syntax::ast_util; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pub struct EnvValue { - action: freevars::CaptureMode, + action: ast::CaptureClause, datum: Datum } @@ -120,8 +120,8 @@ pub fn mk_closure_tys(tcx: &ty::ctxt, // converted to ptrs. let bound_tys = bound_values.iter().map(|bv| { match bv.action { - freevars::CaptureByValue => bv.datum.ty, - freevars::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty) + ast::CaptureByValue => bv.datum.ty, + ast::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty) } }).collect(); let cdata_ty = ty::mk_tup(tcx, bound_tys); @@ -208,10 +208,10 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let bound_data = GEPi(bcx, llbox, [0u, abi::box_field_body, i]); match bv.action { - freevars::CaptureByValue => { + ast::CaptureByValue => { bcx = bv.datum.store_to(bcx, bound_data); } - freevars::CaptureByRef => { + ast::CaptureByRef => { Store(bcx, bv.datum.to_llref(), bound_data); } } @@ -223,8 +223,8 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Given a context and a list of upvars, build a closure. This just // collects the upvars and packages them up for store_environment. fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, - freevar_mode: freevars::CaptureMode, - freevars: &Vec, + freevar_mode: ast::CaptureClause, + freevars: &Vec, store: ty::TraitStore) -> ClosureResult<'blk, 'tcx> { let _icx = push_ctxt("closure::build_closure"); @@ -247,7 +247,7 @@ fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, // with the upvars and type descriptors. fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, cdata_ty: ty::t, - freevars: &Vec, + freevars: &Vec, store: ty::TraitStore) -> Block<'blk, 'tcx> { let _icx = push_ctxt("closure::load_environment"); @@ -301,7 +301,7 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn load_unboxed_closure_environment<'blk, 'tcx>( bcx: Block<'blk, 'tcx>, arg_scope_id: ScopeId, - freevars: &Vec, + freevars: &Vec, closure_id: ast::DefId) -> Block<'blk, 'tcx> { let _icx = push_ctxt("closure::load_environment"); @@ -386,11 +386,9 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // set an inline hint for all closures set_inline_hint(llfn); - let freevar_mode = freevars::get_capture_mode(tcx, id); - let freevars: Vec = - freevars::with_freevars(tcx, - id, - |fv| fv.iter().map(|&fv| fv).collect()); + let freevar_mode = tcx.capture_mode(id); + let freevars: Vec = + ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect()); let ClosureResult { llbox, @@ -476,10 +474,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( .clone(); let function_type = ty::mk_closure(bcx.tcx(), function_type); - let freevars: Vec = - freevars::with_freevars(bcx.tcx(), - id, - |fv| fv.iter().map(|&fv| fv).collect()); + let freevars: Vec = + ty::with_freevars(bcx.tcx(), id, |fv| fv.iter().map(|&fv| fv).collect()); let freevars_ptr = &freevars; trans_closure(bcx.ccx(), diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 60ae26439b483..a5a9d6851762a 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -17,7 +17,6 @@ use llvm; use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef}; use llvm::{True, False, Bool}; use middle::def; -use middle::freevars; use middle::lang_items::LangItem; use middle::mem_categorization as mc; use middle::subst; @@ -267,10 +266,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> { // points to, but if this value is false, that slot will be a local alloca. pub caller_expects_out_pointer: bool, - // Maps arguments to allocas created for them in llallocas. - pub llargs: RefCell>, - - // Maps the def_ids for local variables to the allocas created for + // Maps the DefId's for local variables to the allocas created for // them in llallocas. pub lllocals: RefCell>, @@ -528,7 +524,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } fn capture_mode(&self, closure_expr_id: ast::NodeId) - -> freevars::CaptureMode { + -> ast::CaptureClause { self.tcx().capture_modes.borrow().get_copy(&closure_expr_id) } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 359da14d57eaf..daf910f604fb5 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -1005,11 +1005,11 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata; pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| { - let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) { + let llarg = match bcx.fcx.lllocals.borrow().find_copy(&node_id) { Some(v) => v, None => { bcx.sess().span_bug(span, - format!("no entry in llargs table for {:?}", + format!("no entry in lllocals table for {:?}", node_id).as_slice()); } }; diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 77712570185d9..fd063d79b0bb3 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -71,7 +71,6 @@ use middle::typeck; use middle::typeck::MethodCall; use util::common::indenter; use util::ppaux::Repr; -use util::nodemap::NodeMap; use middle::trans::machine::{llsize_of, llsize_of_alloc}; use middle::trans::type_::Type; @@ -1176,8 +1175,8 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_local_var"); - return match def { - def::DefUpvar(nid, _, _, _) => { + match def { + def::DefUpvar(nid, _, _) => { // Can't move upvars, so this is never a ZeroMemLastUse. let local_ty = node_id_type(bcx, nid); match bcx.fcx.llupvars.borrow().find(&nid) { @@ -1189,34 +1188,24 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } } - def::DefArg(nid, _) => { - take_local(bcx, &*bcx.fcx.llargs.borrow(), nid) - } - def::DefLocal(nid, _) | def::DefBinding(nid, _) => { - take_local(bcx, &*bcx.fcx.lllocals.borrow(), nid) + def::DefLocal(nid) => { + let datum = match bcx.fcx.lllocals.borrow().find(&nid) { + Some(&v) => v, + None => { + bcx.sess().bug(format!( + "trans_local_var: no datum for local/arg {:?} found", + nid).as_slice()); + } + }; + debug!("take_local(nid={:?}, v={}, ty={})", + nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty)); + datum } _ => { bcx.sess().unimpl(format!( "unsupported def type in trans_local_var: {:?}", def).as_slice()); } - }; - - fn take_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - table: &NodeMap>, - nid: ast::NodeId) - -> Datum { - let datum = match table.find(&nid) { - Some(&v) => v, - None => { - bcx.sess().bug(format!( - "trans_local_var: no datum for local/arg {:?} found", - nid).as_slice()); - } - }; - debug!("take_local(nid={:?}, v={}, ty={})", - nid, bcx.val_to_string(datum.val), bcx.ty_to_string(datum.ty)); - datum } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 897bc4517f4e1..7e767b96b6d9c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -17,8 +17,6 @@ use metadata::csearch; use middle::const_eval; use middle::def; use middle::dependency_format; -use middle::freevars::CaptureModeMap; -use middle::freevars; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; use middle::lang_items::{FnOnceTraitLangItem, OpaqueStructLangItem}; use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem}; @@ -480,7 +478,7 @@ pub struct ctxt<'tcx> { pub map: ast_map::Map<'tcx>, pub intrinsic_defs: RefCell>, - pub freevars: RefCell, + pub freevars: RefCell, pub tcache: type_cache, pub rcache: creader_cache, pub short_names_cache: RefCell>, @@ -1463,8 +1461,8 @@ pub fn mk_ctxt<'tcx>(s: Session, dm: resolve::DefMap, named_region_map: resolve_lifetime::NamedRegionMap, map: ast_map::Map<'tcx>, - freevars: freevars::freevar_map, - capture_modes: freevars::CaptureModeMap, + freevars: RefCell, + capture_modes: RefCell, region_maps: middle::region::RegionMaps, lang_items: middle::lang_items::LanguageItems, stability: stability::Index) -> ctxt<'tcx> { @@ -1485,7 +1483,7 @@ pub fn mk_ctxt<'tcx>(s: Session, object_cast_map: RefCell::new(NodeMap::new()), map: map, intrinsic_defs: RefCell::new(DefIdMap::new()), - freevars: RefCell::new(freevars), + freevars: freevars, tcache: RefCell::new(DefIdMap::new()), rcache: RefCell::new(HashMap::new()), short_names_cache: RefCell::new(HashMap::new()), @@ -1522,7 +1520,7 @@ pub fn mk_ctxt<'tcx>(s: Session, node_lint_levels: RefCell::new(HashMap::new()), transmute_restrictions: RefCell::new(Vec::new()), stability: RefCell::new(stability), - capture_modes: RefCell::new(capture_modes), + capture_modes: capture_modes, associated_types: RefCell::new(DefIdMap::new()), trait_associated_types: RefCell::new(DefIdMap::new()), } @@ -3684,9 +3682,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { // DefArg's, particularly those of immediate type, ought to // considered rvalues. def::DefStatic(..) | - def::DefBinding(..) | def::DefUpvar(..) | - def::DefArg(..) | def::DefLocal(..) => LvalueExpr, def => { @@ -4759,7 +4755,7 @@ pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId) -> Vec { if closure_id.krate == ast::LOCAL_CRATE { match tcx.freevars.borrow().find(&closure_id.node) { - None => tcx.sess.bug("no freevars for unboxed closure?!"), + None => vec![], Some(ref freevars) => { freevars.iter().map(|freevar| { let freevar_def_id = freevar.def.def_id(); @@ -5617,7 +5613,7 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> { } fn capture_mode(&self, closure_expr_id: ast::NodeId) - -> freevars::CaptureMode { + -> ast::CaptureClause { self.capture_modes.borrow().get_copy(&closure_expr_id) } @@ -5688,3 +5684,24 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, } }) } + +/// A free variable referred to in a function. +#[deriving(Encodable, Decodable)] +pub struct Freevar { + /// The variable being accessed free. + pub def: def::Def, + + // First span where it is accessed (there can be multiple). + pub span: Span +} + +pub type FreevarMap = NodeMap>; + +pub type CaptureModeMap = NodeMap; + +pub fn with_freevars(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T { + match tcx.freevars.borrow().find(&fid) { + None => f(&[]), + Some(d) => f(d.as_slice()) + } +} diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index c8728d375f6a3..9676e1515530e 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -79,7 +79,6 @@ type parameter). use middle::const_eval; use middle::def; -use middle::freevars; use middle::lang_items::IteratorItem; use middle::mem_categorization::McResult; use middle::mem_categorization; @@ -318,7 +317,7 @@ impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> { self.ccx.tcx.upvar_borrow(upvar_id) } fn capture_mode(&self, closure_expr_id: ast::NodeId) - -> freevars::CaptureMode { + -> ast::CaptureClause { self.ccx.tcx.capture_mode(closure_expr_id) } fn unboxed_closures<'a>(&'a self) @@ -5027,8 +5026,7 @@ pub fn polytype_for_def(fcx: &FnCtxt, defn: def::Def) -> Polytype { match defn { - def::DefArg(nid, _) | def::DefLocal(nid, _) | - def::DefBinding(nid, _) => { + def::DefLocal(nid) | def::DefUpvar(nid, _, _) => { let typ = fcx.local_ty(sp, nid); return no_params(typ); } @@ -5037,9 +5035,6 @@ pub fn polytype_for_def(fcx: &FnCtxt, def::DefStruct(id) => { return ty::lookup_item_type(fcx.ccx.tcx, id); } - def::DefUpvar(_, inner, _, _) => { - return polytype_for_def(fcx, sp, *inner); - } def::DefTrait(_) | def::DefTy(..) | def::DefAssociatedTy(..) | @@ -5183,10 +5178,8 @@ pub fn instantiate_path(fcx: &FnCtxt, // elsewhere. (I hope) def::DefMod(..) | def::DefForeignMod(..) | - def::DefArg(..) | def::DefLocal(..) | def::DefMethod(..) | - def::DefBinding(..) | def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) | diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index a8f2a8f6f1dbb..2effff4767b02 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -119,8 +119,6 @@ and report an error, and it just seems like more mess in the end.) */ use middle::def; -use middle::def::{DefArg, DefBinding, DefLocal, DefUpvar}; -use middle::freevars; use middle::mem_categorization as mc; use middle::ty::{ReScope}; use middle::ty; @@ -243,14 +241,14 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region { let tcx = fcx.tcx(); match def { - DefLocal(node_id, _) | DefArg(node_id, _) | - DefBinding(node_id, _) => { + def::DefLocal(node_id) => { tcx.region_maps.var_region(node_id) } - DefUpvar(_, subdef, closure_id, body_id) => { - match ty::ty_closure_store(fcx.node_ty(closure_id)) { - ty::RegionTraitStore(..) => region_of_def(fcx, *subdef), - ty::UniqTraitStore => ReScope(body_id) + def::DefUpvar(node_id, _, body_id) => { + if body_id == ast::DUMMY_NODE_ID { + tcx.region_maps.var_region(node_id) + } else { + ReScope(body_id) } } _ => { @@ -479,7 +477,7 @@ impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> { } fn capture_mode(&self, closure_expr_id: ast::NodeId) - -> freevars::CaptureMode { + -> ast::CaptureClause { self.tcx().capture_modes.borrow().get_copy(&closure_expr_id) } @@ -852,7 +850,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, ..}) => { // For closure, ensure that the variables outlive region // bound, since they are captured by reference. - freevars::with_freevars(tcx, expr.id, |freevars| { + ty::with_freevars(tcx, expr.id, |freevars| { if freevars.is_empty() { // No free variables means that the environment // will be NULL at runtime and hence the closure @@ -875,13 +873,13 @@ fn check_expr_fn_block(rcx: &mut Rcx, ..}) => { // For proc, ensure that the *types* of the variables // outlive region bound, since they are captured by value. - freevars::with_freevars(tcx, expr.id, |freevars| { + ty::with_freevars(tcx, expr.id, |freevars| { ensure_free_variable_types_outlive_closure_bound( rcx, bounds.region_bound, expr, freevars); }); } ty::ty_unboxed_closure(_, region) => { - freevars::with_freevars(tcx, expr.id, |freevars| { + ty::with_freevars(tcx, expr.id, |freevars| { // No free variables means that there is no environment and // hence the closure has static lifetime. Otherwise, the // closure must not outlive the variables it closes over @@ -907,7 +905,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, store: ty::RegionTraitStore(..), .. }) => { - freevars::with_freevars(tcx, expr.id, |freevars| { + ty::with_freevars(tcx, expr.id, |freevars| { propagate_upupvar_borrow_kind(rcx, expr, freevars); }) } @@ -918,7 +916,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, rcx: &mut Rcx, region_bound: ty::Region, expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) + freevars: &[ty::Freevar]) { /*! * Make sure that the type of all free variables referenced @@ -951,7 +949,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, rcx: &mut Rcx, region_bound: ty::Region, expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) + freevars: &[ty::Freevar]) { /*! * Make sure that all free variables referenced inside the @@ -1001,7 +999,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, fn propagate_upupvar_borrow_kind(rcx: &mut Rcx, expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { + freevars: &[ty::Freevar]) { let tcx = rcx.fcx.ccx.tcx; debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx)); for freevar in freevars.iter() { @@ -1031,7 +1029,7 @@ fn check_expr_fn_block(rcx: &mut Rcx, // determining the final borrow_kind) and propagate that as // a constraint on the outer closure. match freevar.def { - def::DefUpvar(var_id, _, outer_closure_id, _) => { + def::DefUpvar(var_id, outer_closure_id, _) => { // thing being captured is itself an upvar: let outer_upvar_id = ty::UpvarId { var_id: var_id, @@ -1475,7 +1473,6 @@ fn link_region(rcx: &Rcx, mc::cat_static_item | mc::cat_copied_upvar(..) | mc::cat_local(..) | - mc::cat_arg(..) | mc::cat_upvar(..) | mc::cat_rvalue(..) => { // These are all "base cases" with independent lifetimes @@ -1701,7 +1698,6 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx, mc::cat_rvalue(_) | mc::cat_copied_upvar(_) | mc::cat_local(_) | - mc::cat_arg(_) | mc::cat_upvar(..) => { return; } @@ -1753,7 +1749,6 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) { mc::cat_rvalue(_) | mc::cat_copied_upvar(_) | mc::cat_local(_) | - mc::cat_arg(_) | mc::cat_upvar(..) => { return; } diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index c0236cefca3f9..29cd2e77e8b1f 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -22,7 +22,6 @@ use driver::diagnostic; use driver::diagnostic::Emitter; use driver::driver; use driver::session; -use middle::freevars; use middle::lang_items; use middle::region; use middle::resolve; @@ -125,10 +124,8 @@ fn test_env(_test_name: &str, // run just enough stuff to build a tcx: let lang_items = lang_items::collect_language_items(krate, &sess); - let resolve::CrateMap { def_map: def_map, .. } = + let resolve::CrateMap { def_map, freevars, capture_mode_map, .. } = resolve::resolve_crate(&sess, &lang_items, krate); - let (freevars_map, captures_map) = freevars::annotate_freevars(&def_map, - krate); let named_region_map = resolve_lifetime::krate(&sess, krate); let region_map = region::resolve_crate(&sess, krate); let stability_index = stability::Index::build(krate); @@ -138,8 +135,8 @@ fn test_env(_test_name: &str, def_map, named_region_map, ast_map, - freevars_map, - captures_map, + freevars, + capture_mode_map, region_map, lang_items, stability_index);