diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 802fb05796d66..257fbf1ef1ac9 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -116,7 +116,10 @@ pub fn parse_config(args: Vec ) -> Config { } fn opt_path(m: &getopts::Matches, nm: &str) -> Path { - Path::new(m.opt_str(nm).unwrap()) + match m.opt_str(nm) { + Some(s) => Path::new(s), + None => panic!("no option (=path) found for {}", nm), + } } let filter = if !matches.free.is_empty() { diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs index 9605536a052c0..84f9a70b3e483 100644 --- a/src/libregex/vm.rs +++ b/src/libregex/vm.rs @@ -120,8 +120,10 @@ impl<'r, 't> Nfa<'r, 't> { }; let mut matched = false; let ninsts = self.prog.insts.len(); - let mut clist = &mut Threads::new(self.which, ninsts, ncaps); - let mut nlist = &mut Threads::new(self.which, ninsts, ncaps); + let mut cthread = Threads::new(self.which, ninsts, ncaps); + let mut nthread = Threads::new(self.which, ninsts, ncaps); + let mut clist = &mut cthread; + let mut nlist = &mut nthread; let mut groups: Vec<_> = repeat(None).take(ncaps * 2).collect(); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 5aacaa04e46d0..428a7f23466fe 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -390,6 +390,18 @@ fn parse_scope(st: &mut PState) -> region::CodeExtent { let node_id = parse_uint(st) as ast::NodeId; region::CodeExtent::Misc(node_id) } + 'D' => { + let node_id = parse_uint(st) as ast::NodeId; + region::CodeExtent::DestructionScope(node_id) + } + 'B' => { + let node_id = parse_uint(st) as ast::NodeId; + let first_stmt_index = parse_uint(st); + let block_remainder = region::BlockRemainder { + block: node_id, first_statement_index: first_stmt_index, + }; + region::CodeExtent::Remainder(block_remainder) + } _ => panic!("parse_scope: bad input") } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index bdd08ad6c4952..40331d407a3fc 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -276,7 +276,10 @@ pub fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) { fn enc_scope(w: &mut SeekableMemWriter, _cx: &ctxt, scope: region::CodeExtent) { match scope { - region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id) + region::CodeExtent::Misc(node_id) => mywrite!(w, "M{}", node_id), + region::CodeExtent::Remainder(region::BlockRemainder { + block: b, first_statement_index: i }) => mywrite!(w, "B{}{}", b, i), + region::CodeExtent::DestructionScope(node_id) => mywrite!(w, "D{}", node_id), } } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index bbd12c9671d28..e34094ffed69d 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -242,7 +242,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { } } SubSupConflict(var_origin, _, sub_r, _, sup_r) => { - debug!("processing SubSupConflict"); + debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub_r, sup_r); match free_regions_from_same_fn(self.tcx, sub_r, sup_r) { Some(ref same_frs) => { var_origins.push(var_origin); @@ -721,6 +721,22 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { sup, ""); } + infer::SafeDestructor(span) => { + self.tcx.sess.span_err( + span, + "unsafe use of destructor: destructor might be called \ + while references are dead"); + note_and_explain_region( + self.tcx, + "superregion: ", + sup, + ""); + note_and_explain_region( + self.tcx, + "subregion: ", + sub, + ""); + } infer::BindingTypeIsNotValidAtDecl(span) => { self.tcx.sess.span_err( span, @@ -818,6 +834,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { let scope_id = same_regions[0].scope_id; let parent = self.tcx.map.get_parent(scope_id); let parent_node = self.tcx.map.find(parent); + let taken = lifetimes_in_scope(self.tcx, scope_id); + let life_giver = LifeGiver::with_taken(&taken[]); let node_inner = match parent_node { Some(ref node) => match *node { ast_map::NodeItem(ref item) => { @@ -860,8 +878,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }; let (fn_decl, generics, unsafety, ident, expl_self, span) = node_inner.expect("expect item fn"); - let taken = lifetimes_in_scope(self.tcx, scope_id); - let life_giver = LifeGiver::with_taken(&taken[]); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); @@ -1641,6 +1657,12 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { &format!("...so that the declared lifetime parameter bounds \ are satisfied")[]); } + infer::SafeDestructor(span) => { + self.tcx.sess.span_note( + span, + "...so that references are valid when the destructor \ + runs") + } } } } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 8fd44f144e1ea..153eeaa4f2c44 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -222,6 +222,9 @@ pub enum SubregionOrigin<'tcx> { // An auto-borrow that does not enclose the expr where it occurs AutoBorrow(Span), + + // Region constraint arriving from destructor safety + SafeDestructor(Span), } /// Times when we replace late-bound regions with variables: @@ -1217,6 +1220,7 @@ impl<'tcx> SubregionOrigin<'tcx> { CallReturn(a) => a, AddrOf(a) => a, AutoBorrow(a) => a, + SafeDestructor(a) => a, } } } @@ -1279,6 +1283,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> { CallReturn(a) => format!("CallReturn({})", a.repr(tcx)), AddrOf(a) => format!("AddrOf({})", a.repr(tcx)), AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)), + SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)), } } } diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 0d6ab9c273b75..3b200ccdf8d1f 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -19,12 +19,14 @@ use graphviz as dot; use middle::ty; +use middle::region::CodeExtent; use super::Constraint; use middle::infer::SubregionOrigin; use middle::infer::region_inference::RegionVarBindings; use util::nodemap::{FnvHashMap, FnvHashSet}; use util::ppaux::Repr; +use std::borrow::Cow; use std::collections::hash_map::Entry::Vacant; use std::io::{self, File}; use std::os; @@ -120,13 +122,18 @@ struct ConstraintGraph<'a, 'tcx: 'a> { node_ids: FnvHashMap, } -#[derive(Clone, Hash, PartialEq, Eq, Show)] +#[derive(Clone, Hash, PartialEq, Eq, Show, Copy)] enum Node { RegionVid(ty::RegionVid), Region(ty::Region), } -type Edge = Constraint; +// type Edge = Constraint; +#[derive(Clone, PartialEq, Eq, Show, Copy)] +enum Edge { + Constraint(Constraint), + EnclScope(CodeExtent, CodeExtent), +} impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> { fn new(tcx: &'a ty::ctxt<'tcx>, @@ -146,6 +153,11 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> { add_node(n1); add_node(n2); } + + tcx.region_maps.each_encl_scope(|&mut: sub, sup| { + add_node(Node::Region(ty::ReScope(*sub))); + add_node(Node::Region(ty::ReScope(*sup))); + }); } ConstraintGraph { tcx: tcx, @@ -160,7 +172,17 @@ impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> { dot::Id::new(self.graph_name.as_slice()).unwrap() } fn node_id(&self, n: &Node) -> dot::Id { - dot::Id::new(format!("node_{}", self.node_ids.get(n).unwrap())).unwrap() + let node_id = match self.node_ids.get(n) { + Some(node_id) => node_id, + None => panic!("no node_id found for node: {:?}", n), + }; + let name = |&:| format!("node_{}", node_id); + match dot::Id::new(name()) { + Ok(id) => id, + Err(()) => { + panic!("failed to create graphviz node identified by {}", name()); + } + } } fn node_label(&self, n: &Node) -> dot::LabelText { match *n { @@ -171,7 +193,12 @@ impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> { } } fn edge_label(&self, e: &Edge) -> dot::LabelText { - dot::LabelText::label(format!("{}", self.map.get(e).unwrap().repr(self.tcx))) + match *e { + Edge::Constraint(ref c) => + dot::LabelText::label(format!("{}", self.map.get(c).unwrap().repr(self.tcx))), + Edge::EnclScope(..) => + dot::LabelText::label(format!("(enclosed)")), + } } } @@ -186,28 +213,40 @@ fn constraint_to_nodes(c: &Constraint) -> (Node, Node) { } } +fn edge_to_nodes(e: &Edge) -> (Node, Node) { + match *e { + Edge::Constraint(ref c) => constraint_to_nodes(c), + Edge::EnclScope(sub, sup) => { + (Node::Region(ty::ReScope(sub)), Node::Region(ty::ReScope(sup))) + } + } +} + impl<'a, 'tcx> dot::GraphWalk<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> { fn nodes(&self) -> dot::Nodes { let mut set = FnvHashSet::new(); - for constraint in self.map.keys() { - let (n1, n2) = constraint_to_nodes(constraint); - set.insert(n1); - set.insert(n2); + for node in self.node_ids.keys() { + set.insert(*node); } debug!("constraint graph has {} nodes", set.len()); set.into_iter().collect() } fn edges(&self) -> dot::Edges { debug!("constraint graph has {} edges", self.map.len()); - self.map.keys().map(|e|*e).collect() + let mut v : Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect(); + self.tcx.region_maps.each_encl_scope(|&mut: sub, sup| { + v.push(Edge::EnclScope(*sub, *sup)) + }); + debug!("region graph has {} edges", v.len()); + Cow::Owned(v) } fn source(&self, edge: &Edge) -> Node { - let (n1, _) = constraint_to_nodes(edge); + let (n1, _) = edge_to_nodes(edge); debug!("edge {:?} has source {:?}", edge, n1); n1 } fn target(&self, edge: &Edge) -> Node { - let (_, n2) = constraint_to_nodes(edge); + let (_, n2) = edge_to_nodes(edge); debug!("edge {:?} has target {:?}", edge, n2); n2 } diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index d54d0ae87aec0..23e896f2e7637 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -1398,6 +1398,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { for upper_bound in upper_bounds.iter() { if !self.is_subregion_of(lower_bound.region, upper_bound.region) { + debug!("pushing SubSupConflict sub: {:?} sup: {:?}", + lower_bound.region, upper_bound.region); errors.push(SubSupConflict( (*self.var_origins.borrow())[node_idx.index as uint].clone(), lower_bound.origin.clone(), diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 1b1dca004228e..d9a2ec4d423f8 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1535,7 +1535,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let fn_ret = ty::liberate_late_bound_regions( self.ir.tcx, - CodeExtent::from_node_id(body.id), + CodeExtent::DestructionScope(body.id), &self.fn_ret(id)); match fn_ret { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 51ec75284326c..2a057cc1acd2c 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -690,7 +690,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { // Region of environment pointer let env_region = ty::ReFree(ty::FreeRegion { - scope: region::CodeExtent::from_node_id(fn_body_id), + // The environment of a closure is guaranteed to + // outlive any bindings introduced in the body of the + // closure itself. + scope: region::CodeExtent::DestructionScope(fn_body_id), bound_region: ty::BrEnv }); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 5d33a7efd3bee..02d44092b3566 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -27,6 +27,7 @@ use syntax::codemap::Span; use syntax::{ast, visit}; use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local}; use syntax::ast_util::{stmt_id}; +use syntax::ptr::P; use syntax::visit::{Visitor, FnKind}; /// CodeExtent represents a statically-describable extent that can be @@ -39,7 +40,33 @@ use syntax::visit::{Visitor, FnKind}; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Show, Copy)] pub enum CodeExtent { - Misc(ast::NodeId) + Misc(ast::NodeId), + DestructionScope(ast::NodeId), // extent of destructors for temporaries of node-id + Remainder(BlockRemainder) +} + +/// Represents a subscope of `block` for a binding that is introduced +/// by `block.stmts[first_statement_index]`. Such subscopes represent +/// a suffix of the block. Note that each subscope does not include +/// the initializer expression, if any, for the statement indexed by +/// `first_statement_index`. +/// +/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`: +/// +/// * the subscope with `first_statement_index == 0` is scope of both +/// `a` and `b`; it does not include EXPR_1, but does include +/// everything after that first `let`. (If you want a scope that +/// includes EXPR_1 as well, then do not use `CodeExtent::Remainder`, +/// but instead another `CodeExtent` that encompasses the whole block, +/// e.g. `CodeExtent::Misc`. +/// +/// * the subscope with `first_statement_index == 1` is scope of `c`, +/// and thus does not include EXPR_2, but covers the `...`. +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, + RustcDecodable, Show, Copy)] +pub struct BlockRemainder { + pub block: ast::NodeId, + pub first_statement_index: uint, } impl CodeExtent { @@ -56,6 +83,8 @@ impl CodeExtent { pub fn node_id(&self) -> ast::NodeId { match *self { CodeExtent::Misc(node_id) => node_id, + CodeExtent::Remainder(br) => br.block, + CodeExtent::DestructionScope(node_id) => node_id, } } @@ -66,6 +95,10 @@ impl CodeExtent { { match *self { CodeExtent::Misc(node_id) => CodeExtent::Misc(f_id(node_id)), + CodeExtent::Remainder(br) => + CodeExtent::Remainder(BlockRemainder { block: f_id(br.block), ..br }), + CodeExtent::DestructionScope(node_id) => + CodeExtent::DestructionScope(f_id(node_id)), } } } @@ -75,7 +108,8 @@ impl CodeExtent { /// - `scope_map` maps from a scope id to the enclosing scope id; this is /// usually corresponding to the lexical nesting, though in the case of /// closures the parent scope is the innermost conditional expression or repeating -/// block +/// block. (Note that the enclosing scope id for the block +/// associated with a closure is the closure itself.) /// /// - `var_map` maps from a variable or binding id to the block in which /// that variable is declared. @@ -116,12 +150,77 @@ pub struct RegionMaps { terminating_scopes: RefCell>, } -#[derive(Copy)] +/// Carries the node id for the innermost block or match expression, +/// for building up the `var_map` which maps ids to the blocks in +/// which they were declared. +#[derive(PartialEq, Eq, Show, Copy)] +enum InnermostDeclaringBlock { + None, + Block(ast::NodeId), + Statement(DeclaringStatementContext), + Match(ast::NodeId), +} + +impl InnermostDeclaringBlock { + fn to_code_extent(&self) -> Option { + let extent = match *self { + InnermostDeclaringBlock::None => { + return Option::None; + } + InnermostDeclaringBlock::Block(id) | + InnermostDeclaringBlock::Match(id) => CodeExtent::from_node_id(id), + InnermostDeclaringBlock::Statement(s) => s.to_code_extent(), + }; + Option::Some(extent) + } +} + +/// Contextual information for declarations introduced by a statement +/// (i.e. `let`). It carries node-id's for statement and enclosing +/// block both, as well as the statement's index within the block. +#[derive(PartialEq, Eq, Show, Copy)] +struct DeclaringStatementContext { + stmt_id: ast::NodeId, + block_id: ast::NodeId, + stmt_index: uint, +} + +impl DeclaringStatementContext { + fn to_code_extent(&self) -> CodeExtent { + CodeExtent::Remainder(BlockRemainder { + block: self.block_id, + first_statement_index: self.stmt_index, + }) + } +} + +#[derive(PartialEq, Eq, Show, Copy)] +enum InnermostEnclosingExpr { + None, + Some(ast::NodeId), + Statement(DeclaringStatementContext), +} + +impl InnermostEnclosingExpr { + fn to_code_extent(&self) -> Option { + let extent = match *self { + InnermostEnclosingExpr::None => { + return Option::None; + } + InnermostEnclosingExpr::Statement(s) => + s.to_code_extent(), + InnermostEnclosingExpr::Some(parent_id) => + CodeExtent::from_node_id(parent_id), + }; + Some(extent) + } +} + +#[derive(Show, Copy)] pub struct Context { - var_parent: Option, + var_parent: InnermostDeclaringBlock, - // Innermost enclosing expression - parent: Option, + parent: InnermostEnclosingExpr, } struct RegionResolutionVisitor<'a> { @@ -135,6 +234,33 @@ struct RegionResolutionVisitor<'a> { impl RegionMaps { + pub fn each_encl_scope(&self, mut e:E) where E: FnMut(&CodeExtent, &CodeExtent) { + for (child, parent) in self.scope_map.borrow().iter() { + e(child, parent) + } + } + pub fn each_var_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExtent) { + for (child, parent) in self.var_map.borrow().iter() { + e(child, parent) + } + } + pub fn each_encl_free_region(&self, mut e:E) where E: FnMut(&FreeRegion, &FreeRegion) { + for (child, parents) in self.free_region_map.borrow().iter() { + for parent in parents.iter() { + e(child, parent) + } + } + } + pub fn each_rvalue_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, &CodeExtent) { + for (child, parent) in self.rvalue_scopes.borrow().iter() { + e(child, parent) + } + } + pub fn each_terminating_scope(&self, mut e:E) where E: FnMut(&CodeExtent) { + for scope in self.terminating_scopes.borrow().iter() { + e(scope) + } + } pub fn relate_free_regions(&self, sub: FreeRegion, sup: FreeRegion) { match self.free_region_map.borrow_mut().get_mut(&sub) { Some(sups) => { @@ -384,15 +510,13 @@ impl RegionMaps { /// Records the current parent (if any) as the parent of `child_id`. fn record_superlifetime(visitor: &mut RegionResolutionVisitor, - child_id: ast::NodeId, + child_scope: CodeExtent, _sp: Span) { - match visitor.cx.parent { - Some(parent_id) => { - let child_scope = CodeExtent::from_node_id(child_id); - let parent_scope = CodeExtent::from_node_id(parent_id); + match visitor.cx.parent.to_code_extent() { + Option::None => {} + Option::Some(parent_scope) => { visitor.region_maps.record_encl_scope(child_scope, parent_scope); } - None => {} } } @@ -400,9 +524,8 @@ fn record_superlifetime(visitor: &mut RegionResolutionVisitor, fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, var_id: ast::NodeId, _sp: Span) { - match visitor.cx.var_parent { - Some(parent_id) => { - let parent_scope = CodeExtent::from_node_id(parent_id); + match visitor.cx.var_parent.to_code_extent() { + Some(parent_scope) => { visitor.region_maps.record_var_scope(var_id, parent_scope); } None => { @@ -416,21 +539,88 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) { debug!("resolve_block(blk.id={:?})", blk.id); - // Record the parent of this block. - record_superlifetime(visitor, blk.id, blk.span); + let prev_cx = visitor.cx; + + // If block was previously marked as a terminating scope during + // the recursive visit of its parent node in the AST, then we need + // to account for the destruction scope representing the extent of + // the destructors that run immediately after the the block itself + // completes. + let blk_scope = CodeExtent::Misc(blk.id); + if visitor.region_maps.terminating_scopes.borrow().contains(&blk_scope) { + let dtor_scope = CodeExtent::DestructionScope(blk.id); + record_superlifetime(visitor, dtor_scope, blk.span); + visitor.region_maps.record_encl_scope(blk_scope, dtor_scope); + } else { + record_superlifetime(visitor, blk_scope, blk.span); + } // We treat the tail expression in the block (if any) somewhat // differently from the statements. The issue has to do with - // temporary lifetimes. If the user writes: + // temporary lifetimes. Consider the following: + // + // quux({ + // let inner = ... (&bar()) ...; + // ... (&foo()) ... + // }, other_argument()); // - // { - // ... (&foo()) ... - // } + // Here, the tail expression evaluates to a value that will be + // assigned to `outer`. // + // Each of the statements within the block is a terminating + // scope, and thus a temporaries like the result of calling + // `bar()` in the initalizer expression for `let inner = ...;` + // will be cleaned up immediately after `let inner = ...;` + // executes. + // + // On the other hand, temporaries associated with evaluating the + // tail expression for the block are assigned lifetimes so that + // they will be cleaned up as part of the terminating scope + // *surrounding* the block expression. Here, the terminating + // scope for the block expression is the `quux(..)` call; so + // those temporaries will only be cleaned up *after* both + // `other_argument()` has run and also the call to `quux(..)` + // itself has returned. + + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::Block(blk.id), + parent: InnermostEnclosingExpr::Some(blk.id) + }; + + { + // This block should be kept approximately in sync with + // `visit::walk_block`. (We manually walk the block, rather + // than call `walk_block`, in order to maintain precise + // `InnermostDeclaringBlock` information.) + + for view_item in blk.view_items.iter() { + visitor.visit_view_item(view_item) + } + for (i, statement) in blk.stmts.iter().enumerate() { + if let ast::StmtDecl(_, stmt_id) = statement.node { + // Each StmtDecl introduces a subscope for bindings + // introduced by the declaration; this subscope covers + // a suffix of the block . Each subscope in a block + // has the previous subscope in the block as a parent, + // except for the first such subscope, which has the + // block itself as a parent. + let declaring = DeclaringStatementContext { + stmt_id: stmt_id, + block_id: blk.id, + stmt_index: i, + }; + record_superlifetime( + visitor, declaring.to_code_extent(), statement.span); + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::Statement(declaring), + parent: InnermostEnclosingExpr::Statement(declaring), + }; + } + visitor.visit_stmt(&**statement) + } + visit::walk_expr_opt(visitor, &blk.expr) + } - let prev_cx = visitor.cx; - visitor.cx = Context {var_parent: Some(blk.id), parent: Some(blk.id)}; - visit::walk_block(visitor, blk); visitor.cx = prev_cx; } @@ -450,7 +640,7 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) { } fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &ast::Pat) { - record_superlifetime(visitor, pat.id, pat.span); + record_superlifetime(visitor, CodeExtent::from_node_id(pat.id), pat.span); // If this is a binding (or maybe a binding, I'm too lazy to check // the def map) then record the lifetime of that binding. @@ -469,11 +659,19 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) { debug!("resolve_stmt(stmt.id={:?})", stmt_id); let stmt_scope = CodeExtent::from_node_id(stmt_id); + + // Every statement will clean up the temporaries created during + // execution of that statement. Therefore each statement has an + // associated destruction scope that represents the extent of the + // statement plus its destructors, and thus the extent for which + // regions referenced by the destructors need to survive. visitor.region_maps.mark_as_terminating_scope(stmt_scope); - record_superlifetime(visitor, stmt_id, stmt.span); + let dtor_scope = CodeExtent::DestructionScope(stmt_id); + visitor.region_maps.record_encl_scope(stmt_scope, dtor_scope); + record_superlifetime(visitor, dtor_scope, stmt.span); let prev_parent = visitor.cx.parent; - visitor.cx.parent = Some(stmt_id); + visitor.cx.parent = InnermostEnclosingExpr::Some(stmt_id); visit::walk_stmt(visitor, stmt); visitor.cx.parent = prev_parent; } @@ -481,15 +679,30 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &ast::Stmt) { fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { debug!("resolve_expr(expr.id={:?})", expr.id); - record_superlifetime(visitor, expr.id, expr.span); + // If expr was previously marked as a terminating scope during the + // recursive visit of its parent node in the AST, then we need to + // account for the destruction scope representing the extent of + // the destructors that run immediately after the the expression + // itself completes. + let expr_scope = CodeExtent::Misc(expr.id); + if visitor.region_maps.terminating_scopes.borrow().contains(&expr_scope) { + let dtor_scope = CodeExtent::DestructionScope(expr.id); + record_superlifetime(visitor, dtor_scope, expr.span); + visitor.region_maps.record_encl_scope(expr_scope, dtor_scope); + } else { + record_superlifetime(visitor, expr_scope, expr.span); + } let prev_cx = visitor.cx; - visitor.cx.parent = Some(expr.id); - + visitor.cx.parent = InnermostEnclosingExpr::Some(expr.id); { let region_maps = &mut visitor.region_maps; - let terminating = |&: id| { - let scope = CodeExtent::from_node_id(id); + let terminating = |&: e: &P| { + let scope = CodeExtent::from_node_id(e.id); + region_maps.mark_as_terminating_scope(scope) + }; + let terminating_block = |&: b: &P| { + let scope = CodeExtent::from_node_id(b.id); region_maps.mark_as_terminating_scope(scope) }; match expr.node { @@ -501,38 +714,38 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) { ast::ExprBinary(ast::BiOr, _, ref r) => { // For shortcircuiting operators, mark the RHS as a terminating // scope since it only executes conditionally. - terminating(r.id); + terminating(r); } ast::ExprIf(_, ref then, Some(ref otherwise)) => { - terminating(then.id); - terminating(otherwise.id); + terminating_block(then); + terminating(otherwise); } ast::ExprIf(ref expr, ref then, None) => { - terminating(expr.id); - terminating(then.id); + terminating(expr); + terminating_block(then); } ast::ExprLoop(ref body, _) => { - terminating(body.id); + terminating_block(body); } ast::ExprWhile(ref expr, ref body, _) => { - terminating(expr.id); - terminating(body.id); + terminating(expr); + terminating_block(body); } ast::ExprForLoop(ref _pat, ref _head, ref body, _) => { - terminating(body.id); + terminating_block(body); // The variable parent of everything inside (most importantly, the // pattern) is the body. - visitor.cx.var_parent = Some(body.id); + visitor.cx.var_parent = InnermostDeclaringBlock::Block(body.id); } ast::ExprMatch(..) => { - visitor.cx.var_parent = Some(expr.id); + visitor.cx.var_parent = InnermostDeclaringBlock::Match(expr.id); } ast::ExprAssignOp(..) | ast::ExprIndex(..) | @@ -569,19 +782,13 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { debug!("resolve_local(local.id={:?},local.init={:?})", local.id,local.init.is_some()); - let blk_id = match visitor.cx.var_parent { - Some(id) => id, - None => { - visitor.sess.span_bug( - local.span, - "local without enclosing block"); - } - }; - // For convenience in trans, associate with the local-id the var // scope that will be used for any bindings declared in this // pattern. - let blk_scope = CodeExtent::from_node_id(blk_id); + let blk_scope = visitor.cx.var_parent.to_code_extent() + .unwrap_or_else(|| visitor.sess.span_bug( + local.span, "local without enclosing block")); + visitor.region_maps.record_var_scope(local.id, blk_scope); // As an exception to the normal rules governing temporary @@ -804,7 +1011,10 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) { fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) { // Items create a new outer block scope as far as we're concerned. let prev_cx = visitor.cx; - visitor.cx = Context {var_parent: None, parent: None}; + visitor.cx = Context { + var_parent: InnermostDeclaringBlock::None, + parent: InnermostEnclosingExpr::None + }; visit::walk_item(visitor, item); visitor.cx = prev_cx; } @@ -826,19 +1036,27 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, let body_scope = CodeExtent::from_node_id(body.id); visitor.region_maps.mark_as_terminating_scope(body_scope); + let dtor_scope = CodeExtent::DestructionScope(body.id); + visitor.region_maps.record_encl_scope(body_scope, dtor_scope); + record_superlifetime(visitor, dtor_scope, body.span); let outer_cx = visitor.cx; // The arguments and `self` are parented to the body of the fn. - visitor.cx = Context { parent: Some(body.id), - var_parent: Some(body.id) }; + visitor.cx = Context { + parent: InnermostEnclosingExpr::Some(body.id), + var_parent: InnermostDeclaringBlock::Block(body.id) + }; visit::walk_fn_decl(visitor, decl); // The body of the fn itself is either a root scope (top-level fn) // or it continues with the inherited scope (closures). match fk { visit::FkItemFn(..) | visit::FkMethod(..) => { - visitor.cx = Context { parent: None, var_parent: None }; + visitor.cx = Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None + }; visitor.visit_block(body); visitor.cx = outer_cx; } @@ -899,7 +1117,10 @@ pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps { let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: &maps, - cx: Context { parent: None, var_parent: None } + cx: Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None, + } }; visit::walk_crate(&mut visitor, krate); } @@ -912,7 +1133,10 @@ pub fn resolve_inlined_item(sess: &Session, let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: region_maps, - cx: Context { parent: None, var_parent: None } + cx: Context { + parent: InnermostEnclosingExpr::None, + var_parent: InnermostDeclaringBlock::None + } }; visit::walk_inlined_item(&mut visitor, item); } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index b670099ff962a..bdac477f5d9c6 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -20,7 +20,7 @@ use self::ScopeChain::*; use session::Session; use middle::def::{self, DefMap}; -use middle::region; +use middle::region::{self, CodeExtent}; use middle::subst; use middle::ty; use std::fmt; @@ -354,6 +354,10 @@ impl<'a> LifetimeContext<'a> { scope_data: region::CodeExtent, lifetime_ref: &ast::Lifetime, scope: Scope) { + debug!("resolve_free_lifetime_ref \ + scope_data: {:?} lifetime_ref: {:?} scope: {:?}", + scope_data, lifetime_ref, scope); + // Walk up the scope chain, tracking the outermost free scope, // until we encounter a scope that contains the named lifetime // or we run out of scopes. @@ -361,6 +365,9 @@ impl<'a> LifetimeContext<'a> { let mut scope = scope; let mut search_result = None; loop { + debug!("resolve_free_lifetime_ref \ + scope_data: {:?} scope: {:?} search_result: {:?}", + scope_data, scope, search_result); match *scope { BlockScope(blk_scope_data, s) => { scope_data = blk_scope_data; @@ -382,6 +389,14 @@ impl<'a> LifetimeContext<'a> { } } + // The free region in fact outlives not just the outermost + // scope, but also its corresponding DestructionScope. + let scope_data = if let CodeExtent::Misc(node_id) = scope_data { + CodeExtent::DestructionScope(node_id) + } else { + self.sess.bug("unexpected extent in resolve_free_lifetime_ref"); + }; + match search_result { Some((_depth, lifetime)) => { let def = DefFreeRegion(scope_data, lifetime.id); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index cf30969ebefcc..164cb7c3c80a3 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1184,7 +1184,9 @@ pub enum Region { /// region parameters. ReFree(FreeRegion), - /// A concrete region naming some expression within the current function. + /// A concrete region naming some statically determined extent + /// (e.g. an expression or sequence of statements) within the + /// current function. ReScope(region::CodeExtent), /// Static data that has an "infinite" lifetime. Top in the region lattice. @@ -4233,12 +4235,15 @@ pub fn ty_region(tcx: &ctxt, } } -pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef) +pub fn free_region_from_def(outlives_extent: region::CodeExtent, def: &RegionParameterDef) -> ty::Region { - ty::ReFree(ty::FreeRegion { scope: region::CodeExtent::from_node_id(free_id), - bound_region: ty::BrNamed(def.def_id, - def.name) }) + let ret = + ty::ReFree(ty::FreeRegion { scope: outlives_extent, + bound_region: ty::BrNamed(def.def_id, + def.name) }); + debug!("free_region_from_def returns {:?}", ret); + ret } // Returns the type of a pattern as a monotype. Like @expr_ty, this function @@ -6354,23 +6359,23 @@ pub fn construct_parameter_environment<'a,'tcx>( let mut types = VecPerParamSpace::empty(); push_types_from_defs(tcx, &mut types, generics.types.as_slice()); + let free_id_outlive = region::CodeExtent::DestructionScope(free_id); + // map bound 'a => free 'a let mut regions = VecPerParamSpace::empty(); - push_region_params(&mut regions, free_id, generics.regions.as_slice()); + push_region_params(&mut regions, free_id_outlive, generics.regions.as_slice()); let free_substs = Substs { types: types, regions: subst::NonerasedRegions(regions) }; - let free_id_scope = region::CodeExtent::from_node_id(free_id); - // // Compute the bounds on Self and the type parameters. // let bounds = generics.to_bounds(tcx, &free_substs); - let bounds = liberate_late_bound_regions(tcx, free_id_scope, &ty::Binder(bounds)); + let bounds = liberate_late_bound_regions(tcx, free_id_outlive, &ty::Binder(bounds)); // // Compute region bounds. For now, these relations are stored in a @@ -6388,17 +6393,17 @@ pub fn construct_parameter_environment<'a,'tcx>( return ty::ParameterEnvironment { tcx: tcx, free_substs: free_substs, - implicit_region_bound: ty::ReScope(free_id_scope), + implicit_region_bound: ty::ReScope(free_id_outlive), caller_bounds: bounds, selection_cache: traits::SelectionCache::new(), }; fn push_region_params(regions: &mut VecPerParamSpace, - free_id: ast::NodeId, + all_outlive_extent: region::CodeExtent, region_params: &[RegionParameterDef]) { for r in region_params.iter() { - regions.push(r.space, ty::free_region_from_def(free_id, r)); + regions.push(r.space, ty::free_region_from_def(all_outlive_extent, r)); } } @@ -6679,14 +6684,14 @@ impl<'tcx> AutoDerefRef<'tcx> { /// `scope_id`. pub fn liberate_late_bound_regions<'tcx, T>( tcx: &ty::ctxt<'tcx>, - scope: region::CodeExtent, + all_outlive_scope: region::CodeExtent, value: &Binder) -> T where T : TypeFoldable<'tcx> + Repr<'tcx> { replace_late_bound_regions( tcx, value, - |br| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0 + |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0 } pub fn count_late_bound_regions<'tcx, T>( diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 559ec533baa9e..3754e6648f716 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,6 +10,7 @@ use middle::def; +use middle::region; use middle::subst::{VecPerParamSpace,Subst}; use middle::subst; use middle::ty::{BoundRegion, BrAnon, BrNamed}; @@ -902,11 +903,24 @@ impl<'tcx> UserString<'tcx> for ty::Region { impl<'tcx> Repr<'tcx> for ty::FreeRegion { fn repr(&self, tcx: &ctxt) -> String { format!("ReFree({}, {})", - self.scope.node_id(), + self.scope.repr(tcx), self.bound_region.repr(tcx)) } } +impl<'tcx> Repr<'tcx> for region::CodeExtent { + fn repr(&self, _tcx: &ctxt) -> String { + match *self { + region::CodeExtent::Misc(node_id) => + format!("Misc({})", node_id), + region::CodeExtent::DestructionScope(node_id) => + format!("DestructionScope({})", node_id), + region::CodeExtent::Remainder(rem) => + format!("Remainder({}, {})", rem.block, rem.first_statement_index), + } + } +} + impl<'tcx> Repr<'tcx> for ast::DefId { fn repr(&self, tcx: &ctxt) -> String { // Unfortunately, there seems to be no way to attempt to print diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f35f8ab1b40f5..1ec77eb206920 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -99,11 +99,11 @@ pub fn compile_input(sess: Session, &id[])); let mut forest = ast_map::Forest::new(expanded_crate); + let arenas = ty::CtxtArenas::new(); let ast_map = assign_node_ids_and_map(&sess, &mut forest); write_out_deps(&sess, input, &outputs, &id[]); - let arenas = ty::CtxtArenas::new(); let analysis = phase_3_run_analysis_passes(sess, ast_map, &arenas, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ea6ecfbb92b4f..dc557e1062f81 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1031,7 +1031,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - for (_, child_module) in module_.anonymous_children.borrow().iter() { + let children = module_.anonymous_children.borrow(); + for (_, child_module) in children.iter() { self.resolve_imports_for_module_subtree(child_module.clone()); } } @@ -2203,7 +2204,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Search for external modules. if namespace == TypeNS { - if let Some(module) = module_.external_module_children.borrow().get(&name).cloned() { + let child = module_.external_module_children.borrow().get(&name).cloned(); + if let Some(module) = child { let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); debug!("lower name bindings succeeded"); @@ -2485,7 +2487,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Finally, search through external children. if namespace == TypeNS { - if let Some(module) = module_.external_module_children.borrow().get(&name).cloned() { + let child = module_.external_module_children.borrow().get(&name).cloned(); + if let Some(module) = child { let name_bindings = Rc::new(Resolver::create_name_bindings_from_module(module)); return Success((Target::new(module_, @@ -2534,7 +2537,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - for (_, module_) in module_.anonymous_children.borrow().iter() { + let children = module_.anonymous_children.borrow(); + for (_, module_) in children.iter() { self.report_unresolved_imports(module_.clone()); } } diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs index 67bcf152eb78c..eb3127891d84f 100644 --- a/src/librustc_resolve/record_exports.rs +++ b/src/librustc_resolve/record_exports.rs @@ -91,7 +91,8 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> { } } - for (_, child_module) in module_.anonymous_children.borrow().iter() { + let children = module_.anonymous_children.borrow(); + for (_, child_module) in children.iter() { self.record_exports_for_module_subtree(child_module.clone()); } } diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index fc19a582db2f5..0d603a5c9c818 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -269,7 +269,7 @@ impl<'a, 'tcx> Opt<'a, 'tcx> { } } - fn trans<'blk>(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> { + fn trans<'fcx, 'blk>(&self, mut bcx: Block<'fcx, 'blk, 'tcx>) -> OptResult<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::trans_opt"); let ccx = bcx.ccx(); match *self { @@ -307,10 +307,10 @@ pub enum BranchKind { CompareSliceLength } -pub enum OptResult<'blk, 'tcx: 'blk> { - SingleResult(Result<'blk, 'tcx>), - RangeResult(Result<'blk, 'tcx>, Result<'blk, 'tcx>), - LowerBound(Result<'blk, 'tcx>) +pub enum OptResult<'fcx, 'blk: 'fcx, 'tcx: 'blk> { + SingleResult(Result<'fcx, 'blk, 'tcx>), + RangeResult(Result<'fcx, 'blk, 'tcx>, Result<'fcx, 'blk, 'tcx>), + LowerBound(Result<'fcx, 'blk, 'tcx>) } #[derive(Clone, Copy)] @@ -338,8 +338,8 @@ pub struct BindingInfo<'tcx> { type BindingsMap<'tcx> = FnvHashMap>; -struct ArmData<'p, 'blk, 'tcx: 'blk> { - bodycx: Block<'blk, 'tcx>, +struct ArmData<'p, 'fcx, 'blk: 'fcx, 'tcx: 'blk> { + bodycx: Block<'fcx, 'blk, 'tcx>, arm: &'p ast::Arm, bindings_map: BindingsMap<'tcx> } @@ -348,13 +348,13 @@ struct ArmData<'p, 'blk, 'tcx: 'blk> { /// If all `pats` are matched then arm `data` will be executed. /// As we proceed `bound_ptrs` are filled with pointers to values to be bound, /// these pointers are stored in llmatch variables just before executing `data` arm. -struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> { +struct Match<'a, 'p: 'a, 'fcx: 'a, 'blk: 'fcx, 'tcx: 'blk> { pats: Vec<&'p ast::Pat>, - data: &'a ArmData<'p, 'blk, 'tcx>, + data: &'a ArmData<'p, 'fcx, 'blk, 'tcx>, bound_ptrs: Vec<(Ident, ValueRef)>, } -impl<'a, 'p, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'blk, 'tcx> { +impl<'a, 'p, 'fcx, 'blk, 'tcx> Repr<'tcx> for Match<'a, 'p, 'fcx, 'blk, 'tcx> { fn repr(&self, tcx: &ty::ctxt) -> String { if tcx.sess.verbose() { // for many programs, this just take too long to serialize @@ -375,11 +375,11 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool { return false; } -fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], +fn expand_nested_bindings<'a, 'p, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], col: uint, val: ValueRef) - -> Vec> { + -> Vec> { debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})", bcx.to_str(), m.repr(bcx.tcx()), @@ -410,13 +410,13 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }).collect() } -fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +fn enter_match<'a, 'b, 'p, 'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, dm: &DefMap, - m: &[Match<'a, 'p, 'blk, 'tcx>], + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], col: uint, val: ValueRef, mut e: F) - -> Vec> where + -> Vec> where F: FnMut(&[&'p ast::Pat]) -> Option>, { debug!("enter_match(bcx={}, m={}, col={}, val={})", @@ -455,12 +455,12 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }).collect() } -fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn enter_default<'a, 'p, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, dm: &DefMap, - m: &[Match<'a, 'p, 'blk, 'tcx>], + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], col: uint, val: ValueRef) - -> Vec> { + -> Vec> { debug!("enter_default(bcx={}, m={}, col={}, val={})", bcx.to_str(), m.repr(bcx.tcx()), @@ -508,16 +508,16 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// takes the complete row of patterns rather than just the first one. /// Also, most of the enter_() family functions have been unified with /// the check_match specialization step. -fn enter_opt<'a, 'p, 'blk, 'tcx>( - bcx: Block<'blk, 'tcx>, +fn enter_opt<'a, 'p, 'fcx, 'blk, 'tcx>( + bcx: Block<'fcx, 'blk, 'tcx>, _: ast::NodeId, dm: &DefMap, - m: &[Match<'a, 'p, 'blk, 'tcx>], + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], opt: &Opt, col: uint, variant_size: uint, val: ValueRef) - -> Vec> { + -> Vec> { debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})", bcx.to_str(), m.repr(bcx.tcx()), @@ -555,8 +555,8 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( // Returns the options in one column of matches. An option is something that // needs to be conditionally matched at runtime; for example, the discriminant // on a set of enum variants or a literal. -fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], col: uint) +fn get_branches<'a, 'p, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], col: uint) -> Vec> { let tcx = bcx.tcx(); @@ -595,16 +595,16 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, found } -struct ExtractedBlock<'blk, 'tcx: 'blk> { +struct ExtractedBlock<'fcx, 'blk: 'fcx, 'tcx: 'blk> { vals: Vec, - bcx: Block<'blk, 'tcx>, + bcx: Block<'fcx, 'blk, 'tcx>, } -fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn extract_variant_args<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, repr: &adt::Repr<'tcx>, disr_val: ty::Disr, val: ValueRef) - -> ExtractedBlock<'blk, 'tcx> { + -> ExtractedBlock<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::extract_variant_args"); let args = range(0, adt::num_args(repr, disr_val)).map(|i| { adt::trans_field_ptr(bcx, repr, val, disr_val, i) @@ -644,12 +644,12 @@ fn bind_subslice_pat(bcx: Block, scratch.val } -fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn extract_vec_elems<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, left_ty: Ty, before: uint, after: uint, val: ValueRef) - -> ExtractedBlock<'blk, 'tcx> { + -> ExtractedBlock<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::extract_vec_elems"); let vec_datum = match_datum(val, left_ty); let (base, len) = vec_datum.get_vec_base_and_len(bcx); @@ -777,16 +777,16 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option { } // Compiles a comparison between two things. -fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +fn compare_values<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, rhs_t: Ty<'tcx>) - -> Result<'blk, 'tcx> { - fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>, + -> Result<'fcx, 'blk, 'tcx> { + fn compare_str<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, rhs_t: Ty<'tcx>) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let did = langcall(cx, None, &format!("comparison of `{}`", @@ -824,10 +824,10 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, } /// For each binding in `data.bindings_map`, adds an appropriate entry into the `fcx.lllocals` map -fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +fn insert_lllocals<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, bindings_map: &BindingsMap<'tcx>, cs: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { for (&ident, &binding_info) in bindings_map.iter() { let llval = match binding_info.trmode { // By value mut binding for a copy type: load from the ptr @@ -871,14 +871,14 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, bcx } -fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn compile_guard<'a, 'p, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, guard_expr: &ast::Expr, - data: &ArmData<'p, 'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], + data: &ArmData<'p, 'fcx, 'blk, 'tcx>, + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], vals: &[ValueRef], chk: &FailureHandler, has_genuine_default: bool) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})", bcx.to_str(), bcx.expr_to_string(guard_expr), @@ -918,8 +918,8 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }) } -fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], +fn compile_submatch<'a, 'p, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], vals: &[ValueRef], chk: &FailureHandler, has_genuine_default: bool) { @@ -974,13 +974,13 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } _ => () } - Br(bcx, data.bodycx.llbb); + Br(bcx, data.bodycx.data.llbb); } } } -fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, - m: &[Match<'a, 'p, 'blk, 'tcx>], +fn compile_submatch_continue<'a, 'p, 'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, + m: &[Match<'a, 'p, 'fcx, 'blk, 'tcx>], vals: &[ValueRef], chk: &FailureHandler, col: uint, @@ -1084,7 +1084,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => bcx.fcx.new_temp_block("match_else") }; let sw = if kind == Switch { - build::Switch(bcx, test_val, else_cx.llbb, opts.len()) + build::Switch(bcx, test_val, else_cx.data.llbb, opts.len()) } else { C_int(ccx, 0i) // Placeholder for when not using a switch }; @@ -1104,11 +1104,11 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, if !exhaustive || i + 1 < len { opt_cx = bcx.fcx.new_temp_block("match_case"); match kind { - Single => Br(bcx, opt_cx.llbb), + Single => Br(bcx, opt_cx.data.llbb), Switch => { match opt.trans(bcx) { SingleResult(r) => { - AddCase(sw, r.val, opt_cx.llbb); + AddCase(sw, r.val, opt_cx.data.llbb); bcx = r.bcx; } _ => { @@ -1155,14 +1155,14 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let guarded = m[i].data.arm.guard.is_some(); let multi_pats = m[i].pats.len() > 1; if i + 1 < len && (guarded || multi_pats || kind == CompareSliceLength) { - branch_chk = Some(JumpToBasicBlock(bcx.llbb)); + branch_chk = Some(JumpToBasicBlock(bcx.data.llbb)); } - CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb); + CondBr(after_cx, matches, opt_cx.data.llbb, bcx.data.llbb); } _ => () } } else if kind == Compare || kind == CompareSliceLength { - Br(bcx, else_cx.llbb); + Br(bcx, else_cx.data.llbb); } let mut size = 0u; @@ -1202,7 +1202,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, // Compile the fall-through case, if any if !exhaustive && kind != Single { if kind == Compare || kind == CompareSliceLength { - Br(bcx, else_cx.llbb); + Br(bcx, else_cx.data.llbb); } match chk { // If there is only one default arm left, move on to the next @@ -1222,12 +1222,12 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } -pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_match<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, match_expr: &ast::Expr, discr_expr: &ast::Expr, arms: &[ast::Arm], dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::trans_match"); trans_match_inner(bcx, match_expr.id, discr_expr, arms, dest) } @@ -1262,7 +1262,7 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool reassigned: false }; { - let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx); + let mut visitor = euv::ExprUseVisitor::new(&mut rc, &bcx); visitor.walk_expr(body); } rc.reassigned @@ -1304,7 +1304,7 @@ impl<'tcx> euv::Delegate<'tcx> for ReassignmentChecker { } } -fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, +fn create_bindings_map<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, pat: &ast::Pat, discr: &ast::Expr, body: &ast::Expr) -> BindingsMap<'tcx> { // Create the bindings map, which is a mapping from each binding name @@ -1362,11 +1362,11 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat, return bindings_map; } -fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, +fn trans_match_inner<'fcx, 'blk, 'tcx>(scope_cx: Block<'fcx, 'blk, 'tcx>, match_id: ast::NodeId, discr_expr: &ast::Expr, arms: &[ast::Arm], - dest: Dest) -> Block<'blk, 'tcx> { + dest: Dest) -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::trans_match_inner"); let fcx = scope_cx.fcx; let mut bcx = scope_cx; @@ -1374,7 +1374,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, let discr_datum = unpack_datum!(bcx, expr::trans_to_lvalue(bcx, discr_expr, "match")); - if bcx.unreachable.get() { + if bcx.data.unreachable.get() { return bcx; } @@ -1435,17 +1435,17 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, /// Generates code for a local variable declaration like `let ;` or `let = /// `. -pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn store_local<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, local: &ast::Local) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::store_local"); let mut bcx = bcx; let tcx = bcx.tcx(); let pat = &*local.pat; - fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, + fn create_dummy_locals<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, pat: &ast::Pat) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { // create dummy memory for the variables if we have no // value to store into them immediately let tcx = bcx.tcx(); @@ -1507,11 +1507,11 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// - `llval` is a pointer to the argument value (in other words, /// if the argument type is `T`, then `llval` is a `T*`). In some /// cases, this code may zero out the memory `llval` points at. -pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +pub fn store_arg<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, pat: &ast::Pat, arg: Datum<'tcx, Rvalue>, arg_scope: cleanup::ScopeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::store_arg"); match simple_identifier(&*pat) { @@ -1547,11 +1547,11 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, /// Generates code for the pattern binding in a `for` loop like /// `for in { ... }`. -pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn store_for_loop_binding<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, pat: &ast::Pat, llvalue: ValueRef, body_scope: cleanup::ScopeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("match::store_for_loop_binding"); if simple_identifier(&*pat).is_some() && @@ -1570,14 +1570,15 @@ pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bind_irrefutable_pat(bcx, pat, llvalue, body_scope) } -fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, +fn mk_binding_alloca<'fcx, 'blk, 'tcx, A, F>(bcx: Block<'fcx, 'blk, 'tcx>, p_id: ast::NodeId, ident: &ast::Ident, cleanup_scope: cleanup::ScopeId, arg: A, populate: F) - -> Block<'blk, 'tcx> where - F: FnOnce(A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnOnce(A, Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) + -> Block<'fcx, 'blk, 'tcx>, { let var_ty = node_id_type(bcx, p_id); @@ -1609,11 +1610,11 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(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) -fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn bind_irrefutable_pat<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, pat: &ast::Pat, val: ValueRef, cleanup_scope: cleanup::ScopeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("bind_irrefutable_pat(bcx={}, pat={})", bcx.to_str(), pat.repr(bcx.tcx())); diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 92883371ec9db..4d6ce0fefceae 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -130,7 +130,7 @@ pub struct Struct<'tcx> { /// Convenience for `represent_type`. There should probably be more or /// these, for places in trans where the `Ty` isn't directly /// available. -pub fn represent_node<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn represent_node<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, node: ast::NodeId) -> Rc> { represent_type(bcx.ccx(), node_id_type(bcx, node)) } @@ -710,7 +710,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, /// destructuring; this may or may not involve the actual discriminant. /// /// This should ideally be less tightly tied to `_match`. -pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_switch<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr<'tcx>, scrutinee: ValueRef) -> (_match::BranchKind, Option) { match *r { @@ -727,7 +727,7 @@ pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Obtain the actual discriminant of a value. -pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, +pub fn trans_get_discr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr<'tcx>, scrutinee: ValueRef, cast_to: Option) -> ValueRef { let signed; @@ -798,8 +798,8 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) /// discriminant-like value returned by `trans_switch`. /// /// This should ideally be less tightly tied to `_match`. -pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr) - -> _match::OptResult<'blk, 'tcx> { +pub fn trans_case<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr, discr: Disr) + -> _match::OptResult<'fcx, 'blk, 'tcx> { match *r { CEnum(ity, _, _) => { _match::SingleResult(Result::new(bcx, C_integral(ll_inttype(bcx.ccx(), ity), @@ -822,7 +822,7 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr) /// Set the discriminant for a new value of the given case of the given /// representation. -pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, +pub fn trans_set_discr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef, discr: Disr) { match *r { CEnum(ity, min, max) => { @@ -892,7 +892,7 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint { } /// Access a field, at a point when the value's case is known. -pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, +pub fn trans_field_ptr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef, discr: Disr, ix: uint) -> ValueRef { // Note: if this ever needs to generate conditionals (e.g., if we // decide to do some kind of cdr-coding-like non-unique repr @@ -931,8 +931,9 @@ pub fn trans_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, } } -pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, val: ValueRef, - ix: uint, needs_cast: bool) -> ValueRef { +pub fn struct_field_ptr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + st: &Struct<'tcx>, val: ValueRef, + ix: uint, needs_cast: bool) -> ValueRef { let val = if needs_cast { let ccx = bcx.ccx(); let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::>(); @@ -945,12 +946,12 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v GEPi(bcx, val, &[0, ix]) } -pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, - r: &Repr<'tcx>, - value: ValueRef, - mut f: F) - -> Block<'blk, 'tcx> where - F: FnMut(Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'blk, 'tcx>, +pub fn fold_variants<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, + r: &Repr<'tcx>, + value: ValueRef, + mut f: F) + -> Block<'fcx, 'blk, 'tcx> where + F: FnMut(Block<'fcx, 'blk, 'tcx>, &Struct<'tcx>, ValueRef) -> Block<'fcx, 'blk, 'tcx>, { let fcx = bcx.fcx; match *r { @@ -963,7 +964,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, Unreachable(unr_cx); let discr_val = trans_get_discr(bcx, r, value, None); - let llswitch = Switch(bcx, discr_val, unr_cx.llbb, cases.len()); + let llswitch = Switch(bcx, discr_val, unr_cx.data.llbb, cases.len()); let bcx_next = fcx.new_temp_block("enum-variant-iter-next"); for (discr, case) in cases.iter().enumerate() { @@ -971,7 +972,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, &format!("enum-variant-iter-{}", &discr.to_string())[] ); let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true); - AddCase(llswitch, rhs_val, variant_cx.llbb); + AddCase(llswitch, rhs_val, variant_cx.data.llbb); let fields = case.fields.iter().map(|&ty| type_of::type_of(bcx.ccx(), ty)).collect::>(); @@ -979,7 +980,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to()); variant_cx = f(variant_cx, case, variant_value); - Br(variant_cx, bcx_next.llbb); + Br(variant_cx, bcx_next.data.llbb); } bcx_next @@ -989,9 +990,10 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } /// Access the struct drop flag, if present. -pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef) - -> datum::DatumBlock<'blk, 'tcx, datum::Expr> -{ +pub fn trans_drop_flag_ptr<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, + r: &Repr<'tcx>, + val: ValueRef) + -> datum::DatumBlock<'fcx, 'blk, 'tcx, datum::Expr> { let tcx = bcx.tcx(); let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.types.bool); match *r { diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index 9b6fa32405ffb..3b4749aad5a2e 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -25,8 +25,8 @@ use std::ffi::CString; use libc::{c_uint, c_char}; // Take an inline assembly expression and splat it out via LLVM -pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) - -> Block<'blk, 'tcx> { +pub fn trans_inline_asm<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ia: &ast::InlineAsm) + -> Block<'fcx, 'blk, 'tcx> { let fcx = bcx.fcx; let mut bcx = bcx; let mut constraints = Vec::new(); diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index ea98d6bb74e95..d854f075549a8 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -367,7 +367,7 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, // Returns a pointer to the body for the box. The box may be an opaque // box. The result will be casted to the type of body_t, if it is statically // known. -pub fn at_box_body<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn at_box_body<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, body_t: Ty<'tcx>, boxptr: ValueRef) -> ValueRef { let _icx = push_ctxt("at_box_body"); let ccx = bcx.ccx(); @@ -376,7 +376,7 @@ pub fn at_box_body<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, GEPi(bcx, boxptr, &[0u, abi::BOX_FIELD_BODY]) } -fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn require_alloc_fn<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> ast::DefId { match bcx.tcx().lang_items.require(it) { Ok(id) => id, @@ -391,12 +391,12 @@ fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // The following malloc_raw_dyn* functions allocate a box to contain // a given type, but with a potentially dynamic size. -pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn malloc_raw_dyn<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, llty_ptr: Type, info_ty: Ty<'tcx>, size: ValueRef, align: ValueRef) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("malloc_raw_exchange"); // Allocate space: @@ -559,12 +559,12 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) { #[derive(Copy)] pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, } -pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn compare_scalar_types<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, t: Ty<'tcx>, op: ast::BinOp) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let f = |&: a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op)); match t.sty { @@ -580,7 +580,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>, // A helper function to do the actual comparison of scalar values. -pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn compare_scalar_values<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, nt: scalar_type, @@ -640,8 +640,8 @@ pub fn compare_scalar_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, } } -pub fn compare_simd_types<'blk, 'tcx>( - cx: Block<'blk, 'tcx>, +pub fn compare_simd_types<'fcx, 'blk, 'tcx>( + cx: Block<'fcx, 'blk, 'tcx>, lhs: ValueRef, rhs: ValueRef, t: Ty<'tcx>, @@ -679,23 +679,23 @@ pub fn compare_simd_types<'blk, 'tcx>( } // Iterates through the elements of a structural type. -pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, +pub fn iter_structural_ty<'fcx, 'blk, 'tcx, F>(cx: Block<'fcx, 'blk, 'tcx>, av: ValueRef, t: Ty<'tcx>, mut f: F) - -> Block<'blk, 'tcx> where - F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnMut(Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("iter_structural_ty"); - fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, + fn iter_variant<'fcx, 'blk, 'tcx, F>(cx: Block<'fcx, 'blk, 'tcx>, repr: &adt::Repr<'tcx>, av: ValueRef, variant: &ty::VariantInfo<'tcx>, substs: &subst::Substs<'tcx>, f: &mut F) - -> Block<'blk, 'tcx> where - F: FnMut(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnMut(Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("iter_variant"); let tcx = cx.tcx(); @@ -780,7 +780,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, cx = f(cx, lldiscrim_a, cx.tcx().types.int); let unr_cx = fcx.new_temp_block("enum-iter-unr"); Unreachable(unr_cx); - let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, + let llswitch = Switch(cx, lldiscrim_a, unr_cx.data.llbb, n_variants); let next_cx = fcx.new_temp_block("enum-iter-next"); @@ -792,7 +792,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, []); match adt::trans_case(cx, &*repr, variant.disr_val) { _match::SingleResult(r) => { - AddCase(llswitch, r.val, variant_cx.llbb) + AddCase(llswitch, r.val, variant_cx.data.llbb) } _ => ccx.sess().unimpl("value from adt::trans_case \ in iter_structural_ty") @@ -804,7 +804,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, &**variant, substs, &mut f); - Br(variant_cx, next_cx.llbb); + Br(variant_cx, next_cx.data.llbb); } cx = next_cx; } @@ -870,14 +870,14 @@ pub fn cast_shift_rhs(op: ast::BinOp, } } -pub fn fail_if_zero_or_overflows<'blk, 'tcx>( - cx: Block<'blk, 'tcx>, +pub fn fail_if_zero_or_overflows<'fcx, 'blk, 'tcx>( + cx: Block<'fcx, 'blk, 'tcx>, span: Span, divrem: ast::BinOp, lhs: ValueRef, rhs: ValueRef, rhs_t: Ty<'tcx>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let (zero_text, overflow_text) = if divrem == ast::BiDiv { ("attempted to divide by zero", "attempted to divide with overflow") @@ -967,20 +967,20 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn invoke<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, llfn: ValueRef, llargs: &[ValueRef], fn_ty: Ty<'tcx>, call_info: Option) - -> (ValueRef, Block<'blk, 'tcx>) { + -> (ValueRef, Block<'fcx, 'blk, 'tcx>) { let _icx = push_ctxt("invoke_"); - if bcx.unreachable.get() { + if bcx.data.unreachable.get() { return (C_null(Type::i8(bcx.ccx())), bcx); } let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty); - match bcx.opt_node_id { + match bcx.data.opt_node_id { None => { debug!("invoke at ???"); } @@ -990,7 +990,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } if need_invoke(bcx) { - debug!("invoking {} at {:?}", bcx.val_to_string(llfn), bcx.llbb); + debug!("invoking {} at {:?}", bcx.val_to_string(llfn), bcx.data.llbb); for &llarg in llargs.iter() { debug!("arg: {}", bcx.val_to_string(llarg)); } @@ -1005,12 +1005,12 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llresult = Invoke(bcx, llfn, &llargs[], - normal_bcx.llbb, + normal_bcx.data.llbb, landing_pad, Some(attributes)); return (llresult, normal_bcx); } else { - debug!("calling {} at {:?}", bcx.val_to_string(llfn), bcx.llbb); + debug!("calling {} at {:?}", bcx.val_to_string(llfn), bcx.data.llbb); for &llarg in llargs.iter() { debug!("arg: {}", bcx.val_to_string(llarg)); } @@ -1031,14 +1031,14 @@ pub fn need_invoke(bcx: Block) -> bool { } // Avoid using invoke if we are already inside a landing pad. - if bcx.is_lpad { + if bcx.data.is_lpad { return false; } bcx.fcx.needs_invoke() } -pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn load_if_immediate<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>) -> ValueRef { let _icx = push_ctxt("load_if_immediate"); if type_is_immediate(cx.ccx(), t) { return load_ty(cx, v, t); } @@ -1048,8 +1048,8 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>, /// Helper for loading values from memory. Does the necessary conversion if the in-memory type /// differs from the type used for SSA values. Also handles various special cases where the type /// gives us better information about what we are loading. -pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, - ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { +pub fn load_ty<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, + ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { if type_is_zero_size(cx.ccx(), t) { C_undef(type_of::type_of(cx.ccx(), t)) } else if ty::type_is_bool(t) { @@ -1070,7 +1070,10 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, /// Helper for storing values in memory. Does the necessary conversion if the in-memory type /// differs from the type used for SSA values. -pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) { +pub fn store_ty<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, + v: ValueRef, + dst: ValueRef, + t: Ty<'tcx>) { if ty::type_is_bool(t) { Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst); } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() { @@ -1083,35 +1086,35 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t }; } -pub fn init_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, local: &ast::Local) - -> Block<'blk, 'tcx> { +pub fn init_local<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, local: &ast::Local) + -> Block<'fcx, 'blk, 'tcx> { debug!("init_local(bcx={}, local.id={})", bcx.to_str(), local.id); let _indenter = indenter(); let _icx = push_ctxt("init_local"); _match::store_local(bcx, local) } -pub fn raw_block<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, +pub fn raw_block<'fcx, 'blk, 'tcx>(fcx: &'fcx FunctionContext<'blk, 'tcx>, is_lpad: bool, llbb: BasicBlockRef) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { common::BlockS::new(llbb, is_lpad, None, fcx) } -pub fn with_cond<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +pub fn with_cond<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, f: F) - -> Block<'blk, 'tcx> where - F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnOnce(Block<'fcx, 'blk, 'tcx>) -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("with_cond"); let fcx = bcx.fcx; let next_cx = fcx.new_temp_block("next"); let cond_cx = fcx.new_temp_block("cond"); - CondBr(bcx, val, cond_cx.llbb, next_cx.llbb); + CondBr(bcx, val, cond_cx.data.llbb, next_cx.data.llbb); let after_cx = f(cond_cx); - if !after_cx.terminated.get() { - Br(after_cx, next_cx.llbb); + if !after_cx.data.terminated.get() { + Br(after_cx, next_cx.data.llbb); } next_cx } @@ -1161,7 +1164,7 @@ pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, a Call(cx, memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); } -pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn memcpy_ty<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, dst: ValueRef, src: ValueRef, t: Ty<'tcx>) { let _icx = push_ctxt("memcpy_ty"); @@ -1176,8 +1179,8 @@ pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn zero_mem<'blk, 'tcx>(cx: Block<'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) { - if cx.unreachable.get() { return; } +pub fn zero_mem<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, llptr: ValueRef, t: Ty<'tcx>) { + if cx.data.unreachable.get() { return; } let _icx = push_ctxt("zero_mem"); let bcx = cx; memzero(&B(bcx), llptr, t); @@ -1209,7 +1212,9 @@ fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) { b.call(llintrinsicfn, &[llptr, llzeroval, size, align, volatile], None); } -pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, name: &str) -> ValueRef { +pub fn alloc_ty<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + t: Ty<'tcx>, + name: &str) -> ValueRef { let _icx = push_ctxt("alloc_ty"); let ccx = bcx.ccx(); let ty = type_of::type_of(ccx, t); @@ -1226,7 +1231,7 @@ pub fn alloca(cx: Block, ty: Type, name: &str) -> ValueRef { pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef { let _icx = push_ctxt("alloca"); - if cx.unreachable.get() { + if cx.data.unreachable.get() { unsafe { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } @@ -1235,10 +1240,10 @@ pub fn alloca_no_lifetime(cx: Block, ty: Type, name: &str) -> ValueRef { Alloca(cx, ty, name) } -pub fn alloca_zeroed<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, +pub fn alloca_zeroed<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, name: &str) -> ValueRef { let llty = type_of::type_of(cx.ccx(), ty); - if cx.unreachable.get() { + if cx.data.unreachable.get() { unsafe { return llvm::LLVMGetUndef(llty.ptr_to().to_ref()); } @@ -1252,7 +1257,7 @@ pub fn alloca_zeroed<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, pub fn arrayalloca(cx: Block, ty: Type, v: ValueRef) -> ValueRef { let _icx = push_ctxt("arrayalloca"); - if cx.unreachable.get() { + if cx.data.unreachable.get() { unsafe { return llvm::LLVMGetUndef(ty.to_ref()); } @@ -1430,15 +1435,15 @@ fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bo // // Be warned! You must call `init_function` before doing anything with the // returned function context. -pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, +pub fn new_fn_ctxt<'blk, 'tcx>(ccx: &'blk CrateContext<'blk, 'tcx>, llfndecl: ValueRef, id: ast::NodeId, has_env: bool, output_type: ty::FnOutput<'tcx>, - param_substs: &'a Substs<'tcx>, + param_substs: &'blk Substs<'tcx>, sp: Option, - block_arena: &'a TypedArena>) - -> FunctionContext<'a, 'tcx> { + block_arena: &'blk TypedArena) + -> FunctionContext<'blk, 'tcx> { common::validate_substs(param_substs); debug!("new_fn_ctxt(path={}, id={}, param_substs={})", @@ -1496,17 +1501,17 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, /// Performs setup on a newly created function, creating the entry scope block /// and allocating space for the return pointer. -pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>, +pub fn init_function<'fcx, 'blk, 'tcx>(fcx: &'fcx FunctionContext<'blk, 'tcx>, skip_retptr: bool, output: ty::FnOutput<'tcx>) - -> Block<'a, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let entry_bcx = fcx.new_temp_block("entry-block"); // Use a dummy instruction as the insertion point for all allocas. // This is later removed in FunctionContext::cleanup. fcx.alloca_insert_pt.set(Some(unsafe { Load(entry_bcx, C_null(Type::i8p(fcx.ccx))); - llvm::LLVMGetFirstInstruction(entry_bcx.llbb) + llvm::LLVMGetFirstInstruction(entry_bcx.data.llbb) })); if let ty::FnConverging(output_type) = output { @@ -1568,8 +1573,8 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>, /// datums. /// /// FIXME(pcwalton): Reduce the amount of code bloat this is responsible for. -fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>( - mut bcx: Block<'blk, 'tcx>, +fn create_datums_for_fn_args_under_call_abi<'fcx, 'blk, 'tcx>( + mut bcx: Block<'fcx, 'blk, 'tcx>, arg_scope: cleanup::CustomScopeIndex, arg_tys: &[Ty<'tcx>]) -> Vec> { @@ -1629,12 +1634,12 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>( result } -fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, +fn copy_args_to_allocas<'fcx, 'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, arg_scope: cleanup::CustomScopeIndex, - bcx: Block<'blk, 'tcx>, + bcx: Block<'fcx, 'blk, 'tcx>, args: &[ast::Arg], arg_datums: Vec>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("copy_args_to_allocas"); let _icx = push_ctxt("copy_args_to_allocas"); @@ -1661,13 +1666,13 @@ fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, bcx } -fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>( - mut bcx: Block<'blk, 'tcx>, +fn copy_unboxed_closure_args_to_allocas<'fcx, 'blk, 'tcx>( + mut bcx: Block<'fcx, 'blk, 'tcx>, arg_scope: cleanup::CustomScopeIndex, args: &[ast::Arg], arg_datums: Vec>, monomorphized_arg_types: &[Ty<'tcx>]) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("copy_unboxed_closure_args_to_allocas"); let arg_scope_id = cleanup::CustomScope(arg_scope); @@ -1715,14 +1720,14 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>( // Ties up the llstaticallocas -> llloadenv -> lltop edges, // and builds the return block. -pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, - last_bcx: Block<'blk, 'tcx>, +pub fn finish_fn<'fcx, 'blk, 'tcx>(fcx: &'fcx FunctionContext<'blk, 'tcx>, + last_bcx: Block<'fcx, 'blk, 'tcx>, retty: ty::FnOutput<'tcx>) { let _icx = push_ctxt("finish_fn"); let ret_cx = match fcx.llreturn.get() { Some(llreturn) => { - if !last_bcx.terminated.get() { + if !last_bcx.data.terminated.get() { Br(last_bcx, llreturn); } raw_block(fcx, false, llreturn) @@ -1740,8 +1745,8 @@ pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>, } // Builds the return block for a function. -pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>, - ret_cx: Block<'blk, 'tcx>, +pub fn build_return_block<'fcx, 'blk, 'tcx>(fcx: &'fcx FunctionContext<'blk, 'tcx>, + ret_cx: Block<'fcx, 'blk, 'tcx>, retty: ty::FnOutput<'tcx>) { if fcx.llretslotptr.get().is_none() || (!fcx.needs_ret_allocas && fcx.caller_expects_out_pointer) { @@ -1941,7 +1946,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, unsafe { let llreturn = fcx.llreturn.get(); for &llreturn in llreturn.iter() { - llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.llbb); + llvm::LLVMMoveBasicBlockAfter(llreturn, bcx.data.llbb); } } @@ -1993,13 +1998,13 @@ pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfndecl); } -pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +pub fn trans_named_tuple_constructor<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, ctor_ty: Ty<'tcx>, disr: ty::Disr, args: callee::CallArgs, dest: expr::Dest, call_info: Option) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let ccx = bcx.fcx.ccx; let tcx = ccx.tcx(); diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs index 1f77f625c9db3..5a6c2030d247f 100644 --- a/src/librustc_trans/trans/build.rs +++ b/src/librustc_trans/trans/build.rs @@ -25,18 +25,18 @@ use libc::{c_uint, c_char}; pub fn terminate(cx: Block, _: &str) { debug!("terminate({})", cx.to_str()); - cx.terminated.set(true); + cx.data.terminated.set(true); } pub fn check_not_terminated(cx: Block) { - if cx.terminated.get() { + if cx.data.terminated.get() { panic!("already terminated!"); } } -pub fn B<'blk, 'tcx>(cx: Block<'blk, 'tcx>) -> Builder<'blk, 'tcx> { +pub fn B<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>) -> Builder<'blk, 'tcx> { let b = cx.fcx.ccx.builder(); - b.position_at_end(cx.llbb); + b.position_at_end(cx.data.llbb); b } @@ -49,28 +49,28 @@ pub fn B<'blk, 'tcx>(cx: Block<'blk, 'tcx>) -> Builder<'blk, 'tcx> { // further instructions to the block should simply be ignored. pub fn RetVoid(cx: Block) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "RetVoid"); B(cx).ret_void(); } pub fn Ret(cx: Block, v: ValueRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "Ret"); B(cx).ret(v); } pub fn AggregateRet(cx: Block, ret_vals: &[ValueRef]) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "AggregateRet"); B(cx).aggregate_ret(ret_vals); } pub fn Br(cx: Block, dest: BasicBlockRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "Br"); B(cx).br(dest); @@ -80,7 +80,7 @@ pub fn CondBr(cx: Block, if_: ValueRef, then: BasicBlockRef, else_: BasicBlockRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "CondBr"); B(cx).cond_br(if_, then, else_); @@ -88,7 +88,7 @@ pub fn CondBr(cx: Block, pub fn Switch(cx: Block, v: ValueRef, else_: BasicBlockRef, num_cases: uint) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } check_not_terminated(cx); terminate(cx, "Switch"); B(cx).switch(v, else_, num_cases) @@ -102,7 +102,7 @@ pub fn AddCase(s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) { } pub fn IndirectBr(cx: Block, addr: ValueRef, num_dests: uint) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } check_not_terminated(cx); terminate(cx, "IndirectBr"); B(cx).indirect_br(addr, num_dests); @@ -115,7 +115,7 @@ pub fn Invoke(cx: Block, catch: BasicBlockRef, attributes: Option) -> ValueRef { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return C_null(Type::i8(cx.ccx())); } check_not_terminated(cx); @@ -127,11 +127,11 @@ pub fn Invoke(cx: Block, } pub fn Unreachable(cx: Block) { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return } - cx.unreachable.set(true); - if !cx.terminated.get() { + cx.data.unreachable.set(true); + if !cx.data.terminated.get() { B(cx).unreachable(); } } @@ -144,164 +144,164 @@ pub fn _Undef(val: ValueRef) -> ValueRef { /* Arithmetic */ pub fn Add(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).add(lhs, rhs) } pub fn NSWAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nswadd(lhs, rhs) } pub fn NUWAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nuwadd(lhs, rhs) } pub fn FAdd(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).fadd(lhs, rhs) } pub fn Sub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).sub(lhs, rhs) } pub fn NSWSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nswsub(lhs, rhs) } pub fn NUWSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nuwsub(lhs, rhs) } pub fn FSub(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).fsub(lhs, rhs) } pub fn Mul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).mul(lhs, rhs) } pub fn NSWMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nswmul(lhs, rhs) } pub fn NUWMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).nuwmul(lhs, rhs) } pub fn FMul(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).fmul(lhs, rhs) } pub fn UDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).udiv(lhs, rhs) } pub fn SDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).sdiv(lhs, rhs) } pub fn ExactSDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).exactsdiv(lhs, rhs) } pub fn FDiv(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).fdiv(lhs, rhs) } pub fn URem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).urem(lhs, rhs) } pub fn SRem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).srem(lhs, rhs) } pub fn FRem(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).frem(lhs, rhs) } pub fn Shl(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).shl(lhs, rhs) } pub fn LShr(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).lshr(lhs, rhs) } pub fn AShr(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).ashr(lhs, rhs) } pub fn And(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).and(lhs, rhs) } pub fn Or(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).or(lhs, rhs) } pub fn Xor(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).xor(lhs, rhs) } pub fn BinOp(cx: Block, op: Opcode, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(lhs); } + if cx.data.unreachable.get() { return _Undef(lhs); } B(cx).binop(op, lhs, rhs) } pub fn Neg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } B(cx).neg(v) } pub fn NSWNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } B(cx).nswneg(v) } pub fn NUWNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } B(cx).nuwneg(v) } pub fn FNeg(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } B(cx).fneg(v) } pub fn Not(cx: Block, v: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(v); } + if cx.data.unreachable.get() { return _Undef(v); } B(cx).not(v) } /* Memory */ pub fn Malloc(cx: Block, ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } B(cx).malloc(ty) @@ -310,7 +310,7 @@ pub fn Malloc(cx: Block, ty: Type) -> ValueRef { pub fn ArrayMalloc(cx: Block, ty: Type, val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } B(cx).array_malloc(ty, val) @@ -319,7 +319,7 @@ pub fn ArrayMalloc(cx: Block, ty: Type, val: ValueRef) -> ValueRef { pub fn Alloca(cx: Block, ty: Type, name: &str) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } AllocaFcx(cx.fcx, ty, name) } } @@ -332,7 +332,7 @@ pub fn AllocaFcx(fcx: &FunctionContext, ty: Type, name: &str) -> ValueRef { pub fn ArrayAlloca(cx: Block, ty: Type, val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); } let b = cx.fcx.ccx.builder(); b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); b.array_alloca(ty, val) @@ -340,14 +340,14 @@ pub fn ArrayAlloca(cx: Block, ty: Type, val: ValueRef) -> ValueRef { } pub fn Free(cx: Block, pointer_val: ValueRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).free(pointer_val) } pub fn Load(cx: Block, pointer_val: ValueRef) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable.get() { + if cx.data.unreachable.get() { let ty = val_ty(pointer_val); let eltty = if ty.kind() == llvm::Array { ty.element_type() @@ -362,7 +362,7 @@ pub fn Load(cx: Block, pointer_val: ValueRef) -> ValueRef { pub fn VolatileLoad(cx: Block, pointer_val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).volatile_load(pointer_val) @@ -372,7 +372,7 @@ pub fn VolatileLoad(cx: Block, pointer_val: ValueRef) -> ValueRef { pub fn AtomicLoad(cx: Block, pointer_val: ValueRef, order: AtomicOrdering) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ccx.int_type().to_ref()); } B(cx).atomic_load(pointer_val, order) @@ -382,7 +382,7 @@ pub fn AtomicLoad(cx: Block, pointer_val: ValueRef, order: AtomicOrdering) -> Va pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: u64, hi: u64, signed: llvm::Bool) -> ValueRef { - if cx.unreachable.get() { + if cx.data.unreachable.get() { let ccx = cx.fcx.ccx; let ty = val_ty(pointer_val); let eltty = if ty.kind() == llvm::Array { @@ -399,23 +399,23 @@ pub fn LoadRangeAssert(cx: Block, pointer_val: ValueRef, lo: u64, } pub fn Store(cx: Block, val: ValueRef, ptr: ValueRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).store(val, ptr) } pub fn VolatileStore(cx: Block, val: ValueRef, ptr: ValueRef) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).volatile_store(val, ptr) } pub fn AtomicStore(cx: Block, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).atomic_store(val, ptr, order) } pub fn GEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); } B(cx).gep(pointer, indices) @@ -427,7 +427,7 @@ pub fn GEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef { #[inline] pub fn GEPi(cx: Block, base: ValueRef, ixs: &[uint]) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); } B(cx).gepi(base, ixs) @@ -436,7 +436,7 @@ pub fn GEPi(cx: Block, base: ValueRef, ixs: &[uint]) -> ValueRef { pub fn InBoundsGEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); } B(cx).inbounds_gep(pointer, indices) @@ -445,7 +445,7 @@ pub fn InBoundsGEP(cx: Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueR pub fn StructGEP(cx: Block, pointer: ValueRef, idx: uint) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref()); } B(cx).struct_gep(pointer, idx) @@ -454,7 +454,7 @@ pub fn StructGEP(cx: Block, pointer: ValueRef, idx: uint) -> ValueRef { pub fn GlobalString(cx: Block, _str: *const c_char) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } B(cx).global_string(_str) @@ -463,7 +463,7 @@ pub fn GlobalString(cx: Block, _str: *const c_char) -> ValueRef { pub fn GlobalStringPtr(cx: Block, _str: *const c_char) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref()); } B(cx).global_string_ptr(_str) @@ -473,105 +473,105 @@ pub fn GlobalStringPtr(cx: Block, _str: *const c_char) -> ValueRef { /* Casts */ pub fn Trunc(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).trunc(val, dest_ty) } } pub fn ZExt(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).zext(val, dest_ty) } } pub fn SExt(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).sext(val, dest_ty) } } pub fn FPToUI(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).fptoui(val, dest_ty) } } pub fn FPToSI(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).fptosi(val, dest_ty) } } pub fn UIToFP(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).uitofp(val, dest_ty) } } pub fn SIToFP(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).sitofp(val, dest_ty) } } pub fn FPTrunc(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).fptrunc(val, dest_ty) } } pub fn FPExt(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).fpext(val, dest_ty) } } pub fn PtrToInt(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).ptrtoint(val, dest_ty) } } pub fn IntToPtr(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).inttoptr(val, dest_ty) } } pub fn BitCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).bitcast(val, dest_ty) } } pub fn ZExtOrBitCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).zext_or_bitcast(val, dest_ty) } } pub fn SExtOrBitCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).sext_or_bitcast(val, dest_ty) } } pub fn TruncOrBitCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).trunc_or_bitcast(val, dest_ty) } } @@ -580,28 +580,28 @@ pub fn Cast(cx: Block, op: Opcode, val: ValueRef, dest_ty: Type, _: *const u8) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).cast(op, val, dest_ty) } } pub fn PointerCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).pointercast(val, dest_ty) } } pub fn IntCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).intcast(val, dest_ty) } } pub fn FPCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(dest_ty.to_ref()); } B(cx).fpcast(val, dest_ty) } } @@ -611,7 +611,7 @@ pub fn FPCast(cx: Block, val: ValueRef, dest_ty: Type) -> ValueRef { pub fn ICmp(cx: Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } B(cx).icmp(op, lhs, rhs) @@ -621,7 +621,7 @@ pub fn ICmp(cx: Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) pub fn FCmp(cx: Block, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } B(cx).fcmp(op, lhs, rhs) @@ -631,7 +631,7 @@ pub fn FCmp(cx: Block, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) /* Miscellaneous instructions */ pub fn EmptyPhi(cx: Block, ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } B(cx).empty_phi(ty) } } @@ -639,7 +639,7 @@ pub fn EmptyPhi(cx: Block, ty: Type) -> ValueRef { pub fn Phi(cx: Block, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } B(cx).phi(ty, vals, bbs) } } @@ -682,36 +682,36 @@ pub fn InlineAsmCall(cx: Block, asm: *const c_char, cons: *const c_char, pub fn Call(cx: Block, fn_: ValueRef, args: &[ValueRef], attributes: Option) -> ValueRef { - if cx.unreachable.get() { return _UndefReturn(cx, fn_); } + if cx.data.unreachable.get() { return _UndefReturn(cx, fn_); } B(cx).call(fn_, args, attributes) } pub fn CallWithConv(cx: Block, fn_: ValueRef, args: &[ValueRef], conv: CallConv, attributes: Option) -> ValueRef { - if cx.unreachable.get() { return _UndefReturn(cx, fn_); } + if cx.data.unreachable.get() { return _UndefReturn(cx, fn_); } B(cx).call_with_conv(fn_, args, conv, attributes) } pub fn AtomicFence(cx: Block, order: AtomicOrdering) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).atomic_fence(order) } pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef { - if cx.unreachable.get() { return _Undef(then); } + if cx.data.unreachable.get() { return _Undef(then); } B(cx).select(if_, then, else_) } pub fn VAArg(cx: Block, list: ValueRef, ty: Type) -> ValueRef { unsafe { - if cx.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ty.to_ref()); } B(cx).va_arg(list, ty) } } pub fn ExtractElement(cx: Block, vec_val: ValueRef, index: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).extract_element(vec_val, index) @@ -721,7 +721,7 @@ pub fn ExtractElement(cx: Block, vec_val: ValueRef, index: ValueRef) -> ValueRef pub fn InsertElement(cx: Block, vec_val: ValueRef, elt_val: ValueRef, index: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).insert_element(vec_val, elt_val, index) @@ -731,7 +731,7 @@ pub fn InsertElement(cx: Block, vec_val: ValueRef, elt_val: ValueRef, pub fn ShuffleVector(cx: Block, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).shuffle_vector(v1, v2, mask) @@ -740,7 +740,7 @@ pub fn ShuffleVector(cx: Block, v1: ValueRef, v2: ValueRef, pub fn VectorSplat(cx: Block, num_elts: uint, elt_val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).vector_splat(num_elts, elt_val) @@ -749,7 +749,7 @@ pub fn VectorSplat(cx: Block, num_elts: uint, elt_val: ValueRef) -> ValueRef { pub fn ExtractValue(cx: Block, agg_val: ValueRef, index: uint) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).extract_value(agg_val, index) @@ -758,7 +758,7 @@ pub fn ExtractValue(cx: Block, agg_val: ValueRef, index: uint) -> ValueRef { pub fn InsertValue(cx: Block, agg_val: ValueRef, elt_val: ValueRef, index: uint) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref()); } B(cx).insert_value(agg_val, elt_val, index) @@ -767,7 +767,7 @@ pub fn InsertValue(cx: Block, agg_val: ValueRef, elt_val: ValueRef, index: uint) pub fn IsNull(cx: Block, val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } B(cx).is_null(val) @@ -776,7 +776,7 @@ pub fn IsNull(cx: Block, val: ValueRef) -> ValueRef { pub fn IsNotNull(cx: Block, val: ValueRef) -> ValueRef { unsafe { - if cx.unreachable.get() { + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref()); } B(cx).is_not_null(val) @@ -786,20 +786,20 @@ pub fn IsNotNull(cx: Block, val: ValueRef) -> ValueRef { pub fn PtrDiff(cx: Block, lhs: ValueRef, rhs: ValueRef) -> ValueRef { unsafe { let ccx = cx.fcx.ccx; - if cx.unreachable.get() { return llvm::LLVMGetUndef(ccx.int_type().to_ref()); } + if cx.data.unreachable.get() { return llvm::LLVMGetUndef(ccx.int_type().to_ref()); } B(cx).ptrdiff(lhs, rhs) } } pub fn Trap(cx: Block) { - if cx.unreachable.get() { return; } + if cx.data.unreachable.get() { return; } B(cx).trap(); } pub fn LandingPad(cx: Block, ty: Type, pers_fn: ValueRef, num_clauses: uint) -> ValueRef { check_not_terminated(cx); - assert!(!cx.unreachable.get()); + assert!(!cx.data.unreachable.get()); B(cx).landing_pad(ty, pers_fn, num_clauses) } diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 6196f9e5eab65..c290d54889d63 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -80,13 +80,13 @@ pub enum CalleeData<'tcx> { TraitItem(MethodData) } -pub struct Callee<'blk, 'tcx: 'blk> { - pub bcx: Block<'blk, 'tcx>, +pub struct Callee<'fcx, 'blk: 'fcx, 'tcx: 'blk> { + pub bcx: Block<'fcx, 'blk, 'tcx>, pub data: CalleeData<'tcx>, } -fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) - -> Callee<'blk, 'tcx> { +fn trans<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) + -> Callee<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_callee"); debug!("callee::trans(expr={})", expr.repr(bcx.tcx())); @@ -98,8 +98,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) // any other expressions are closures: return datum_callee(bcx, expr); - fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) - -> Callee<'blk, 'tcx> { + fn datum_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) + -> Callee<'fcx, 'blk, 'tcx> { let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr); match datum.ty.sty { ty::ty_bare_fn(..) => { @@ -119,18 +119,18 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } - fn fn_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn: ValueRef) - -> Callee<'blk, 'tcx> { + fn fn_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, llfn: ValueRef) + -> Callee<'fcx, 'blk, 'tcx> { return Callee { bcx: bcx, data: Fn(llfn), }; } - fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn trans_def<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, def: def::Def, ref_expr: &ast::Expr) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx())); let expr_ty = node_id_type(bcx, ref_expr.id); match def { @@ -230,11 +230,11 @@ pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trans_fn_ref_with_substs(ccx, def_id, node, param_substs, substs) } -fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_fn_ref_with_substs_to_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, def_id: ast::DefId, ref_id: ast::NodeId, substs: subst::Substs<'tcx>) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { Callee { bcx: bcx, data: Fn(trans_fn_ref_with_substs(bcx.ccx(), @@ -264,7 +264,6 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( { let _icx = push_ctxt("trans_fn_pointer_shim"); let tcx = ccx.tcx(); - let bare_fn_ty = erase_regions(tcx, &bare_fn_ty); match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) { Some(&llval) => { return llval; } @@ -573,12 +572,12 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>( // ______________________________________________________________________ // Translating calls -pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>, +pub fn trans_call<'a, 'fcx, 'blk, 'tcx>(in_cx: Block<'fcx, 'blk, 'tcx>, call_ex: &ast::Expr, f: &ast::Expr, args: CallArgs<'a, 'tcx>, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_call"); trans_call_inner(in_cx, Some(common::expr_info(call_ex)), @@ -588,12 +587,12 @@ pub fn trans_call<'a, 'blk, 'tcx>(in_cx: Block<'blk, 'tcx>, Some(dest)).bcx } -pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_method_call<'a, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, call_ex: &ast::Expr, rcvr: &ast::Expr, args: CallArgs<'a, 'tcx>, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_method_call"); debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx())); let method_call = MethodCall::expr(call_ex.id); @@ -609,11 +608,11 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Some(dest)).bcx } -pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_lang_call<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, did: ast::DefId, args: &[ValueRef], dest: Option) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let fty = if did.krate == ast::LOCAL_CRATE { ty::node_id_to_type(bcx.tcx(), did.node) } else { @@ -642,14 +641,14 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// /// For non-lang items, `dest` is always Some, and hence the result is written into memory /// somewhere. Nonetheless we return the actual return value of the function. -pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +pub fn trans_call_inner<'a, 'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, call_info: Option, callee_ty: Ty<'tcx>, get_callee: F, args: CallArgs<'a, 'tcx>, dest: Option) - -> Result<'blk, 'tcx> where - F: FnOnce(Block<'blk, 'tcx>, cleanup::ScopeId) -> Callee<'blk, 'tcx>, + -> Result<'fcx, 'blk, 'tcx> where + F: FnOnce(Block<'fcx, 'blk, 'tcx>, cleanup::ScopeId) -> Callee<'fcx, 'blk, 'tcx>, { // Introduce a temporary cleanup scope that will contain cleanups // for the arguments while they are being evaluated. The purpose @@ -859,14 +858,14 @@ pub enum CallArgs<'a, 'tcx> { ArgOverloadedCall(Vec<&'a ast::Expr>), } -fn trans_args_under_call_abi<'blk, 'tcx>( - mut bcx: Block<'blk, 'tcx>, +fn trans_args_under_call_abi<'fcx, 'blk, 'tcx>( + mut bcx: Block<'fcx, 'blk, 'tcx>, arg_exprs: &[P], fn_ty: Ty<'tcx>, llargs: &mut Vec, arg_cleanup_scope: cleanup::ScopeId, ignore_self: bool) - -> Block<'blk, 'tcx> + -> Block<'fcx, 'blk, 'tcx> { let args = ty::erase_late_bound_regions( @@ -923,14 +922,14 @@ fn trans_args_under_call_abi<'blk, 'tcx>( bcx } -fn trans_overloaded_call_args<'blk, 'tcx>( - mut bcx: Block<'blk, 'tcx>, +fn trans_overloaded_call_args<'fcx, 'blk, 'tcx>( + mut bcx: Block<'fcx, 'blk, 'tcx>, arg_exprs: Vec<&ast::Expr>, fn_ty: Ty<'tcx>, llargs: &mut Vec, arg_cleanup_scope: cleanup::ScopeId, ignore_self: bool) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { // Translate the `self` argument first. let arg_tys = ty::erase_late_bound_regions(bcx.tcx(), &ty::ty_fn_args(fn_ty)); if !ignore_self { @@ -969,14 +968,14 @@ fn trans_overloaded_call_args<'blk, 'tcx>( bcx } -pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn trans_args<'a, 'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, args: CallArgs<'a, 'tcx>, fn_ty: Ty<'tcx>, llargs: &mut Vec, arg_cleanup_scope: cleanup::ScopeId, ignore_self: bool, abi: synabi::Abi) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("trans_args(abi={})", abi); let _icx = push_ctxt("trans_args"); @@ -1061,12 +1060,12 @@ pub enum AutorefArg { DoAutorefArg(ast::NodeId) } -pub fn trans_arg_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_arg_datum<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, formal_arg_ty: Ty<'tcx>, arg_datum: Datum<'tcx, Expr>, arg_cleanup_scope: cleanup::ScopeId, autoref_arg: AutorefArg) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_arg_datum"); let mut bcx = bcx; let ccx = bcx.ccx(); diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 5658889aaf368..2906b4426ae7d 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -21,7 +21,7 @@ use trans::base; use trans::build; use trans::callee; use trans::common; -use trans::common::{Block, FunctionContext, ExprId, NodeInfo}; +use trans::common::{Block, BlockS, FunctionContext, ExprId, NodeInfo}; use trans::debuginfo; use trans::glue; use middle::region; @@ -31,13 +31,13 @@ use std::fmt; use syntax::ast; use util::ppaux::Repr; -pub struct CleanupScope<'blk, 'tcx: 'blk> { +pub struct CleanupScope<'blk, 'tcx> { // The id of this cleanup scope. If the id is None, // this is a *temporary scope* that is pushed during trans to // cleanup miscellaneous garbage that trans may generate whose // lifetime is a subset of some expression. See module doc for // more details. - kind: CleanupScopeKind<'blk, 'tcx>, + kind: CleanupScopeKind<'blk>, // Cleanups to run upon scope exit. cleanups: Vec>, @@ -59,13 +59,13 @@ pub const EXIT_BREAK: uint = 0; pub const EXIT_LOOP: uint = 1; pub const EXIT_MAX: uint = 2; -pub enum CleanupScopeKind<'blk, 'tcx: 'blk> { +pub enum CleanupScopeKind<'blk> { CustomScopeKind, AstScopeKind(ast::NodeId), - LoopScopeKind(ast::NodeId, [Block<'blk, 'tcx>; EXIT_MAX]) + LoopScopeKind(ast::NodeId, [&'blk BlockS; EXIT_MAX]) } -impl<'blk, 'tcx: 'blk> fmt::Show for CleanupScopeKind<'blk, 'tcx> { +impl<'blk> fmt::Show for CleanupScopeKind<'blk> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { CustomScopeKind => write!(f, "CustomScopeKind"), @@ -98,10 +98,10 @@ pub trait Cleanup<'tcx> { fn must_unwind(&self) -> bool; fn clean_on_unwind(&self) -> bool; fn is_lifetime_end(&self) -> bool; - fn trans<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, debug_loc: Option) - -> Block<'blk, 'tcx>; + -> Block<'fcx, 'blk, 'tcx>; } pub type CleanupObj<'tcx> = Box+'tcx>; @@ -130,12 +130,17 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { // this new AST scope had better be its immediate child. let top_scope = self.top_ast_scope(); if top_scope.is_some() { - assert_eq!(self.ccx - .tcx() - .region_maps - .opt_encl_scope(region::CodeExtent::from_node_id(debug_loc.id)) - .map(|s|s.node_id()), - top_scope); + assert!((self.ccx + .tcx() + .region_maps + .opt_encl_scope(region::CodeExtent::from_node_id(debug_loc.id)) + .map(|s|s.node_id()) == top_scope) + || + (self.ccx + .tcx() + .region_maps + .opt_encl_scope(region::CodeExtent::DestructionScope(debug_loc.id)) + .map(|s|s.node_id()) == top_scope)); } self.push_scope(CleanupScope::new(AstScopeKind(debug_loc.id), @@ -144,7 +149,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { fn push_loop_cleanup_scope(&self, id: ast::NodeId, - exits: [Block<'blk, 'tcx>; EXIT_MAX]) { + exits: [&'blk BlockS; EXIT_MAX]) { debug!("push_loop_cleanup_scope({})", self.ccx.tcx().map.node_to_string(id)); assert_eq!(Some(id), self.top_ast_scope()); @@ -186,10 +191,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Removes the cleanup scope for id `cleanup_scope`, which must be at the top of the cleanup /// stack, and generates the code to do its cleanups for normal exit. - fn pop_and_trans_ast_cleanup_scope(&self, - bcx: Block<'blk, 'tcx>, + fn pop_and_trans_ast_cleanup_scope<'fcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, cleanup_scope: ast::NodeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("pop_and_trans_ast_cleanup_scope({})", self.ccx.tcx().map.node_to_string(cleanup_scope)); @@ -223,10 +228,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Removes the top cleanup scope from the stack, which must be a temporary scope, and /// generates the code to do its cleanups for normal exit. - fn pop_and_trans_custom_cleanup_scope(&self, - bcx: Block<'blk, 'tcx>, + fn pop_and_trans_custom_cleanup_scope<'fcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, custom_scope: CustomScopeIndex) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("pop_and_trans_custom_cleanup_scope({:?})", custom_scope); assert!(self.is_valid_to_pop_custom_scope(custom_scope)); @@ -246,7 +251,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Returns a block to branch to which will perform all pending cleanups and then /// break/continue (depending on `exit`) out of the loop with id `cleanup_scope` - fn normal_exit_block(&'blk self, + fn normal_exit_block(&self, cleanup_scope: ast::NodeId, exit: uint) -> BasicBlockRef { self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit)) @@ -254,7 +259,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Returns a block to branch to which will perform all pending cleanups and then return from /// this function - fn return_exit_block(&'blk self) -> BasicBlockRef { + fn return_exit_block(&self) -> BasicBlockRef { self.trans_cleanups_to_exit_scope(ReturnExit) } @@ -429,7 +434,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { /// Returns a basic block to branch to in the event of a panic. This block will run the panic /// cleanups and eventually invoke the LLVM `Resume` instruction. - fn get_landing_pad(&'blk self) -> BasicBlockRef { + fn get_landing_pad(&self) -> BasicBlockRef { let _icx = base::push_ctxt("get_landing_pad"); debug!("get_landing_pad"); @@ -491,12 +496,11 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx } /// Generates the cleanups for `scope` into `bcx` - fn trans_scope_cleanups(&self, // cannot borrow self, will recurse - bcx: Block<'blk, 'tcx>, - scope: &CleanupScope<'blk, 'tcx>) -> Block<'blk, 'tcx> { - + fn trans_scope_cleanups<'fcx>(&self, // cannot borrow self, will recurse + bcx: Block<'fcx, 'blk, 'tcx>, + scope: &CleanupScope<'blk, 'tcx>) -> Block<'fcx, 'blk, 'tcx> { let mut bcx = bcx; - if !bcx.unreachable.get() { + if !bcx.data.unreachable.get() { for cleanup in scope.cleanups.iter().rev() { bcx = cleanup.trans(bcx, scope.debug_loc); } @@ -546,7 +550,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx /// value would be the first basic block in that sequence (`Cleanup(AST 24)`). The caller could /// then branch to `Cleanup(AST 24)` and it will perform all cleanups and finally branch to the /// `break_blk`. - fn trans_cleanups_to_exit_scope(&'blk self, + fn trans_cleanups_to_exit_scope(&self, label: EarlyExitLabel) -> BasicBlockRef { debug!("trans_cleanups_to_exit_scope label={:?} scopes={}", @@ -574,7 +578,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx "create_landing_pad() should have set this"); build::Resume(prev_bcx, build::Load(prev_bcx, personality)); - prev_llbb = prev_bcx.llbb; + prev_llbb = prev_bcx.data.llbb; break; } @@ -665,7 +669,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx } } build::Br(bcx_out, prev_llbb); - prev_llbb = bcx_in.llbb; + prev_llbb = bcx_in.data.llbb; } else { debug!("no suitable cleanups in {}", scope.block_name("clean")); @@ -689,7 +693,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx /// /// (The cleanups and resume instruction are created by `trans_cleanups_to_exit_scope()`, not /// in this function itself.) - fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef { + fn get_or_create_landing_pad(&self) -> BasicBlockRef { let pad_bcx; debug!("get_or_create_landing_pad"); @@ -703,7 +707,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx None => { let name = last_scope.block_name("unwind"); pad_bcx = self.new_block(true, &name[], None); - last_scope.cached_landing_pad = Some(pad_bcx.llbb); + last_scope.cached_landing_pad = Some(pad_bcx.data.llbb); } } } @@ -768,12 +772,12 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx let cleanup_llbb = self.trans_cleanups_to_exit_scope(UnwindExit); build::Br(pad_bcx, cleanup_llbb); - return pad_bcx.llbb; + return pad_bcx.data.llbb; } } impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { - fn new(kind: CleanupScopeKind<'blk, 'tcx>, + fn new(kind: CleanupScopeKind<'blk>, debug_loc: Option) -> CleanupScope<'blk, 'tcx> { CleanupScope { @@ -827,7 +831,7 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { } } -impl<'blk, 'tcx> CleanupScopeKind<'blk, 'tcx> { +impl<'blk> CleanupScopeKind<'blk> { fn is_temp(&self) -> bool { match *self { CustomScopeKind => true, @@ -894,10 +898,10 @@ impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> { false } - fn trans<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, debug_loc: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let bcx = if self.is_immediate { glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc) } else { @@ -935,10 +939,10 @@ impl<'tcx> Cleanup<'tcx> for FreeValue<'tcx> { false } - fn trans<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, debug_loc: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { apply_debug_loc(bcx.fcx, debug_loc); match self.heap { @@ -970,10 +974,10 @@ impl<'tcx> Cleanup<'tcx> for FreeSlice { false } - fn trans<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, debug_loc: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { apply_debug_loc(bcx.fcx, debug_loc); match self.heap { @@ -1002,10 +1006,10 @@ impl<'tcx> Cleanup<'tcx> for LifetimeEnd { true } - fn trans<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, debug_loc: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { apply_debug_loc(bcx.fcx, debug_loc); base::call_lifetime_end(bcx, self.ptr); bcx @@ -1059,28 +1063,28 @@ pub trait CleanupMethods<'blk, 'tcx> { fn push_ast_cleanup_scope(&self, id: NodeInfo); fn push_loop_cleanup_scope(&self, id: ast::NodeId, - exits: [Block<'blk, 'tcx>; EXIT_MAX]); + exits: [&'blk BlockS; EXIT_MAX]); fn push_custom_cleanup_scope(&self) -> CustomScopeIndex; fn push_custom_cleanup_scope_with_debug_loc(&self, debug_loc: NodeInfo) -> CustomScopeIndex; - fn pop_and_trans_ast_cleanup_scope(&self, - bcx: Block<'blk, 'tcx>, + fn pop_and_trans_ast_cleanup_scope<'fcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, cleanup_scope: ast::NodeId) - -> Block<'blk, 'tcx>; + -> Block<'fcx, 'blk, 'tcx>; fn pop_loop_cleanup_scope(&self, cleanup_scope: ast::NodeId); fn pop_custom_cleanup_scope(&self, custom_scope: CustomScopeIndex); - fn pop_and_trans_custom_cleanup_scope(&self, - bcx: Block<'blk, 'tcx>, + fn pop_and_trans_custom_cleanup_scope<'fcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, custom_scope: CustomScopeIndex) - -> Block<'blk, 'tcx>; + -> Block<'fcx, 'blk, 'tcx>; fn top_loop_scope(&self) -> ast::NodeId; - fn normal_exit_block(&'blk self, + fn normal_exit_block(&self, cleanup_scope: ast::NodeId, exit: uint) -> BasicBlockRef; - fn return_exit_block(&'blk self) -> BasicBlockRef; + fn return_exit_block(&self) -> BasicBlockRef; fn schedule_lifetime_end(&self, cleanup_scope: ScopeId, val: ValueRef); @@ -1117,7 +1121,7 @@ pub trait CleanupMethods<'blk, 'tcx> { custom_scope: CustomScopeIndex, cleanup: CleanupObj<'tcx>); fn needs_invoke(&self) -> bool; - fn get_landing_pad(&'blk self) -> BasicBlockRef; + fn get_landing_pad(&self) -> BasicBlockRef; } trait CleanupHelperMethods<'blk, 'tcx> { @@ -1125,13 +1129,13 @@ trait CleanupHelperMethods<'blk, 'tcx> { fn top_nonempty_cleanup_scope(&self) -> Option; fn is_valid_to_pop_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool; fn is_valid_custom_scope(&self, custom_scope: CustomScopeIndex) -> bool; - fn trans_scope_cleanups(&self, - bcx: Block<'blk, 'tcx>, - scope: &CleanupScope<'blk, 'tcx>) -> Block<'blk, 'tcx>; - fn trans_cleanups_to_exit_scope(&'blk self, + fn trans_scope_cleanups<'fcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, + scope: &CleanupScope<'blk, 'tcx>) -> Block<'fcx, 'blk, 'tcx>; + fn trans_cleanups_to_exit_scope(&self, label: EarlyExitLabel) -> BasicBlockRef; - fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef; + fn get_or_create_landing_pad(&self) -> BasicBlockRef; fn scopes_len(&self) -> uint; fn push_scope(&self, scope: CleanupScope<'blk, 'tcx>); fn pop_scope(&self) -> CleanupScope<'blk, 'tcx>; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 8989dfd493236..1bfde3f99f6d4 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -136,19 +136,19 @@ fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t)) } -pub struct ClosureResult<'blk, 'tcx: 'blk> { +pub struct ClosureResult<'fcx, 'blk: 'fcx, 'tcx: 'blk> { llbox: ValueRef, // llvalue of ptr to closure cdata_ty: Ty<'tcx>, // type of the closure data - bcx: Block<'blk, 'tcx> // final bcx + bcx: Block<'fcx, 'blk, 'tcx> // final bcx } // Given a block context and a list of tydescs and values to bind // construct a closure out of them. If copying is true, it is a // heap allocated closure that copies the upvars into environment. // Otherwise, it is stack allocated and copies pointers to the upvars. -pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn store_environment<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, bound_values: Vec>) - -> ClosureResult<'blk, 'tcx> { + -> ClosureResult<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::store_environment"); let ccx = bcx.ccx(); let tcx = ccx.tcx(); @@ -203,10 +203,10 @@ 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>, +fn build_closure<'fcx, 'blk, 'tcx>(bcx0: Block<'fcx, 'blk, 'tcx>, freevar_mode: ast::CaptureClause, freevars: &Vec) - -> ClosureResult<'blk, 'tcx> { + -> ClosureResult<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::build_closure"); // If we need to, package up the iterator body to call @@ -225,11 +225,11 @@ fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>, // Given an enclosing block context, a new function context, a closure type, // and a list of upvars, generate code to load and populate the environment // with the upvars and type descriptors. -fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn load_environment<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, cdata_ty: Ty<'tcx>, freevars: &[ty::Freevar], store: ty::TraitStore) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::load_environment"); // Load a pointer to the closure data, skipping over the box header: @@ -275,12 +275,12 @@ fn load_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx } -fn load_unboxed_closure_environment<'blk, 'tcx>( - bcx: Block<'blk, 'tcx>, +fn load_unboxed_closure_environment<'fcx, 'blk, 'tcx>( + bcx: Block<'fcx, 'blk, 'tcx>, arg_scope_id: ScopeId, freevar_mode: ast::CaptureClause, freevars: &[ty::Freevar]) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::load_environment"); // Special case for small by-value selfs. @@ -370,8 +370,8 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { } } - pub fn load<'blk>(self, bcx: Block<'blk, 'tcx>, arg_scope: ScopeId) - -> Block<'blk, 'tcx> { + pub fn load<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>, arg_scope: ScopeId) + -> Block<'fcx, 'blk, 'tcx> { // Don't bother to create the block if there's nothing to load if self.freevars.is_empty() { return bcx; @@ -398,13 +398,13 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { /// - `cap_clause`: information about captured variables, if any. /// - `dest`: where to write the closure value, which must be a /// (fn ptr, env) pair -pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_expr_fn<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, store: ty::TraitStore, decl: &ast::FnDecl, body: &ast::Block, id: ast::NodeId, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::trans_expr_fn"); let dest_addr = match dest { @@ -503,13 +503,13 @@ pub fn get_or_create_declaration_if_unboxed_closure<'a, 'tcx>(ccx: &CrateContext Some(Datum::new(llfn, function_type, Rvalue::new(ByValue))) } -pub fn trans_unboxed_closure<'blk, 'tcx>( - mut bcx: Block<'blk, 'tcx>, +pub fn trans_unboxed_closure<'fcx, 'blk, 'tcx>( + mut bcx: Block<'fcx, 'blk, 'tcx>, decl: &ast::FnDecl, body: &ast::Block, id: ast::NodeId, dest: expr::Dest) - -> Block<'blk, 'tcx> + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::trans_unboxed_closure"); @@ -581,4 +581,3 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( bcx } - diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index f59e70d099a63..67c0eb9e32fb5 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -353,7 +353,7 @@ type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>; // Function context. Every LLVM function we create will have one of // these. -pub struct FunctionContext<'a, 'tcx: 'a> { +pub struct FunctionContext<'blk, 'tcx: 'blk> { // The ValueRef returned from a call to llvm::LLVMAddFunction; the // address of the first instruction in the sequence of // instructions for this function that will go in the .text @@ -361,7 +361,7 @@ pub struct FunctionContext<'a, 'tcx: 'a> { pub llfn: ValueRef, // always an empty parameter-environment - pub param_env: ty::ParameterEnvironment<'a, 'tcx>, + pub param_env: ty::ParameterEnvironment<'blk, 'tcx>, // The environment argument in a closure. pub llenv: Option, @@ -407,28 +407,28 @@ pub struct FunctionContext<'a, 'tcx: 'a> { // If this function is being monomorphized, this contains the type // substitutions used. - pub param_substs: &'a Substs<'tcx>, + pub param_substs: &'blk Substs<'tcx>, // The source span and nesting context where this function comes from, for // error reporting and symbol generation. pub span: Option, // The arena that blocks are allocated from. - pub block_arena: &'a TypedArena>, + pub block_arena: &'blk TypedArena, // This function's enclosing crate context. - pub ccx: &'a CrateContext<'a, 'tcx>, + pub ccx: &'blk CrateContext<'blk, 'tcx>, // Used and maintained by the debuginfo module. pub debug_context: debuginfo::FunctionDebugContext, // Cleanup scopes. - pub scopes: RefCell>>, + pub scopes: RefCell>>, pub cfg: Option, } -impl<'a, 'tcx> FunctionContext<'a, 'tcx> { +impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { pub fn arg_pos(&self, arg: uint) -> uint { let arg = self.env_arg_pos() + arg; if self.llenv.is_some() { @@ -466,7 +466,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { self.llreturn.get().unwrap() } - pub fn get_ret_slot(&self, bcx: Block<'a, 'tcx>, + pub fn get_ret_slot<'fcx>(&'fcx self, bcx: Block<'fcx, 'blk, 'tcx>, output: ty::FnOutput<'tcx>, name: &str) -> ValueRef { if self.needs_ret_allocas { @@ -479,11 +479,11 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { } } - pub fn new_block(&'a self, + pub fn new_block<'fcx>(&'fcx self, is_lpad: bool, name: &str, opt_node_id: Option) - -> Block<'a, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { unsafe { let name = CString::from_slice(name.as_bytes()); let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), @@ -493,28 +493,28 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { } } - pub fn new_id_block(&'a self, + pub fn new_id_block<'fcx>(&'fcx self, name: &str, node_id: ast::NodeId) - -> Block<'a, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { self.new_block(false, name, Some(node_id)) } - pub fn new_temp_block(&'a self, + pub fn new_temp_block<'fcx>(&'fcx self, name: &str) - -> Block<'a, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { self.new_block(false, name, None) } - pub fn join_blocks(&'a self, + pub fn join_blocks<'fcx>(&'fcx self, id: ast::NodeId, - in_cxs: &[Block<'a, 'tcx>]) - -> Block<'a, 'tcx> { + in_cxs: &[Block<'fcx, 'blk, 'tcx>]) + -> Block<'fcx, 'blk, 'tcx> { let out = self.new_id_block("join", id); let mut reachable = false; for bcx in in_cxs.iter() { - if !bcx.unreachable.get() { - build::Br(*bcx, out.llbb); + if !bcx.data.unreachable.get() { + build::Br(*bcx, out.data.llbb); reachable = true; } } @@ -538,7 +538,18 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { // code. Each basic block we generate is attached to a function, typically // with many basic blocks per function. All the basic blocks attached to a // function are organized as a directed graph. -pub struct BlockS<'blk, 'tcx: 'blk> { +pub struct Block<'fcx, 'blk: 'fcx, 'tcx: 'blk> { + // The function context for the function to which this block is + // attached. + pub fcx: &'fcx FunctionContext<'blk, 'tcx>, + + // The block payload (stored in an arena). + pub data: &'blk BlockS, +} + +impl<'fcx, 'blk, 'tcx> Copy for Block<'fcx, 'blk, 'tcx> { } + +pub struct BlockS { // The BasicBlockRef returned from a call to // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic // block to the function pointed to by llfn. We insert @@ -555,29 +566,9 @@ pub struct BlockS<'blk, 'tcx: 'blk> { // debugging purposes only. pub opt_node_id: Option, - // The function context for the function to which this block is - // attached. - pub fcx: &'blk FunctionContext<'blk, 'tcx>, } -pub type Block<'blk, 'tcx> = &'blk BlockS<'blk, 'tcx>; - -impl<'blk, 'tcx> BlockS<'blk, 'tcx> { - pub fn new(llbb: BasicBlockRef, - is_lpad: bool, - opt_node_id: Option, - fcx: &'blk FunctionContext<'blk, 'tcx>) - -> Block<'blk, 'tcx> { - fcx.block_arena.alloc(BlockS { - llbb: llbb, - terminated: Cell::new(false), - unreachable: Cell::new(false), - is_lpad: is_lpad, - opt_node_id: opt_node_id, - fcx: fcx - }) - } - +impl<'fcx, 'blk, 'tcx> Block<'fcx, 'blk, 'tcx> { pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> { self.fcx.ccx } @@ -621,7 +612,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } pub fn to_str(&self) -> String { - format!("[block {:p}]", self) + self.data.to_str() } pub fn monomorphize(&self, value: &T) -> T @@ -633,17 +624,40 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { } } -impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { +impl BlockS { + pub fn new<'fcx, 'blk, 'tcx>(llbb: BasicBlockRef, + is_lpad: bool, + opt_node_id: Option, + fcx: &'fcx FunctionContext<'blk, 'tcx>) -> Block<'fcx, 'blk, 'tcx> { + let data = fcx.block_arena.alloc(BlockS { + llbb: llbb, + terminated: Cell::new(false), + unreachable: Cell::new(false), + is_lpad: is_lpad, + opt_node_id: opt_node_id, + }); + Block { + fcx: fcx, + data: data, + } + } + + pub fn to_str(&self) -> String { + format!("[block {:p}]", self) + } +} + +impl<'fcx, 'blk, 'tcx> mc::Typer<'tcx> for Block<'fcx, 'blk, 'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx() } fn node_ty(&self, id: ast::NodeId) -> mc::McResult> { - Ok(node_id_type(self, id)) + Ok(node_id_type(*self, id)) } fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult> { - Ok(expr_ty_adjusted(self, expr)) + Ok(expr_ty_adjusted(*self, expr)) } fn node_method_ty(&self, method_call: ty::MethodCall) -> Option> { @@ -651,7 +665,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { .method_map .borrow() .get(&method_call) - .map(|method| monomorphize_type(self, method.ty)) + .map(|method| monomorphize_type(*self, method.ty)) } fn node_method_origin(&self, method_call: ty::MethodCall) @@ -690,7 +704,7 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { } } -impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> { +impl<'fcx, 'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for Block<'fcx, 'blk, 'tcx> { fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> { &self.fcx.param_env } @@ -722,13 +736,13 @@ impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> { } } -pub struct Result<'blk, 'tcx: 'blk> { - pub bcx: Block<'blk, 'tcx>, +pub struct Result<'fcx, 'blk: 'fcx, 'tcx: 'blk> { + pub bcx: Block<'fcx, 'blk, 'tcx>, pub val: ValueRef } -impl<'b, 'tcx> Result<'b, 'tcx> { - pub fn new(bcx: Block<'b, 'tcx>, val: ValueRef) -> Result<'b, 'tcx> { +impl<'fcx, 'blk, 'tcx> Result<'fcx, 'blk, 'tcx> { + pub fn new(bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef) -> Result<'fcx, 'blk, 'tcx> { Result { bcx: bcx, val: val, @@ -961,21 +975,22 @@ pub fn is_null(val: ValueRef) -> bool { } } -pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { +pub fn monomorphize_type<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { bcx.fcx.monomorphize(&t) } -pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> { +pub fn node_id_type<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> { let tcx = bcx.tcx(); let t = ty::node_id_to_type(tcx, id); monomorphize_type(bcx, t) } -pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> { +pub fn expr_ty<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> { node_id_type(bcx, ex.id) } -pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> { +pub fn expr_ty_adjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + ex: &ast::Expr) -> Ty<'tcx> { monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex)) } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index adf302501cd1f..9cb7cd3b1575b 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -40,9 +40,9 @@ use syntax::parse::token::InternedString; use syntax::parse::token; use syntax::visit::Visitor; -pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn trans_stmt<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, s: &ast::Stmt) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_stmt"); let fcx = cx.fcx; debug!("trans_stmt({})", s.repr(cx.tcx())); @@ -83,8 +83,8 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr) - -> Block<'blk, 'tcx> { +pub fn trans_stmt_semi<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, e: &ast::Expr) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_stmt_semi"); let ty = expr_ty(cx, e); if type_needs_drop(cx.tcx(), ty) { @@ -94,10 +94,10 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr) } } -pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_block<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, b: &ast::Block, mut dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_block"); let fcx = bcx.fcx; let mut bcx = bcx; @@ -131,7 +131,7 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx = expr::trans_into(bcx, &**e, dest); } None => { - assert!(dest == expr::Ignore || bcx.unreachable.get()); + assert!(dest == expr::Ignore || bcx.data.unreachable.get()); } } @@ -140,13 +140,13 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_if<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, if_id: ast::NodeId, cond: &ast::Expr, thn: &ast::Block, els: Option<&ast::Expr>, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("trans_if(bcx={}, if_id={}, cond={}, thn={}, dest={})", bcx.to_str(), if_id, bcx.expr_to_string(cond), thn.id, dest.to_string(bcx.ccx())); @@ -199,13 +199,13 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let else_bcx_out = expr::trans_into(else_bcx_in, &*elexpr, dest); next_bcx = bcx.fcx.join_blocks(if_id, &[then_bcx_out, else_bcx_out]); - CondBr(bcx, cond_val, then_bcx_in.llbb, else_bcx_in.llbb); + CondBr(bcx, cond_val, then_bcx_in.data.llbb, else_bcx_in.data.llbb); } None => { next_bcx = bcx.fcx.new_id_block("next-block", if_id); - Br(then_bcx_out, next_bcx.llbb); - CondBr(bcx, cond_val, then_bcx_in.llbb, next_bcx.llbb); + Br(then_bcx_out, next_bcx.data.llbb); + CondBr(bcx, cond_val, then_bcx_in.data.llbb, next_bcx.data.llbb); } } @@ -216,11 +216,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, next_bcx } -pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_while<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, loop_id: ast::NodeId, cond: &ast::Expr, body: &ast::Block) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_while"); let fcx = bcx.fcx; @@ -239,9 +239,9 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let cond_bcx_in = fcx.new_id_block("while_cond", cond.id); let body_bcx_in = fcx.new_id_block("while_body", body.id); - fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, cond_bcx_in]); + fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in.data, cond_bcx_in.data]); - Br(bcx, cond_bcx_in.llbb); + Br(bcx, cond_bcx_in.data.llbb); // compile the block where we will handle loop cleanups let cleanup_llbb = fcx.normal_exit_block(loop_id, cleanup::EXIT_BREAK); @@ -249,23 +249,23 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // compile the condition let Result {bcx: cond_bcx_out, val: cond_val} = expr::trans(cond_bcx_in, cond).to_llbool(); - CondBr(cond_bcx_out, cond_val, body_bcx_in.llbb, cleanup_llbb); + CondBr(cond_bcx_out, cond_val, body_bcx_in.data.llbb, cleanup_llbb); // loop body: let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); - Br(body_bcx_out, cond_bcx_in.llbb); + Br(body_bcx_out, cond_bcx_in.data.llbb); fcx.pop_loop_cleanup_scope(loop_id); return next_bcx_in; } /// Translates a `for` loop. -pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +pub fn trans_for<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, loop_info: NodeInfo, pat: &ast::Pat, head: &ast::Expr, body: &ast::Block) - -> Block<'blk, 'tcx> + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_for"); @@ -295,8 +295,8 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let loopback_bcx_in = bcx.fcx.new_id_block("for_loopback", head.id); let body_bcx_in = bcx.fcx.new_id_block("for_body", body.id); bcx.fcx.push_loop_cleanup_scope(loop_info.id, - [next_bcx_in, loopback_bcx_in]); - Br(bcx, loopback_bcx_in.llbb); + [next_bcx_in.data, loopback_bcx_in.data]); + Br(bcx, loopback_bcx_in.data.llbb); let cleanup_llbb = bcx.fcx.normal_exit_block(loop_info.id, cleanup::EXIT_BREAK); @@ -351,7 +351,7 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, None); let i1_type = Type::i1(loopback_bcx_out.ccx()); let llcondition = Trunc(loopback_bcx_out, lldiscriminant, i1_type); - CondBr(loopback_bcx_out, llcondition, body_bcx_in.llbb, cleanup_llbb); + CondBr(loopback_bcx_out, llcondition, body_bcx_in.data.llbb, cleanup_llbb); // Now we're in the body. Unpack the `Option` value into the programmer- // supplied pattern. @@ -381,17 +381,17 @@ pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, body_bcx_out.fcx .pop_and_trans_custom_cleanup_scope(body_bcx_out, option_cleanup_scope); - Br(body_bcx_out, loopback_bcx_in.llbb); + Br(body_bcx_out, loopback_bcx_in.data.llbb); // Codegen cleanups and leave. next_bcx_in.fcx.pop_loop_cleanup_scope(loop_info.id); next_bcx_in } -pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_loop<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, loop_id: ast::NodeId, body: &ast::Block) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_loop"); let fcx = bcx.fcx; @@ -409,26 +409,26 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let next_bcx_in = bcx.fcx.new_id_block("loop_exit", loop_id); let body_bcx_in = bcx.fcx.new_id_block("loop_body", body.id); - fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in, body_bcx_in]); + fcx.push_loop_cleanup_scope(loop_id, [next_bcx_in.data, body_bcx_in.data]); - Br(bcx, body_bcx_in.llbb); + Br(bcx, body_bcx_in.data.llbb); let body_bcx_out = trans_block(body_bcx_in, body, expr::Ignore); - Br(body_bcx_out, body_bcx_in.llbb); + Br(body_bcx_out, body_bcx_in.data.llbb); fcx.pop_loop_cleanup_scope(loop_id); return next_bcx_in; } -pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_break_cont<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr_id: ast::NodeId, opt_label: Option, exit: uint) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_break_cont"); let fcx = bcx.fcx; - if bcx.unreachable.get() { + if bcx.data.unreachable.get() { return bcx; } @@ -453,23 +453,23 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_break<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr_id: ast::NodeId, label_opt: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_BREAK); } -pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_cont<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr_id: ast::NodeId, label_opt: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { return trans_break_cont(bcx, expr_id, label_opt, cleanup::EXIT_LOOP); } -pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - e: Option<&ast::Expr>) - -> Block<'blk, 'tcx> { +pub fn trans_ret<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + e: Option<&ast::Expr>) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_ret"); let fcx = bcx.fcx; let mut bcx = bcx; @@ -495,10 +495,10 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_fail<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, sp: Span, fail_str: InternedString) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_value"); @@ -519,11 +519,11 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_fail_bounds_check<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, sp: Span, index: ValueRef, len: ValueRef) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_bounds_check"); diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index 8b52732f4ee97..3ccf258d80664 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -47,8 +47,8 @@ pub struct Datum<'tcx, K> { pub kind: K, } -pub struct DatumBlock<'blk, 'tcx: 'blk, K> { - pub bcx: Block<'blk, 'tcx>, +pub struct DatumBlock<'fcx, 'blk: 'fcx, 'tcx: 'blk, K> { + pub bcx: Block<'fcx, 'blk, 'tcx>, pub datum: Datum<'tcx, K>, } @@ -96,10 +96,10 @@ pub fn immediate_rvalue<'tcx>(val: ValueRef, ty: Ty<'tcx>) -> Datum<'tcx, Rvalue return Datum::new(val, ty, Rvalue::new(ByValue)); } -pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn immediate_rvalue_bcx<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, ty: Ty<'tcx>) - -> DatumBlock<'blk, 'tcx, Rvalue> { + -> DatumBlock<'fcx, 'blk, 'tcx, Rvalue> { return DatumBlock::new(bcx, immediate_rvalue(val, ty)) } @@ -108,15 +108,15 @@ pub fn immediate_rvalue_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// it. The memory will be dropped upon exit from `scope`. The callback `populate` should /// initialize the memory. If `zero` is true, the space will be zeroed when it is allocated; this /// is not necessary unless `bcx` does not dominate the end of `scope`. -pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, +pub fn lvalue_scratch_datum<'fcx, 'blk, 'tcx, A, F>(bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, name: &str, zero: bool, scope: cleanup::ScopeId, arg: A, populate: F) - -> DatumBlock<'blk, 'tcx, Lvalue> where - F: FnOnce(A, Block<'blk, 'tcx>, ValueRef) -> Block<'blk, 'tcx>, + -> DatumBlock<'fcx, 'blk, 'tcx, Lvalue> where + F: FnOnce(A, Block<'fcx, 'blk, 'tcx>, ValueRef) -> Block<'fcx, 'blk, 'tcx>, { let scratch = if zero { alloca_zeroed(bcx, ty, name) @@ -138,7 +138,7 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>, /// necessary, but in the case of automatic rooting in match statements it is possible to have /// temporaries that may not get initialized if a certain arm is not taken, so we must zero them. /// You must arrange any cleanups etc yourself! -pub fn rvalue_scratch_datum<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn rvalue_scratch_datum<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, name: &str) -> Datum<'tcx, Rvalue> { @@ -158,8 +158,8 @@ pub fn appropriate_rvalue_mode<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -fn add_rvalue_clean<'a, 'tcx>(mode: RvalueMode, - fcx: &FunctionContext<'a, 'tcx>, +fn add_rvalue_clean<'fcx, 'blk, 'tcx>(mode: RvalueMode, + fcx: &FunctionContext<'blk, 'tcx>, scope: cleanup::ScopeId, val: ValueRef, ty: Ty<'tcx>) { @@ -176,11 +176,11 @@ pub trait KindOps { /// Take appropriate action after the value in `datum` has been /// stored to a new location. - fn post_store<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, - val: ValueRef, - ty: Ty<'tcx>) - -> Block<'blk, 'tcx>; + fn post_store<'fcx, 'blk, 'tcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, + val: ValueRef, + ty: Ty<'tcx>) + -> Block<'fcx, 'blk, 'tcx>; /// True if this mode is a reference mode, meaning that the datum's /// val field is a pointer to the actual value @@ -192,11 +192,11 @@ pub trait KindOps { } impl KindOps for Rvalue { - fn post_store<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, + fn post_store<'fcx, 'blk, 'tcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, _val: ValueRef, _ty: Ty<'tcx>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { // No cleanup is scheduled for an rvalue, so we don't have // to do anything after a move to cancel or duplicate it. bcx @@ -214,11 +214,11 @@ impl KindOps for Rvalue { impl KindOps for Lvalue { /// If an lvalue is moved, we must zero out the memory in which it resides so as to cancel /// cleanup. If an @T lvalue is copied, we must increment the reference count. - fn post_store<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, + fn post_store<'fcx, 'blk, 'tcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, ty: Ty<'tcx>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { if type_needs_drop(bcx.tcx(), ty) { // cancel cleanup of affine values by zeroing out let () = zero_mem(bcx, val, ty); @@ -238,11 +238,11 @@ impl KindOps for Lvalue { } impl KindOps for Expr { - fn post_store<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, + fn post_store<'fcx, 'blk, 'tcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, ty: Ty<'tcx>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { match *self { LvalueExpr => Lvalue.post_store(bcx, val, ty), RvalueExpr(ref r) => r.post_store(bcx, val, ty), @@ -265,21 +265,21 @@ impl<'tcx> Datum<'tcx, Rvalue> { /// Schedules a cleanup for this datum in the given scope. That means that this datum is no /// longer an rvalue datum; hence, this function consumes the datum and returns the contained /// ValueRef. - pub fn add_clean<'a>(self, - fcx: &FunctionContext<'a, 'tcx>, - scope: cleanup::ScopeId) - -> ValueRef { + pub fn add_clean<'blk>(self, + fcx: &FunctionContext<'blk, 'tcx>, + scope: cleanup::ScopeId) + -> ValueRef { add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty); self.val } /// Returns an lvalue datum (that is, a by ref datum with cleanup scheduled). If `self` is not /// already an lvalue, cleanup will be scheduled in the temporary scope for `expr_id`. - pub fn to_lvalue_datum_in_scope<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn to_lvalue_datum_in_scope<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, name: &str, scope: cleanup::ScopeId) - -> DatumBlock<'blk, 'tcx, Lvalue> { + -> DatumBlock<'fcx, 'blk, 'tcx, Lvalue> { let fcx = bcx.fcx; match self.kind.mode { @@ -296,8 +296,8 @@ impl<'tcx> Datum<'tcx, Rvalue> { } } - pub fn to_ref_datum<'blk>(self, bcx: Block<'blk, 'tcx>) - -> DatumBlock<'blk, 'tcx, Rvalue> { + pub fn to_ref_datum<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>) + -> DatumBlock<'fcx, 'blk, 'tcx, Rvalue> { let mut bcx = bcx; match self.kind.mode { ByRef => DatumBlock::new(bcx, self), @@ -309,8 +309,8 @@ impl<'tcx> Datum<'tcx, Rvalue> { } } - pub fn to_appropriate_datum<'blk>(self, bcx: Block<'blk, 'tcx>) - -> DatumBlock<'blk, 'tcx, Rvalue> { + pub fn to_appropriate_datum<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>) + -> DatumBlock<'fcx, 'blk, 'tcx, Rvalue> { match self.appropriate_rvalue_mode(bcx.ccx()) { ByRef => { self.to_ref_datum(bcx) @@ -354,11 +354,11 @@ impl<'tcx> Datum<'tcx, Expr> { |_| bcx.sess().bug("assert_lvalue given rvalue")) } - pub fn store_to_dest<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn store_to_dest<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, dest: expr::Dest, expr_id: ast::NodeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { match dest { expr::Ignore => { self.add_clean_if_rvalue(bcx, expr_id); @@ -372,8 +372,8 @@ impl<'tcx> Datum<'tcx, Expr> { /// Arranges cleanup for `self` if it is an rvalue. Use when you are done working with a value /// that may need drop. - pub fn add_clean_if_rvalue<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn add_clean_if_rvalue<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, expr_id: ast::NodeId) { self.match_kind( |_| { /* Nothing to do, cleanup already arranged */ }, @@ -384,19 +384,19 @@ impl<'tcx> Datum<'tcx, Expr> { } /// Ensures that `self` will get cleaned up, if it is not an lvalue already. - pub fn clean<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn clean<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, name: &'static str, expr_id: ast::NodeId) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { self.to_lvalue_datum(bcx, name, expr_id).bcx } - pub fn to_lvalue_datum<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn to_lvalue_datum<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, name: &str, expr_id: ast::NodeId) - -> DatumBlock<'blk, 'tcx, Lvalue> { + -> DatumBlock<'fcx, 'blk, 'tcx, Lvalue> { debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx())); assert!(lltype_is_sized(bcx.tcx(), self.ty), @@ -410,10 +410,10 @@ impl<'tcx> Datum<'tcx, Expr> { } /// Ensures that we have an rvalue datum (that is, a datum with no cleanup scheduled). - pub fn to_rvalue_datum<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn to_rvalue_datum<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, name: &'static str) - -> DatumBlock<'blk, 'tcx, Rvalue> { + -> DatumBlock<'fcx, 'blk, 'tcx, Rvalue> { self.match_kind( |l| { let mut bcx = bcx; @@ -451,7 +451,7 @@ impl<'tcx> Datum<'tcx, Lvalue> { // datum may also be unsized _without the size information_. It is the // callers responsibility to package the result in some way to make a valid // datum in that case (e.g., by making a fat pointer or opened pair). - pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, + pub fn get_element<'fcx, 'blk, F>(&self, bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, gep: F) -> Datum<'tcx, Lvalue> where F: FnOnce(ValueRef) -> ValueRef, @@ -494,10 +494,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// Moves or copies this value into a new home, as appropriate depending on the type of the /// datum. This method consumes the datum, since it would be incorrect to go on using the datum /// if the value represented is affine (and hence the value is moved). - pub fn store_to<'blk>(self, - bcx: Block<'blk, 'tcx>, + pub fn store_to<'fcx, 'blk>(self, + bcx: Block<'fcx, 'blk, 'tcx>, dst: ValueRef) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { self.shallow_copy_raw(bcx, dst); self.kind.post_store(bcx, self.val, self.ty) @@ -511,10 +511,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// source value has been copied but not zeroed. Public methods are `store_to` (if you no /// longer need the source value) or `shallow_copy` (if you wish the source value to remain /// valid). - fn shallow_copy_raw<'blk>(&self, - bcx: Block<'blk, 'tcx>, + fn shallow_copy_raw<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, dst: ValueRef) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("copy_to_no_check"); if type_is_zero_size(bcx.ccx(), self.ty) { @@ -533,17 +533,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// Copies the value into a new location. This function always preserves the existing datum as /// a valid value. Therefore, it does not consume `self` and, also, cannot be applied to affine /// values (since they must never be duplicated). - pub fn shallow_copy<'blk>(&self, - bcx: Block<'blk, 'tcx>, + pub fn shallow_copy<'fcx, 'blk>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, dst: ValueRef) - -> Block<'blk, 'tcx> { - /*! - * Copies the value into a new location. This function always - * preserves the existing datum as a valid value. Therefore, - * it does not consume `self` and, also, cannot be applied to - * affine values (since they must never be duplicated). - */ - + -> Block<'fcx, 'blk, 'tcx> { assert!(!ty::type_moves_by_default(&ty::empty_parameter_environment(bcx.tcx()), DUMMY_SP, self.ty)); @@ -568,7 +561,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { /// responsibility to cleanup the value). For this to work, the value must be something /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is /// naturally passed around by value, and not by reference. - pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { + pub fn to_llscalarish<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>) -> ValueRef { assert!(!type_needs_drop(bcx.tcx(), self.ty)); assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue); if self.kind.is_by_ref() { @@ -578,34 +571,34 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { } } - pub fn to_llbool<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { + pub fn to_llbool<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>) -> ValueRef { assert!(ty::type_is_bool(self.ty)); self.to_llscalarish(bcx) } } -impl<'blk, 'tcx, K> DatumBlock<'blk, 'tcx, K> { - pub fn new(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, K>) - -> DatumBlock<'blk, 'tcx, K> { +impl<'fcx, 'blk, 'tcx, K> DatumBlock<'fcx, 'blk, 'tcx, K> { + pub fn new(bcx: Block<'fcx, 'blk, 'tcx>, datum: Datum<'tcx, K>) + -> DatumBlock<'fcx, 'blk, 'tcx, K> { DatumBlock { bcx: bcx, datum: datum } } } -impl<'blk, 'tcx, K: KindOps + fmt::Show> DatumBlock<'blk, 'tcx, K> { - pub fn to_expr_datumblock(self) -> DatumBlock<'blk, 'tcx, Expr> { +impl<'fcx, 'blk, 'tcx, K: KindOps + fmt::Show> DatumBlock<'fcx, 'blk, 'tcx, K> { + pub fn to_expr_datumblock(self) -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { DatumBlock::new(self.bcx, self.datum.to_expr_datum()) } } -impl<'blk, 'tcx> DatumBlock<'blk, 'tcx, Expr> { +impl<'fcx, 'blk, 'tcx> DatumBlock<'fcx, 'blk, 'tcx, Expr> { pub fn store_to_dest(self, dest: expr::Dest, - expr_id: ast::NodeId) -> Block<'blk, 'tcx> { + expr_id: ast::NodeId) -> Block<'fcx, 'blk, 'tcx> { let DatumBlock { bcx, datum } = self; datum.store_to_dest(bcx, dest, expr_id) } - pub fn to_llbool(self) -> Result<'blk, 'tcx> { + pub fn to_llbool(self) -> Result<'fcx, 'blk, 'tcx> { let DatumBlock { datum, bcx } = self; Result::new(bcx, datum.to_llbool(bcx)) } diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 2f58baab7fca9..cbab154e17a6d 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -854,7 +854,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, /// local in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { - if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { + if bcx.data.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -892,13 +892,13 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) { /// Creates debug information for a variable captured in a closure. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn create_captured_var_metadata<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, node_id: ast::NodeId, env_pointer: ValueRef, env_index: uint, captured_by_ref: bool, span: Span) { - if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { + if bcx.data.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -978,10 +978,10 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// match-statement arm. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn create_match_binding_metadata<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, variable_ident: ast::Ident, binding: BindingInfo<'tcx>) { - if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { + if bcx.data.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -1021,7 +1021,7 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// argument in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { - if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { + if bcx.data.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -1075,7 +1075,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) { /// loop variable in `bcx.fcx.lllocals`. /// Adds the created metadata nodes directly to the crate's IR. pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) { - if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) { + if bcx.data.unreachable.get() || fn_should_be_ignored(bcx.fcx) { return; } @@ -1649,7 +1649,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { } } -fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn declare_local<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, variable_ident: ast::Ident, variable_type: Ty<'tcx>, scope_metadata: DIScope, @@ -1715,7 +1715,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DIB(cx), var_alloca, var_metadata, - bcx.llbb); + bcx.data.llbb); llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index ac50445be2f9b..53ad7e91c7d17 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -93,10 +93,10 @@ impl Dest { /// This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` but it may generate /// better optimized LLVM code. -pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_into<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let mut bcx = bcx; if bcx.tcx().adjustments.borrow().contains_key(&expr.id) { @@ -134,9 +134,9 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Translates an expression, returning a datum (and new block) encapsulating the result. When /// possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the /// stack. -pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { debug!("trans(expr={})", bcx.expr_to_string(expr)); let mut bcx = bcx; @@ -163,10 +163,10 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { /// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted /// translation of `expr`. -fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn apply_adjustments<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let mut datum = datum; let adjustment = match bcx.tcx().adjustments.borrow().get(&expr.id).cloned() { @@ -234,11 +234,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("after adjustments, datum={}", datum.to_string(bcx.ccx())); return DatumBlock::new(bcx, datum); - fn apply_autoref<'blk, 'tcx>(autoref: &ty::AutoRef<'tcx>, - bcx: Block<'blk, 'tcx>, + fn apply_autoref<'fcx, 'blk, 'tcx>(autoref: &ty::AutoRef<'tcx>, + bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let mut datum = datum; @@ -271,10 +271,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, datum) } - fn ref_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn ref_ptr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { debug!("ref_ptr(expr={}, datum={})", expr.repr(bcx.tcx()), datum.to_string(bcx.ccx())); @@ -297,7 +297,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // into a type to be destructed. If we want to end up with a Box pointer, // then mk_ty should make a Box pointer (T -> Box), if we want a // borrowed reference then it should be T -> &T. - fn unsized_info<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, + fn unsized_info<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, kind: &ty::UnsizeKind<'tcx>, id: ast::NodeId, unadjusted_ty: Ty<'tcx>, @@ -337,11 +337,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } - fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn unsize_expr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, k: &ty::UnsizeKind<'tcx>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let tcx = bcx.tcx(); let datum_ty = datum.ty; let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span); @@ -376,10 +376,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } - fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn ref_fat_ptr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let tcx = bcx.tcx(); let dest_ty = ty::close_type(tcx, datum.ty); let base = |: bcx, val| Load(bcx, get_dataptr(bcx, val)); @@ -387,15 +387,15 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, into_fat_ptr(bcx, expr, datum, dest_ty, base, len) } - fn into_fat_ptr<'blk, 'tcx, F, G>(bcx: Block<'blk, 'tcx>, + fn into_fat_ptr<'fcx, 'blk, 'tcx, F, G>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, dest_ty: Ty<'tcx>, base: F, info: G) - -> DatumBlock<'blk, 'tcx, Expr> where - F: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef, - G: FnOnce(Block<'blk, 'tcx>, ValueRef) -> ValueRef, + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> where + F: FnOnce(Block<'fcx, 'blk, 'tcx>, ValueRef) -> ValueRef, + G: FnOnce(Block<'fcx, 'blk, 'tcx>, ValueRef) -> ValueRef, { let mut bcx = bcx; @@ -412,11 +412,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, scratch.to_expr_datum()) } - fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn unsize_unique_vec<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, len: uint) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let tcx = bcx.tcx(); @@ -440,11 +440,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, scratch.to_expr_datum()) } - fn unsize_unique_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn unsize_unique_expr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, k: &ty::UnsizeKind<'tcx>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let tcx = bcx.tcx(); @@ -483,10 +483,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// something like `x().f` is translated into roughly the equivalent of /// /// { tmp = x(); tmp.f } -pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_to_lvalue<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, name: &str) - -> DatumBlock<'blk, 'tcx, Lvalue> { + -> DatumBlock<'fcx, 'blk, 'tcx, Lvalue> { let mut bcx = bcx; let datum = unpack_datum!(bcx, trans(bcx, expr)); return datum.to_lvalue_datum(bcx, name, expr.id); @@ -494,9 +494,9 @@ pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// A version of `trans` that ignores adjustments. You almost certainly do not want to call this /// directly. -fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr)); @@ -545,17 +545,17 @@ fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } }; - fn nil<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>) - -> DatumBlock<'blk, 'tcx, Expr> { + fn nil<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>) + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let llval = C_undef(type_of::type_of(bcx.ccx(), ty)); let datum = immediate_rvalue(llval, ty); DatumBlock::new(bcx, datum.to_expr_datum()) } } -fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_datum_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let fcx = bcx.fcx; let _icx = push_ctxt("trans_datum_unadjusted"); @@ -630,10 +630,10 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +fn trans_field<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, base: &ast::Expr, get_idx: F) - -> DatumBlock<'blk, 'tcx, Expr> where + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> where F: FnOnce(&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]) -> uint, { let mut bcx = bcx; @@ -665,27 +665,27 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, } /// Translates `base.field`. -fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_rec_field<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, base: &ast::Expr, field: ast::Ident) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { trans_field(bcx, base, |tcx, field_tys| ty::field_idx_strict(tcx, field.name, field_tys)) } /// Translates `base.`. -fn trans_rec_tup_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_rec_tup_field<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, base: &ast::Expr, idx: uint) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { trans_field(bcx, base, |_, _| idx) } -fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_index<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, index_expr: &ast::Expr, base: &ast::Expr, idx: &ast::Expr, method_call: MethodCall) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { //! Translates `base[idx]`. let _icx = push_ctxt("trans_index"); @@ -796,10 +796,10 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, elt_datum) } -fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_def<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ref_expr: &ast::Expr, def: def::Def) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { //! Translates a reference to a path. let _icx = push_ctxt("trans_def_lvalue"); @@ -820,7 +820,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // pointer to that. let const_ty = expr_ty(bcx, ref_expr); - fn get_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, did: ast::DefId, + fn get_val<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, did: ast::DefId, const_ty: Ty<'tcx>) -> ValueRef { // For external constants, we don't inline. if did.krate == ast::LOCAL_CRATE { @@ -874,13 +874,13 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_rvalue_stmt_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let mut bcx = bcx; let _icx = push_ctxt("trans_rvalue_stmt"); - if bcx.unreachable.get() { + if bcx.data.unreachable.get() { return bcx; } @@ -983,10 +983,10 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_rvalue_dps_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_rvalue_dps_unadjusted"); let mut bcx = bcx; let tcx = bcx.tcx(); @@ -1188,11 +1188,11 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_def_dps_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ref_expr: &ast::Expr, def: def::Def, dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_def_dps_unadjusted"); let lldest = match dest { @@ -1268,7 +1268,7 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } /// Translates a reference to a local variable or argument. This always results in an lvalue datum. -pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_local_var<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, def: def::Def) -> Datum<'tcx, Lvalue> { let _icx = push_ctxt("trans_local_var"); @@ -1364,13 +1364,13 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, } } -fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_struct<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, fields: &[ast::Field], base: Option<&ast::Expr>, expr_span: codemap::Span, expr_id: ast::NodeId, ty: Ty<'tcx>, - dest: Dest) -> Block<'blk, 'tcx> { + dest: Dest) -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_rec"); let tcx = bcx.tcx(); @@ -1443,14 +1443,14 @@ pub struct StructBaseInfo<'a, 'tcx> { /// /// - `optbase` contains information on the base struct (if any) from /// which remaining fields are copied; see comments on `StructBaseInfo`. -pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +pub fn trans_adt<'a, 'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, discr: ty::Disr, fields: &[(uint, &ast::Expr)], optbase: Option>, dest: Dest, source_location: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_adt"); let fcx = bcx.fcx; let repr = adt::represent_type(bcx.ccx(), ty); @@ -1549,10 +1549,10 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } -fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_immediate_lit<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, lit: &ast::Lit) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { // must not be a string constant, that is a RvalueDpsExpr let _icx = push_ctxt("trans_immediate_lit"); let ty = expr_ty(bcx, expr); @@ -1560,11 +1560,11 @@ fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, immediate_rvalue_bcx(bcx, v, ty).to_expr_datumblock() } -fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_unary<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, op: ast::UnOp, sub_expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let ccx = bcx.ccx(); let mut bcx = bcx; let _icx = push_ctxt("trans_unary_datum"); @@ -1608,11 +1608,11 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_uniq_expr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, box_ty: Ty<'tcx>, contents: &ast::Expr, contents_ty: Ty<'tcx>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_uniq_expr"); let fcx = bcx.fcx; assert!(type_is_sized(bcx.tcx(), contents_ty)); @@ -1637,10 +1637,10 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock() } -fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_addr_of<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, subexpr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_addr_of"); let mut bcx = bcx; let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of")); @@ -1670,7 +1670,7 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Important to get types for both lhs and rhs, because one might be _|_ // and the other not. -fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_eager_binop<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, binop_expr: &ast::Expr, binop_ty: Ty<'tcx>, op: ast::BinOp, @@ -1678,7 +1678,7 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lhs: ValueRef, rhs_t: Ty<'tcx>, rhs: ValueRef) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_eager_binop"); let tcx = bcx.tcx(); @@ -1766,12 +1766,12 @@ enum lazy_binop_ty { lazy_or, } -fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_lazy_binop<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, binop_expr: &ast::Expr, op: lazy_binop_ty, a: &ast::Expr, b: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_lazy_binop"); let binop_ty = expr_ty(bcx, binop_expr); let fcx = bcx.fcx; @@ -1779,7 +1779,7 @@ fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let DatumBlock {bcx: past_lhs, datum: lhs} = trans(bcx, a); let lhs = lhs.to_llscalarish(past_lhs); - if past_lhs.unreachable.get() { + if past_lhs.data.unreachable.get() { return immediate_rvalue_bcx(past_lhs, lhs, binop_ty).to_expr_datumblock(); } @@ -1787,30 +1787,30 @@ fn trans_lazy_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let before_rhs = fcx.new_id_block("before_rhs", b.id); match op { - lazy_and => CondBr(past_lhs, lhs, before_rhs.llbb, join.llbb), - lazy_or => CondBr(past_lhs, lhs, join.llbb, before_rhs.llbb) + lazy_and => CondBr(past_lhs, lhs, before_rhs.data.llbb, join.data.llbb), + lazy_or => CondBr(past_lhs, lhs, join.data.llbb, before_rhs.data.llbb) } let DatumBlock {bcx: past_rhs, datum: rhs} = trans(before_rhs, b); let rhs = rhs.to_llscalarish(past_rhs); - if past_rhs.unreachable.get() { + if past_rhs.data.unreachable.get() { return immediate_rvalue_bcx(join, lhs, binop_ty).to_expr_datumblock(); } - Br(past_rhs, join.llbb); + Br(past_rhs, join.data.llbb); let phi = Phi(join, Type::i1(bcx.ccx()), &[lhs, rhs], - &[past_lhs.llbb, past_rhs.llbb]); + &[past_lhs.data.llbb, past_rhs.data.llbb]); return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock(); } -fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_binary<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_binary"); let ccx = bcx.ccx(); @@ -1847,14 +1847,14 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_overloaded_op<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, method_call: MethodCall, lhs: Datum<'tcx, Expr>, rhs: Vec<(Datum<'tcx, Expr>, ast::NodeId)>, dest: Option, autoref: bool) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty; callee::trans_call_inner(bcx, Some(expr_info(expr)), @@ -1869,12 +1869,12 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest) } -fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +fn trans_overloaded_call<'a, 'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, callee: &'a ast::Expr, args: &'a [P], dest: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let method_call = MethodCall::expr(expr.id); let method_type = (*bcx.tcx() .method_map @@ -1974,10 +1974,10 @@ fn cast_is_noop<'tcx>(t_in: Ty<'tcx>, t_out: Ty<'tcx>) -> bool { } } -fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_imm_cast<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, id: ast::NodeId) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_cast"); let mut bcx = bcx; let ccx = bcx.ccx(); @@ -2066,12 +2066,12 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock(); } -fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_assign_op<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, op: ast::BinOp, dst: &ast::Expr, src: &ast::Expr) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_assign_op"); let mut bcx = bcx; @@ -2098,10 +2098,10 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return result_datum.store_to(bcx, dst_datum.val); } -fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn auto_ref<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, datum: Datum<'tcx, Expr>, expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; // Ensure cleanup of `datum` if not already scheduled and obtain @@ -2122,11 +2122,11 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(llref, ptr_ty, RvalueExpr(Rvalue::new(ByValue)))) } -fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn deref_multiple<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, times: uint) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let mut datum = datum; for i in range(0, times) { @@ -2136,11 +2136,11 @@ fn deref_multiple<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock { bcx: bcx, datum: datum } } -fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn deref_once<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, method_call: MethodCall) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let ccx = bcx.ccx(); debug!("deref_once(expr={}, datum={}, method_call={:?})", @@ -2243,11 +2243,11 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that /// the contents are not yet scheduled to be freed. The language rules ensure that the contents /// will be used (or moved) before the free occurs. - fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn deref_owned_pointer<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, content_ty: Ty<'tcx>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { match datum.kind { RvalueExpr(Rvalue { mode: ByRef }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index fb61bab6ade2c..0682f08451958 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -212,13 +212,13 @@ pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, /// can derive these from callee_ty but in the case of variadic /// functions passed_arg_tys will include the Rust type of all /// the arguments including the ones not specified in the fn's signature. -pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_native_call<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, callee_ty: Ty<'tcx>, llfn: ValueRef, llretptr: ValueRef, llargs_rust: &[ValueRef], passed_arg_tys: Vec>) - -> Block<'blk, 'tcx> + -> Block<'fcx, 'blk, 'tcx> { let ccx = bcx.ccx(); let tcx = bcx.tcx(); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index a79bb6ca16470..0ad0aab8c0ecb 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -45,9 +45,9 @@ use std::ffi::CString; use syntax::ast; use syntax::parse::token; -pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, +pub fn trans_exchange_free_dyn<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, size: ValueRef, align: ValueRef) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_exchange_free"); let ccx = cx.ccx(); callee::trans_lang_call(cx, @@ -56,14 +56,14 @@ pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, Some(expr::Ignore)).bcx } -pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, - size: u64, align: u32) -> Block<'blk, 'tcx> { +pub fn trans_exchange_free<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, + size: u64, align: u32) -> Block<'fcx, 'blk, 'tcx> { trans_exchange_free_dyn(cx, v, C_uint(cx.ccx(), size), C_uint(cx.ccx(), align)) } -pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, - content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> { +pub fn trans_exchange_free_ty<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ptr: ValueRef, + content_ty: Ty<'tcx>) -> Block<'fcx, 'blk, 'tcx> { assert!(type_is_sized(bcx.ccx().tcx(), content_ty)); let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); @@ -103,11 +103,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } } -pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn drop_ty<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>, source_location: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { // NB: v is an *alias* of type t here, not a direct value. debug!("drop_ty(t={})", t.repr(bcx.tcx())); let _icx = push_ctxt("drop_ty"); @@ -131,11 +131,11 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx } -pub fn drop_ty_immediate<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn drop_ty_immediate<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, t: Ty<'tcx>, source_location: Option) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("drop_ty_immediate"); let vp = alloca(bcx, type_of(bcx.ccx(), t), ""); store_ty(bcx, v, vp, t); @@ -186,13 +186,13 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val glue } -fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +fn trans_struct_drop_flag<'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, t: Ty<'tcx>, v0: ValueRef, dtor_did: ast::DefId, class_did: ast::DefId, substs: &subst::Substs<'tcx>) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let repr = adt::represent_type(bcx.ccx(), t); let struct_data = if type_is_sized(bcx.tcx(), t) { v0 @@ -206,13 +206,13 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }) } -fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_struct_drop<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, t: Ty<'tcx>, v0: ValueRef, dtor_did: ast::DefId, class_did: ast::DefId, substs: &subst::Substs<'tcx>) - -> Block<'blk, 'tcx> + -> Block<'fcx, 'blk, 'tcx> { let repr = adt::represent_type(bcx.ccx(), t); @@ -302,8 +302,10 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }) } -fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: ValueRef) - -> (ValueRef, ValueRef) { +fn size_and_align_of_dst<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + t: Ty<'tcx>, + info: ValueRef) + -> (ValueRef, ValueRef) { debug!("calculate size of DST: {}; with lost info: {}", bcx.ty_to_string(t), bcx.val_to_string(info)); if type_is_sized(bcx.tcx(), t) { @@ -358,8 +360,8 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: } } -fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) - -> Block<'blk, 'tcx> { +fn make_drop_glue<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>) + -> Block<'fcx, 'blk, 'tcx> { // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_drop_glue"); match t.sty { @@ -527,7 +529,8 @@ fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>, helper: F, name: &str) -> ValueRef where - F: for<'blk> FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + F: for<'fcx, 'blk> FnOnce(Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) + -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("make_generic_glue"); let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t)); diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 91c7409182df6..aff6f126d02bf 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -142,7 +142,7 @@ pub fn check_intrinsics(ccx: &CrateContext) { ccx.sess().abort_if_errors(); } -pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, +pub fn trans_intrinsic_call<'a, 'fcx, 'blk, 'tcx>(mut bcx: Block<'fcx, 'blk, 'tcx>, node: ast::NodeId, callee_ty: Ty<'tcx>, cleanup_scope: cleanup::CustomScopeIndex, @@ -150,7 +150,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, dest: expr::Dest, substs: subst::Substs<'tcx>, call_info: NodeInfo) - -> Result<'blk, 'tcx> + -> Result<'fcx, 'blk, 'tcx> { let fcx = bcx.fcx; let ccx = fcx.ccx; @@ -620,7 +620,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Result::new(bcx, llresult) } -fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn copy_intrinsic<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, allow_overlap: bool, volatile: bool, tp_ty: Ty<'tcx>, dst: ValueRef, src: ValueRef, count: ValueRef) -> ValueRef { let ccx = bcx.ccx(); @@ -650,7 +650,7 @@ fn copy_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, C_bool(ccx, volatile)], None) } -fn memset_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, volatile: bool, tp_ty: Ty<'tcx>, +fn memset_intrinsic<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, volatile: bool, tp_ty: Ty<'tcx>, dst: ValueRef, val: ValueRef, count: ValueRef) -> ValueRef { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); @@ -675,7 +675,7 @@ fn count_zeros_intrinsic(bcx: Block, name: &'static str, val: ValueRef) -> Value Call(bcx, llfn, &[val, y], None) } -fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, name: &'static str, +fn with_overflow_intrinsic<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, name: &'static str, t: Ty<'tcx>, a: ValueRef, b: ValueRef) -> ValueRef { let llfn = bcx.ccx().get_intrinsic(&name); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7ac062108f3fb..2ad167bcd91f2 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -103,11 +103,11 @@ pub fn trans_impl(ccx: &CrateContext, } } -pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_method_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, method_call: MethodCall, self_expr: Option<&ast::Expr>, arg_cleanup_scope: cleanup::ScopeId) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("meth::trans_method_callee"); let (origin, method_ty) = @@ -317,12 +317,12 @@ fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name) meth_did.def_id() } -fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_monomorphized_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, method_call: MethodCall, trait_id: ast::DefId, n_method: uint, vtable: traits::Vtable<'tcx, ()>) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("meth::trans_monomorphized_callee"); match vtable { traits::VtableImpl(vtable_impl) => { @@ -393,7 +393,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// In that case, the vector we want is: `[X, M1, M2, M3]`. Therefore, what we do now is to slice /// off the method type parameters and append them to the type parameters from the type that the /// receiver is mapped to. -fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn combine_impl_and_methods_tps<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, node: ExprOrMethodCall, rcvr_substs: subst::Substs<'tcx>) -> subst::Substs<'tcx> @@ -424,12 +424,12 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// In this case, we must pull the fn pointer out of the vtable that is packaged up with the /// object. Objects are represented as a pair, so we first evaluate the self expression and then /// extract the self data and vtable out of the pair. -fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_trait_callee<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, method_ty: Ty<'tcx>, n_method: uint, self_expr: &ast::Expr, arg_cleanup_scope: cleanup::ScopeId) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("meth::trans_trait_callee"); let mut bcx = bcx; @@ -461,11 +461,11 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Same as `trans_trait_callee()` above, except that it is given a by-ref pointer to the object /// pair. -pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_trait_callee_from_llval<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, callee_ty: Ty<'tcx>, n_method: uint, llpair: ValueRef) - -> Callee<'blk, 'tcx> { + -> Callee<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("meth::trans_trait_callee"); let ccx = bcx.ccx(); @@ -678,7 +678,7 @@ pub fn trans_object_shim<'a, 'tcx>( /// `trait_ref` would map `T:Trait`, but `box_ty` would be /// `Foo`. This `box_ty` is primarily used to encode the destructor. /// This will hopefully change now that DST is underway. -pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn get_vtable<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, box_ty: Ty<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> ValueRef @@ -784,7 +784,7 @@ pub fn make_vtable>(ccx: &CrateContext, } } -fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn emit_vtable_methods<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, impl_id: ast::DefId, substs: subst::Substs<'tcx>) -> Vec { @@ -843,12 +843,12 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Generates the code to convert from a pointer (`Box`, `&T`, etc) into an object /// (`Box`, `&Trait`, etc). This means creating a pair where the first word is the vtable /// and the second word is the pointer. -pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_trait_cast<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, datum: Datum<'tcx, Expr>, id: ast::NodeId, trait_ref: ty::PolyTraitRef<'tcx>, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let mut bcx = bcx; let _icx = push_ctxt("meth::trans_trait_cast"); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index e3288466aa79c..f67c5a4e6441c 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -51,11 +51,11 @@ pub fn pointer_add_byte(bcx: Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef return PointerCast(bcx, InBoundsGEP(bcx, bptr, &[bytes]), old_ty); } -pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn make_drop_glue_unboxed<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, vptr: ValueRef, unit_ty: Ty<'tcx>, should_deallocate: bool) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let not_null = IsNotNull(bcx, vptr); with_cond(bcx, not_null, |bcx| { let ccx = bcx.ccx(); @@ -109,10 +109,10 @@ impl<'tcx> VecTypes<'tcx> { } } -pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_fixed_vstore<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { //! // // [...] allocates a fixed-size array and moves it around "by value". @@ -139,10 +139,10 @@ pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// &[...] allocates memory on the stack and writes the values into it, returning the vector (the /// caller must make the reference). "..." is similar except that the memory can be statically /// allocated and we return a reference (strings are always by-ref). -pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_slice_vec<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, slice_expr: &ast::Expr, content_expr: &ast::Expr) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let fcx = bcx.fcx; let ccx = fcx.ccx; let mut bcx = bcx; @@ -202,11 +202,11 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Literal strings translate to slices into static memory. This is different from /// trans_slice_vstore() above because it doesn't need to copy the content anywhere. -pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_lit_str<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, lit_expr: &ast::Expr, str_lit: InternedString, dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { debug!("trans_lit_str(lit_expr={}, dest={})", bcx.expr_to_string(lit_expr), dest.to_string(bcx.ccx())); @@ -225,12 +225,12 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn write_content<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, vt: &VecTypes<'tcx>, vstore_expr: &ast::Expr, content_expr: &ast::Expr, dest: Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("tvec::write_content"); let fcx = bcx.fcx; let mut bcx = bcx; @@ -321,14 +321,14 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -pub fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn vec_types_from_expr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, vec_expr: &ast::Expr) -> VecTypes<'tcx> { let vec_ty = node_id_type(bcx, vec_expr.id); vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty)) } -pub fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn vec_types<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, unit_ty: Ty<'tcx>) -> VecTypes<'tcx> { let ccx = bcx.ccx(); @@ -416,13 +416,13 @@ pub fn get_base_and_len(bcx: Block, } } -pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +pub fn iter_vec_loop<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, data_ptr: ValueRef, vt: &VecTypes<'tcx>, count: ValueRef, f: F) - -> Block<'blk, 'tcx> where - F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnOnce(Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("tvec::iter_vec_loop"); let fcx = bcx.fcx; @@ -432,14 +432,14 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let cond_bcx = fcx.new_temp_block("expr_repeat: loop cond"); let body_bcx = fcx.new_temp_block("expr_repeat: body: set"); let inc_bcx = fcx.new_temp_block("expr_repeat: body: inc"); - Br(bcx, loop_bcx.llbb); + Br(bcx, loop_bcx.data.llbb); let loop_counter = { // i = 0 let i = alloca(loop_bcx, bcx.ccx().int_type(), "__i"); Store(loop_bcx, C_uint(bcx.ccx(), 0u), i); - Br(loop_bcx, cond_bcx.llbb); + Br(loop_bcx, cond_bcx.data.llbb); i }; @@ -448,7 +448,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let rhs = count; let cond_val = ICmp(cond_bcx, llvm::IntULT, lhs, rhs); - CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb); + CondBr(cond_bcx, cond_val, body_bcx.data.llbb, next_bcx.data.llbb); } { // loop body @@ -460,7 +460,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, }; let body_bcx = f(body_bcx, lleltptr, vt.unit_ty); - Br(body_bcx, inc_bcx.llbb); + Br(body_bcx, inc_bcx.data.llbb); } { // i += 1 @@ -468,19 +468,19 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1u)); Store(inc_bcx, plusone, loop_counter); - Br(inc_bcx, cond_bcx.llbb); + Br(inc_bcx, cond_bcx.data.llbb); } next_bcx } -pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, +pub fn iter_vec_raw<'fcx, 'blk, 'tcx, F>(bcx: Block<'fcx, 'blk, 'tcx>, data_ptr: ValueRef, unit_ty: Ty<'tcx>, len: ValueRef, f: F) - -> Block<'blk, 'tcx> where - F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>, + -> Block<'fcx, 'blk, 'tcx> where + F: FnOnce(Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'fcx, 'blk, 'tcx>, { let _icx = push_ctxt("tvec::iter_vec_raw"); let fcx = bcx.fcx; @@ -500,19 +500,19 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, // Now perform the iteration. let header_bcx = fcx.new_temp_block("iter_vec_loop_header"); - Br(bcx, header_bcx.llbb); + Br(bcx, header_bcx.data.llbb); let data_ptr = - Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.llbb]); + Phi(header_bcx, val_ty(data_ptr), &[data_ptr], &[bcx.data.llbb]); let not_yet_at_end = ICmp(header_bcx, llvm::IntULT, data_ptr, data_end_ptr); let body_bcx = fcx.new_temp_block("iter_vec_loop_body"); let next_bcx = fcx.new_temp_block("iter_vec_next"); - CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb); + CondBr(header_bcx, not_yet_at_end, body_bcx.data.llbb, next_bcx.data.llbb); let body_bcx = f(body_bcx, data_ptr, vt.unit_ty); AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr, &[C_int(bcx.ccx(), 1i)]), - body_bcx.llbb); - Br(body_bcx, header_bcx.llbb); + body_bcx.data.llbb); + Br(body_bcx, header_bcx.data.llbb); next_bcx } } diff --git a/src/librustc_trans/trans/value.rs b/src/librustc_trans/trans/value.rs index b6fd2eb57be27..1c3c50be3a193 100644 --- a/src/librustc_trans/trans/value.rs +++ b/src/librustc_trans/trans/value.rs @@ -58,7 +58,7 @@ impl Value { match self.get_single_user().and_then(|user| user.as_store_inst()) { Some(store) => { store.get_parent().and_then(|store_bb| { - let mut bb = BasicBlock(bcx.llbb); + let mut bb = BasicBlock(bcx.data.llbb); let mut ret = Some(store); while bb.get() != store_bb.get() { match bb.get_single_predecessor() { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index bfe43086aab10..a1ccda1b11594 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -119,7 +119,9 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.write_ty(expr.id, closure_type); let fn_sig = - ty::liberate_late_bound_regions(fcx.tcx(), CodeExtent::from_node_id(body.id), &fn_ty.sig); + ty::liberate_late_bound_regions(fcx.tcx(), + CodeExtent::DestructionScope(body.id), + &fn_ty.sig); check_fn(fcx.ccx, ast::Unsafety::Normal, diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs new file mode 100644 index 0000000000000..bbf78eb72892c --- /dev/null +++ b/src/librustc_typeck/check/dropck.rs @@ -0,0 +1,230 @@ +// Copyright 2014-2015 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. + +use check::regionck::{Rcx}; + +use middle::infer; +use middle::region; +use middle::subst; +use middle::ty::{self, Ty}; +use util::ppaux::{Repr}; + +use syntax::codemap::Span; + +pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, + typ: ty::Ty<'tcx>, + span: Span, + scope: region::CodeExtent) { + debug!("check_safety_of_destructor_if_necessary typ: {} scope: {:?}", + typ.repr(rcx.tcx()), scope); + + // types that have been traversed so far by `traverse_type_if_unseen` + let mut breadcrumbs: Vec> = Vec::new(); + + iterate_over_potentially_unsafe_regions_in_type( + rcx, + &mut breadcrumbs, + typ, + span, + scope, + false, + 0); +} + +fn constrain_region_for_destructor_safety(rcx: &mut Rcx, + region: ty::Region, + inner_scope: region::CodeExtent, + span: Span) { + debug!("constrain_region_for_destructor_safety region: {:?} inner_scope: {:?}", + region, inner_scope); + + // Ignore bound regions. + match region { + ty::ReEarlyBound(..) | ty::ReLateBound(..) => return, + ty::ReFree(_) | ty::ReScope(_) | ty::ReStatic | + ty::ReInfer(_) | ty::ReEmpty => {} + } + + // Get the parent scope. + let parent_inner_region = + match rcx.tcx().region_maps.opt_encl_scope(inner_scope) { + Some(parent_inner_scope) => ty::ReScope(parent_inner_scope), + None => + rcx.tcx().sess.span_bug( + span, format!("no enclosing scope found for inner_scope: {:?}", + inner_scope).as_slice()), + }; + + rcx.mk_subr(infer::SafeDestructor(span), + parent_inner_region, + region); +} + +fn traverse_type_if_unseen<'a, 'tcx, P>(rcx: &mut Rcx<'a, 'tcx>, + breadcrumbs: &mut Vec>, + typ: ty::Ty<'tcx>, + keep_going: P) -> bool where + P: Fn(&mut Rcx<'a, 'tcx>, &mut Vec>) -> bool, +{ + // Avoid recursing forever. + if !breadcrumbs.contains(&typ) { + breadcrumbs.push(typ); + let keep_going = keep_going(rcx, breadcrumbs); + + // You might be tempted to pop breadcrumbs here after the + // `keep_going` call, but then you hit exponential time + // blowup e.g. on compile-fail/huge-struct.rs. Instead, we + // do not remove anything from the breadcrumbs vector + // during any particular traversal, and instead clear it + // after the whole traversal is done. + + keep_going + } else { + false + } +} + + +fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( + rcx: &mut Rcx<'a, 'tcx>, + breadcrumbs: &mut Vec>, + typ: ty::Ty<'tcx>, + span: Span, + scope: region::CodeExtent, + reachable_by_destructor: bool, + depth: uint) +{ + ty::maybe_walk_ty(typ, |typ| { + // Avoid recursing forever. + traverse_type_if_unseen(rcx, breadcrumbs, typ, |rcx, breadcrumbs| { + debug!("iterate_over_potentially_unsafe_regions_in_type \ + {}typ: {} scope: {:?} reachable_by_destructor: {}", + (0..depth).map(|_| ' ').collect::(), + typ.repr(rcx.tcx()), scope, reachable_by_destructor); + + let keep_going = match typ.sty { + ty::ty_struct(structure_id, substitutions) => { + let reachable_by_destructor = + reachable_by_destructor || + ty::has_dtor(rcx.tcx(), structure_id); + + let fields = + ty::lookup_struct_fields(rcx.tcx(), + structure_id); + for field in fields.iter() { + let field_type = + ty::lookup_field_type(rcx.tcx(), + structure_id, + field.id, + substitutions); + iterate_over_potentially_unsafe_regions_in_type( + rcx, + breadcrumbs, + field_type, + span, + scope, + reachable_by_destructor, depth+1) + } + + false + } + ty::ty_enum(enumeration_id, substitutions) => { + let reachable_by_destructor = reachable_by_destructor || + ty::has_dtor(rcx.tcx(), enumeration_id); + + let all_variant_info = + ty::substd_enum_variants(rcx.tcx(), + enumeration_id, + substitutions); + for variant_info in all_variant_info.iter() { + for argument_type in variant_info.args.iter() { + iterate_over_potentially_unsafe_regions_in_type( + rcx, + breadcrumbs, + *argument_type, + span, + scope, + reachable_by_destructor, depth+1) + } + } + + false + } + ty::ty_rptr(region, _) => { + if reachable_by_destructor { + constrain_region_for_destructor_safety(rcx, + *region, + scope, + span) + } + // Don't recurse, since references do not own their + // contents. + false + } + ty::ty_unboxed_closure(..) => { + true + } + ty::ty_trait(ref trait_type) => { + if reachable_by_destructor { + match trait_type.principal.substs().regions { + subst::NonerasedRegions(ref regions) => { + for region in regions.iter() { + constrain_region_for_destructor_safety( + rcx, + *region, + scope, + span) + } + } + subst::ErasedRegions => {} + } + + // FIXME (pnkfelix): Added by pnkfelix, but + // need to double-check that this additional + // constraint is necessary. + constrain_region_for_destructor_safety( + rcx, + trait_type.bounds.region_bound, + scope, + span) + } + true + } + ty::ty_ptr(_) | ty::ty_bare_fn(..) => { + // Don't recurse, since pointers, boxes, and bare + // functions don't own instances of the types appearing + // within them. + false + } + ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | + ty::ty_float(_) | ty::ty_uniq(_) | ty::ty_str | + ty::ty_vec(..) | ty::ty_tup(_) | ty::ty_param(_) | + ty::ty_infer(_) | ty::ty_open(_) | ty::ty_err => true, + + ty::ty_projection(_) => { + // We keep going, since we want to descend into + // the substructure `Trait<..>` within the + // projection `>::N`. + // + // Furthermore, in the future, we are likely to + // support higher-kinded projections (i.e. an + // associated item that is parameterized over a + // lifetime). When that is supported, we will need + // to ensure that we constrain the input regions + // accordingly (which might go here, or might end + // up in some recursive part of the traversal). + true + } + }; + + keep_going + }) + }); +} diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index dc4d6c9a826c9..858b1d76a1359 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -498,12 +498,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { trait_def_id); let trait_impls = self.tcx().trait_impls.borrow(); - let impl_def_ids = match trait_impls.get(&trait_def_id) { + let impl_def_ids = trait_impls.get(&trait_def_id); + let impl_def_ids = match impl_def_ids { None => { return; } Some(impls) => impls, }; - for &impl_def_id in impl_def_ids.borrow().iter() { + let impl_def_ids = impl_def_ids.borrow(); + for &impl_def_id in impl_def_ids.iter() { debug!("assemble_extension_candidates_for_trait_impl: trait_def_id={} impl_def_id={}", trait_def_id.repr(self.tcx()), impl_def_id.repr(self.tcx())); @@ -998,8 +1000,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // if there are any. assert_eq!(substs.types.len(subst::FnSpace), 0); assert_eq!(substs.regions().len(subst::FnSpace), 0); - let mut substs = substs; let placeholder; + let mut substs = substs; if !method.generics.types.is_empty_in(subst::FnSpace) || !method.generics.regions.is_empty_in(subst::FnSpace) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7473f0223a669..b9c19176ae5d0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,7 +90,7 @@ use middle::lang_items::IteratorItem; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::pat_util::{self, pat_id_map}; -use middle::region::CodeExtent; +use middle::region::{CodeExtent}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::traits; use middle::ty::{FnSig, VariantInfo, TypeScheme}; @@ -126,6 +126,7 @@ use syntax::ptr::P; use syntax::visit::{self, Visitor}; mod assoc; +pub mod dropck; pub mod _match; pub mod vtable; pub mod writeback; @@ -478,7 +479,9 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fn_sig = fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs); let fn_sig = - liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig); + liberate_late_bound_regions(ccx.tcx, + CodeExtent::DestructionScope(body.id), + &fn_sig); let fn_sig = inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 3b5027dbb9e69..c59b8835aaa1d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -83,6 +83,7 @@ //! contents. use astconv::AstConv; +use check::dropck; use check::FnCtxt; use check::regionmanip; use check::vtable; @@ -171,6 +172,7 @@ pub struct Rcx<'a, 'tcx: 'a> { // id of AST node being analyzed (the subject of the analysis). subject: SubjectNode, + } /// Returns the validity region of `def` -- that is, how long is `def` valid? @@ -205,13 +207,21 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Rcx { fcx: fcx, repeating_scope: initial_repeating_scope, subject: subject, - region_bound_pairs: Vec::new() } + region_bound_pairs: Vec::new() + } } pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fcx.ccx.tcx } + pub fn mk_subr(&self, + origin: infer::SubregionOrigin<'tcx>, + sub: ty::Region, + sup: ty::Region) { + self.fcx.mk_subr(origin, sub, sup) + } + pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId { let old_scope = self.repeating_scope; self.repeating_scope = scope; @@ -465,6 +475,10 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) { type_of_node_must_outlive( rcx, infer::BindingTypeIsNotValidAtDecl(span), id, var_region); + + let var_scope = tcx.region_maps.var_scope(id); + let typ = rcx.resolve_node_type(id); + dropck::check_safety_of_destructor_if_necessary(rcx, typ, span, var_scope); }) } @@ -513,6 +527,40 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { */ _ => {} } + + // If necessary, constrain destructors in the unadjusted form of this + // expression. + let cmt_result = { + let mc = mc::MemCategorizationContext::new(rcx.fcx); + mc.cat_expr_unadjusted(expr) + }; + match cmt_result { + Ok(head_cmt) => { + check_safety_of_rvalue_destructor_if_necessary(rcx, + head_cmt, + expr.span); + } + Err(..) => { + rcx.fcx.tcx().sess.span_note(expr.span, + "cat_expr_unadjusted Errd during dtor check"); + } + } + } + + // If necessary, constrain destructors in this expression. This will be + // the adjusted form if there is an adjustment. + let cmt_result = { + let mc = mc::MemCategorizationContext::new(rcx.fcx); + mc.cat_expr(expr) + }; + match cmt_result { + Ok(head_cmt) => { + check_safety_of_rvalue_destructor_if_necessary(rcx, head_cmt, expr.span); + } + Err(..) => { + rcx.fcx.tcx().sess.span_note(expr.span, + "cat_expr Errd during dtor check"); + } } match expr.node { @@ -1018,6 +1066,33 @@ pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx, minimum_lifetime, maximum_lifetime) } +fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, + cmt: mc::cmt<'tcx>, + span: Span) { + match cmt.cat { + mc::cat_rvalue(region) => { + match region { + ty::ReScope(rvalue_scope) => { + let typ = rcx.resolve_type(cmt.ty); + dropck::check_safety_of_destructor_if_necessary(rcx, + typ, + span, + rvalue_scope); + } + ty::ReStatic => {} + region => { + rcx.tcx() + .sess + .span_bug(span, + format!("unexpected rvalue region in rvalue \ + destructor safety checking: `{}`", + region.repr(rcx.tcx())).as_slice()); + } + } + } + _ => {} + } +} /// Invoked on any index expression that occurs. Checks that if this is a slice being indexed, the /// lifetime of the pointer includes the deref expr. diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index 89de1ea80fcf4..c17c9049a31ad 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -22,7 +22,6 @@ use util::ppaux::Repr; use std::collections::HashSet; use syntax::ast; use syntax::ast_util::{local_def}; -use syntax::attr; use syntax::codemap::Span; use syntax::parse::token; use syntax::visit; @@ -118,6 +117,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item.span, region::CodeExtent::from_node_id(item.id), Some(&mut this.cache)); + debug!("check_type_defn at bounds_checker.scope: {:?}", bounds_checker.scope); + for variant in variants.iter() { for field in variant.fields.iter() { // Regions are checked below. @@ -153,6 +154,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item.span, region::CodeExtent::from_node_id(item.id), Some(&mut this.cache)); + debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope); let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id)); let item_ty = fcx.instantiate_type_scheme(item.span, @@ -167,12 +169,20 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { item: &ast::Item) { self.with_fcx(item, |this, fcx| { + + // FIXME (pnkfelix): what is the "extent" of an item impl? + // This seems fundamentally different from the dynamic + // extent represented by a block or a function body. + // + // For now, just leaving as the default you get via + // `fn CodeExtent::from_node_id`. let item_scope = region::CodeExtent::from_node_id(item.id); let mut bounds_checker = BoundsChecker::new(fcx, item.span, item_scope, Some(&mut this.cache)); + debug!("check_impl at bounds_checker.scope: {:?}", bounds_checker.scope); // Find the impl self type as seen from the "inside" -- // that is, with all type parameters converted from bound @@ -195,22 +205,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { &fcx.inh.param_env.free_substs, &trait_ref); - // There are special rules that apply to drop. - if - fcx.tcx().lang_items.drop_trait() == Some(trait_ref.def_id) && - !attr::contains_name(item.attrs.as_slice(), "unsafe_destructor") - { - match self_ty.sty { - ty::ty_struct(def_id, _) | - ty::ty_enum(def_id, _) => { - check_struct_safe_for_destructor(fcx, item.span, def_id); - } - _ => { - // Coherence already reports an error in this case. - } - } - } - if fcx.tcx().lang_items.copy_trait() == Some(trait_ref.def_id) { // This is checked in coherence. return @@ -420,8 +414,8 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { { self.binding_count += 1; let value = liberate_late_bound_regions(self.fcx.tcx(), self.scope, binder); - debug!("BoundsChecker::fold_binder: late-bound regions replaced: {}", - value.repr(self.tcx())); + debug!("BoundsChecker::fold_binder: late-bound regions replaced: {} at scope: {:?}", + value.repr(self.tcx()), self.scope); let value = value.fold_with(self); self.binding_count -= 1; ty::Binder(value) @@ -584,22 +578,3 @@ fn filter_to_trait_obligations<'tcx>(bounds: ty::GenericBounds<'tcx>) } result } - -/////////////////////////////////////////////////////////////////////////// -// Special drop trait checking - -fn check_struct_safe_for_destructor<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, - struct_did: ast::DefId) { - let struct_tpt = ty::lookup_item_type(fcx.tcx(), struct_did); - if struct_tpt.generics.has_type_params(subst::TypeSpace) - || struct_tpt.generics.has_region_params(subst::TypeSpace) - { - span_err!(fcx.tcx().sess, span, E0141, - "cannot implement a destructor on a structure \ - with type parameters"); - span_note!(fcx.tcx().sess, span, - "use \"#[unsafe_destructor]\" on the implementation \ - to force the compiler to allow this"); - } -} diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9d4aa23960db9..583e9ad9ae0b5 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -397,7 +397,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { Some(found_impls) => found_impls }; - for &impl_did in trait_impls.borrow().iter() { + let trait_impls = trait_impls.borrow(); + for &impl_did in trait_impls.iter() { let items = &(*impl_items)[impl_did]; if items.len() < 1 { // We'll error out later. For now, just don't ICE. diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c56952abc4419..bc3b2d967be86 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1547,7 +1547,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>( _ => typ, }; - let body_scope = region::CodeExtent::from_node_id(body_id); + let body_scope = region::CodeExtent::DestructionScope(body_id); // "Required type" comes from the trait definition. It may // contain late-bound regions from the method, but not the diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8929bbe0232ed..ba032eeaaf0bb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -300,9 +300,8 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "unsafe_destructor") { self.gate_feature("unsafe_destructor", i.span, - "`#[unsafe_destructor]` allows too \ - many unsafe patterns and may be \ - removed in the future"); + "`#[unsafe_destructor]` does nothing \ + anymore") } if attr::contains_name(&i.attrs[], diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index e340331dbfd11..dd1ad413a3d27 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -19,5 +19,6 @@ pub type header_map = HashMap>>>>; // the unused ty param is necessary so this gets monomorphized pub fn request(req: &header_map) { - let _x = req["METHOD".to_string()].clone().borrow().clone()[0].clone(); + let data = req["METHOD".to_string()].clone(); + let _x = data.borrow().clone()[0].clone(); } diff --git a/src/test/compile-fail/destructor-restrictions.rs b/src/test/compile-fail/destructor-restrictions.rs new file mode 100644 index 0000000000000..02887d18a681b --- /dev/null +++ b/src/test/compile-fail/destructor-restrictions.rs @@ -0,0 +1,21 @@ +// Copyright 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. + +// Tests the new destructor semantics. + +use std::cell::RefCell; + +fn main() { + let b = { + let a = box RefCell::new(4i); + *a.borrow() + 1i //~ ERROR `*a` does not live long enough + }; + println!("{}", b); +} diff --git a/src/test/run-pass/issue-13304.rs b/src/test/run-pass/issue-13304.rs index 11003c6fc524d..fbe073eef2c97 100644 --- a/src/test/run-pass/issue-13304.rs +++ b/src/test/run-pass/issue-13304.rs @@ -37,7 +37,8 @@ fn parent() { } fn child() { - for line in io::stdin().lock().lines() { + let mut stdin = io::stdin(); + for line in stdin.lock().lines() { println!("{}", line.unwrap()); - } + }; } diff --git a/src/test/run-pass/issue-14456.rs b/src/test/run-pass/issue-14456.rs index f5fdf8704ed25..302e191f670c0 100644 --- a/src/test/run-pass/issue-14456.rs +++ b/src/test/run-pass/issue-14456.rs @@ -27,7 +27,8 @@ fn main() { fn child() { io::stdout().write_line("foo").unwrap(); io::stderr().write_line("bar").unwrap(); - assert_eq!(io::stdin().lock().read_line().err().unwrap().kind, io::EndOfFile); + let mut stdin = io::stdin(); + assert_eq!(stdin.lock().read_line().err().unwrap().kind, io::EndOfFile); } fn test() { diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index cd71bfce27428..bd0ab605d070e 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -17,7 +17,7 @@ extern crate collections; use std::collections::HashMap; pub fn main() { - let mut buggy_map: HashMap = HashMap::new(); let x = box 1; + let mut buggy_map: HashMap = HashMap::new(); buggy_map.insert(42, &*x); } diff --git a/src/test/run-pass/multidispatch-conditional-impl-not-considered.rs b/src/test/run-pass/multidispatch-conditional-impl-not-considered.rs index 5db5a6267bf2b..49ecef9c7359a 100644 --- a/src/test/run-pass/multidispatch-conditional-impl-not-considered.rs +++ b/src/test/run-pass/multidispatch-conditional-impl-not-considered.rs @@ -29,5 +29,5 @@ impl Bar { fn main() { let b = RefCell::new(Bar); - b.borrow().foo() + b.borrow().foo(); } diff --git a/src/test/run-pass/regions-refcell.rs b/src/test/run-pass/regions-refcell.rs new file mode 100644 index 0000000000000..9122d2865e061 --- /dev/null +++ b/src/test/run-pass/regions-refcell.rs @@ -0,0 +1,36 @@ +// 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. + +// This is a regression test for something that only came up while +// attempting to bootstrap librustc with new destructor lifetime +// semantics. + +use std::collections::HashMap; +use std::cell::RefCell; + +fn foo(map: RefCell>) { + // assert_eq!(map.borrow().get("one"), Some(&1u)); + let map = map.borrow(); + for (i, &x) in map.get("one").unwrap().iter().enumerate() { + assert_eq!((i, x), (0u, 1u)); + } +} + +fn main() { + let zer = [0u]; + let one = [1u]; + let two = [2u]; + let mut map = HashMap::new(); + map.insert("zero", zer.as_slice()); + map.insert("one", one.as_slice()); + map.insert("two", two.as_slice()); + let map = RefCell::new(map); + foo(map); +} diff --git a/src/test/run-pass/regions-trait-object-1.rs b/src/test/run-pass/regions-trait-object-1.rs new file mode 100644 index 0000000000000..eb3bec7732666 --- /dev/null +++ b/src/test/run-pass/regions-trait-object-1.rs @@ -0,0 +1,43 @@ +// 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. + +// This is a regression test for something that only came up while +// attempting to bootstrap libsyntax; it is adapted from +// `syntax::ext::tt::generic_extension`. + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box; + } +} + +fn main() { + let w = E { f: &10u8 }; + let o = extension(&w); + assert_eq!(o.n(), 10u8); +} diff --git a/src/test/run-pass/trait-object-with-lifetime-bound.rs b/src/test/run-pass/trait-object-with-lifetime-bound.rs new file mode 100644 index 0000000000000..4e481910aa98f --- /dev/null +++ b/src/test/run-pass/trait-object-with-lifetime-bound.rs @@ -0,0 +1,42 @@ +// Copyright 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. + +// Uncovered during work on new scoping rules for safe destructors +// as an important use case to support properly. + +pub struct E<'a> { + pub f: &'a u8, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b u8 { self.f } +} + +pub struct P<'c> { + pub g: &'c u8, +} +pub trait M { + fn n(&self) -> u8; +} +impl<'d> M for P<'d> { + fn n(&self) -> u8 { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return Box::new(p) as Box; + } +} + +fn main() { + let w = E { f: &10u8 }; + let o = extension(&w); + assert_eq!(o.n(), 10u8); +}