diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index f76cefcd94127..dc39d4ca2d6ab 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -111,7 +111,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/liballoc/rc.rs b/src/liballoc/rc.rs index df84ac9aec935..c390a8b0f7d5d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -142,6 +142,14 @@ //! // destroyed. There are now no strong (Rc) references to the gadgets. //! // Once they get destroyed, the Gadgets get destroyed. This zeroes the //! // reference count on Gadget Man, so he gets destroyed as well. +//! +//! // This is an unfortunate wart that is a side-effect of the implmentation +//! // of new destructor semantics: if the above for-loop is the final expression +//! // in the function, the borrow-checker treats the gadget_owner as needing to +//! // live past the destruction scope of the function (which of course it does not). +//! // To work around this, for now I am inserting a dummy value just so the above +//! // for-loop is no longer the final expression in the block. +//! () //! } //! ``` diff --git a/src/libcollections/hash/sip.rs b/src/libcollections/hash/sip.rs index ab69a3ad8b883..c5a2dd559c4e8 100644 --- a/src/libcollections/hash/sip.rs +++ b/src/libcollections/hash/sip.rs @@ -490,8 +490,10 @@ mod tests { assert!(s != t && t != u); assert!(hash(&s) != hash(&t) && hash(&s) != hash(&u)); - let v: (&[u8], &[u8], &[u8]) = (&[1u8], &[0u8, 0], &[0u8]); - let w: (&[u8], &[u8], &[u8]) = (&[1u8, 0, 0, 0], &[], &[]); + let (v1, v2, v3) = ([1u8], [0u8, 0], [0u8]); + let (w1, w2, w3) = ([1u8, 0, 0, 0], [], []); + let v: (&[u8], &[u8], &[u8]) = (&v1, &v2, &v3); + let w: (&[u8], &[u8], &[u8]) = (&w1, &w2, &w3); assert!(v != w); assert!(hash(&v) != hash(&w)); diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index fd0526db411cb..b400f49857e91 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -64,6 +64,6 @@ pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! { line: uint) -> !; } - let (file, line) = *file_line; + let (file, line) : (&'static str, uint) = *file_line; unsafe { panic_impl(fmt, file, line) } } diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs index 79019d213b8ba..aae1b9830a03e 100644 --- a/src/libregex/vm.rs +++ b/src/libregex/vm.rs @@ -116,8 +116,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::from_elem(ncaps * 2, None); diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs index 3cc6d361e3c58..14d23ecc9fb96 100644 --- a/src/libregex_macros/lib.rs +++ b/src/libregex_macros/lib.rs @@ -183,8 +183,10 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str, fn run(&mut self, start: uint, end: uint) -> Vec> { let mut matched = false; let prefix_bytes: &[u8] = $prefix_bytes; - let mut clist = &mut Threads::new(self.which); - let mut nlist = &mut Threads::new(self.which); + let mut cthread = Threads::new(self.which); + let mut nthread = Threads::new(self.which); + let mut clist = &mut cthread; + let mut nlist = &mut nthread; let mut groups = $init_groups; diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 00d12ad6a382d..70dd275d2bfa9 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -344,6 +344,22 @@ fn parse_scope(st: &mut PState) -> region::CodeExtent { let node_id = parse_uint(st) as ast::NodeId; region::CodeExtent::Misc(node_id) } + 'C' => { + let node_id = parse_uint(st) as ast::NodeId; + region::CodeExtent::Closure(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 bbb2faaae0691..5cd575031dca3 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -170,7 +170,11 @@ 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::Closure(node_id) => mywrite!(w, "C{}", 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/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 238a4ca7bd69e..52a322cd7484a 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -239,6 +239,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let tcx = self.tcx(); self.each_issued_loan(scope, |loan| { + debug!("each_in_scope_loan scope: {} loan: {} loan.kill_scope: {}", + scope.repr(self.tcx()), + loan.repr(self.tcx()), + loan.kill_scope.repr(self.tcx())); if tcx.region_maps.is_subscope_of(scope, loan.kill_scope) { op(loan) } else { @@ -265,6 +269,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let loan_path = owned_ptr_base_path(loan_path); let cont = self.each_in_scope_loan(scope, |loan| { let mut ret = true; + debug!("each_in_scope_loan_affecting_path \ + scope: {} loan_path: {} restricted_paths: {}", + scope.repr(self.tcx()), + loan_path.repr(self.tcx()), + loan.restricted_paths.repr(self.tcx())); for restr_path in loan.restricted_paths.iter() { if **restr_path == *loan_path { if !op(loan) { @@ -304,6 +313,12 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } let cont = self.each_in_scope_loan(scope, |loan| { + debug!("each_in_scope_loan_affecting_path \ + scope: {} loan_path: {} loan: {}", + scope.repr(self.tcx()), + loan_path.repr(self.tcx()), + loan.repr(self.tcx())); + if *loan.loan_path == *loan_path { op(loan) } else { diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 5b8cb0608b39c..130ad4d42532f 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -96,6 +96,9 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { fn check_scope(&self, max_scope: ty::Region) -> R { //! Reports an error if `loan_region` is larger than `max_scope` + debug!("check_scope self.loan_region: {} max_scope: {}", + self.loan_region.repr(self.bccx.tcx), + max_scope.repr(self.bccx.tcx)); if !self.bccx.is_subregion_of(self.loan_region, max_scope) { Err(self.report_error(err_out_of_scope(max_scope, self.loan_region))) } else { @@ -103,39 +106,14 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { } } - fn scope(&self, cmt: &mc::cmt) -> ty::Region { + fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region { //! Returns the maximal region scope for the which the //! lvalue `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. // See the SCOPE(LV) function in doc.rs - match cmt.cat { - mc::cat_rvalue(temp_scope) => { - temp_scope - } - mc::cat_upvar(..) => { - ty::ReScope(self.item_scope) - } - mc::cat_static_item => { - ty::ReStatic - } - mc::cat_local(local_id) => { - ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id)) - } - mc::cat_deref(_, _, mc::UnsafePtr(..)) => { - ty::ReStatic - } - mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) | - mc::cat_deref(_, _, mc::Implicit(_, r)) => { - r - } - mc::cat_downcast(ref cmt) | - mc::cat_deref(ref cmt, _, mc::OwnedPtr) | - mc::cat_interior(ref cmt, _) => { - self.scope(cmt) - } - } + mc::scope(self.bccx.tcx, cmt, self.item_scope) } fn report_error(&self, code: bckerr_code) { diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index c36a466919b45..13c735b820440 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -474,6 +474,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> { fn visit_expr(&mut self, ex: &Expr) { match ex.node { ast::ExprAddrOf(mutbl, ref base) => { + debug!("StaticInitializerCtxt visit_expr ex: {}", + ex.repr(self.bccx.tcx)); let base_cmt = self.bccx.cat_expr(&**base); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); // Check that we don't allow borrows of unsafe static items. diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 9b9a5e61393f8..64b8bb4f92ee3 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -105,6 +105,8 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { } mc::cat_deref(cmt_base, _, pk) => { + debug!("restrict cat_deref (cmt={}) pk: {}", + cmt.repr(self.bccx.tcx), pk); match pk { mc::OwnedPtr => { // R-Deref-Send-Pointer diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index fa0f59f686049..238f2575af601 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -285,6 +285,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { assignment_expr: &ast::Expr, expr: &ast::Expr, mode: MutateMode) { + debug!("mutate_expr(expr={})", expr.repr(self.tcx())); let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode); self.walk_expr(expr); @@ -601,6 +602,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { } fn walk_local(&mut self, local: &ast::Local) { + debug!("walk_local(local.id={})", local.id); match local.init { None => { let delegate = &mut self.delegate; @@ -643,6 +645,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { _expr: &ast::Expr, fields: &Vec, opt_with: &Option>) { + debug!("walk_struct_expr(_expr.id={})", _expr.id); + // Consume the expressions supplying values for each field. for field in fields.iter() { self.consume_expr(&*field.expr); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index e9986e47e4a21..9ddc8ff0fac30 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -80,7 +80,7 @@ use middle::typeck; use util::nodemap::{DefIdMap, NodeMap}; use util::ppaux::{ty_to_string, Repr}; -use syntax::ast::{MutImmutable, MutMutable}; +use syntax::ast::{MutImmutable, MutMutable, NodeId}; use syntax::ast; use syntax::ast_map; use syntax::codemap::Span; @@ -414,6 +414,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } pub fn cat_expr(&self, expr: &ast::Expr) -> McResult> { + debug!("cat_expr expr.id: {} {}", expr.id, expr); match self.typer.adjustments().borrow().get(&expr.id) { None => { // No adjustments. @@ -457,6 +458,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { expr: &ast::Expr, autoderefs: uint) -> McResult> { + debug!("cat_expr_autoderefd: autoderefs={}", autoderefs); let mut cmt = if_ok!(self.cat_expr_unadjusted(expr)); debug!("cat_expr_autoderefd: autoderefs={}, cmt={}", autoderefs, @@ -468,9 +470,16 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { } pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult> { - debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx())); - - let expr_ty = if_ok!(self.expr_ty(expr)); + debug!("cat_expr_unadjusted: id={} expr={}", expr.id, expr.repr(self.tcx())); + + // let expr_ty = if_ok!(self.expr_ty(expr)); + let expr_ty = match self.expr_ty(expr) { + Ok(expr_ty) => expr_ty, + Err(e) => { + debug!("cat_expr_unadjusted expr_ty errd"); + return Err(e); + } + }; match expr.node { ast::ExprUnary(ast::UnDeref, ref e_base) => { let base_cmt = if_ok!(self.cat_expr(&**e_base)); @@ -702,7 +711,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 }); @@ -1543,3 +1555,34 @@ fn element_kind(t: Ty) -> ElementKind { _ => OtherElement } } + + +/// Returns the maximal region scope for the which the lvalue `cmt` is +/// guaranteed to be valid without any rooting etc, and presuming `cmt` +/// is not mutated. See the `SCOPE(LV)` function in `borrowck/doc.rs`. +pub fn scope<'tcx>(tcx: &ty::ctxt<'tcx>, + cmt: &cmt<'tcx>, + extent: region::CodeExtent) -> ty::Region { + let ret = match cmt.cat { + cat_rvalue(temp_scope) => temp_scope, + cat_upvar(..) => ty::ReScope(extent), + + cat_static_item => ty::ReStatic, + + cat_local(local_id) => { + ty::ReScope(tcx.region_maps.var_scope(local_id)) + } + + cat_deref(_, _, UnsafePtr(..)) => ty::ReStatic, + + cat_deref(_, _, BorrowedPtr(_, r)) | + cat_deref(_, _, Implicit(_, r)) => r, + + cat_downcast(ref cmt) | + cat_deref(ref cmt, _, OwnedPtr) | + cat_interior(ref cmt, _) => scope(tcx, cmt, extent), + }; + debug!("scope cmt: {} {} return: {}", cmt, cmt.repr(tcx), ret); + return ret; +} + diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c5511f995bc68..773fbe1c06d2a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -32,6 +32,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 @@ -43,7 +44,33 @@ use syntax::visit::{Visitor, FnKind}; /// generated via deriving here. #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)] pub enum CodeExtent { - Misc(ast::NodeId) + Misc(ast::NodeId), + DestructionScope(ast::NodeId), // extent of destructors for temporaries of node-id + Closure(ast::NodeId), + 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 `...`. +#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)] +pub struct BlockRemainder { + pub block: ast::NodeId, + pub first_statement_index: uint, } impl CodeExtent { @@ -60,6 +87,10 @@ impl CodeExtent { pub fn node_id(&self) -> ast::NodeId { match *self { CodeExtent::Misc(node_id) => node_id, + CodeExtent::Closure(node_id) => node_id, + CodeExtent::Remainder(br) => br.block, + // FIXME (pnkfelix): very sketchy here. + CodeExtent::DestructionScope(node_id) => node_id, } } @@ -68,6 +99,11 @@ impl CodeExtent { pub fn map_id(&self, f_id: |ast::NodeId| -> ast::NodeId) -> CodeExtent { match *self { CodeExtent::Misc(node_id) => CodeExtent::Misc(f_id(node_id)), + CodeExtent::Closure(node_id) => CodeExtent::Closure(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)), } } } @@ -77,8 +113,10 @@ The region maps encode information about region relationships. - `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 + closures the parent scope of a closure expression is the innermost + conditional expression or repeating 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. @@ -120,11 +158,86 @@ pub struct RegionMaps { terminating_scopes: RefCell>, } +/// 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. +#[deriving(PartialEq, Eq, Show)] +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. +#[deriving(PartialEq, Eq, Show)] +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, + }) + } +} + +#[deriving(PartialEq, Eq, Show)] +enum InnermostEnclosingExpr { + None, + Some(ast::NodeId), + DestructionScope(ast::NodeId), + Statement(DeclaringStatementContext), + /// A closure is treated as a separate case, because a closure and + /// its enclosed block do not have the same relationship with + /// respect to control-flow that most other expressions do. + Closure(ast::NodeId), +} + +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), + InnermostEnclosingExpr::Closure(closure_id) => + CodeExtent::Closure(closure_id), + InnermostEnclosingExpr::DestructionScope(parent_id) => + CodeExtent::DestructionScope(parent_id), + }; + Some(extent) + } +} + +#[deriving(PartialEq, Eq, Show)] pub struct Context { - var_parent: Option, + var_parent: InnermostDeclaringBlock, - // Innermost enclosing expression - parent: Option, + parent: InnermostEnclosingExpr, } struct RegionResolutionVisitor<'a> { @@ -156,22 +269,24 @@ impl RegionMaps { pub fn record_encl_scope(&self, sub: CodeExtent, sup: CodeExtent) { debug!("record_encl_scope(sub={}, sup={})", sub, sup); assert!(sub != sup); + assert!(self.scope_map.borrow().get(&sup) != Some(&sub), + "cyclic encl scope sub: {} sup: {}", sub, sup); self.scope_map.borrow_mut().insert(sub, sup); } - pub fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { + fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_var_scope(sub={}, sup={})", var, lifetime); assert!(var != lifetime.node_id()); self.var_map.borrow_mut().insert(var, lifetime); } - pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { + fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) { debug!("record_rvalue_scope(sub={}, sup={})", var, lifetime); assert!(var != lifetime.node_id()); self.rvalue_scopes.borrow_mut().insert(var, lifetime); } - pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { + fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { /*! * Records that a scope is a TERMINATING SCOPE. Whenever we * create automatic temporaries -- e.g. by an @@ -285,7 +400,8 @@ impl RegionMaps { return true; } - pub fn sub_free_region(&self, sub: FreeRegion, sup: FreeRegion) -> bool { + pub fn sub_free_region(&self, sub: + FreeRegion, sup: FreeRegion) -> bool { /*! * Determines whether two free regions have a subregion relationship * by walking the graph encoded in `free_region_map`. Note that @@ -388,7 +504,7 @@ impl RegionMaps { fn ancestors_of(this: &RegionMaps, scope: CodeExtent) -> Vec { - // debug!("ancestors_of(scope={})", scope); + debug!("ancestors_of(scope={})", scope); let mut result = vec!(scope); let mut scope = scope; loop { @@ -399,7 +515,7 @@ impl RegionMaps { scope = superscope; } } - // debug!("ancestors_of_loop(scope={})", scope); + debug!("ancestors_of_loop(scope={})", scope); } } } @@ -407,15 +523,21 @@ 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); + // FIXME (pnkfelix): this may need to redundantly add entries for + // both a specific variant (Closure in this case) as well as the + // catch-all `CodeExtent::Misc`. (At least, it needed that on one + // path of development that I followed). But doing this would + // bloat the hashtable and is ugly to boot; we should instead + // consistently select the specific variant in all necessary + // contexts. + + match visitor.cx.parent.to_code_extent() { + Option::None => {} + Option::Some(parent_scope) => { visitor.region_maps.record_encl_scope(child_scope, parent_scope); } - None => {} } } @@ -423,9 +545,10 @@ 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); + debug!("record_var_lifetime var_id: {}", var_id); + + match visitor.cx.var_parent.to_code_extent() { + Some(parent_scope) => { visitor.region_maps.record_var_scope(var_id, parent_scope); } None => { @@ -439,21 +562,106 @@ 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; + + // FIXME (pnkfelix): Hack: introduce a separate destruction scope + // around each block, to ensure that a (tightly enclosing) + // immediate parent always exists to represent the extent where + // user code of the block is done but destructors of the block are + // still running. + // + // FIXME (pnkfelix): I now think this is unnecessary since I am + // handling DestructionScopes by making a 1:1 mapping between + // entries in terminating_scopes and DestructionScope instances. + if false { + record_superlifetime(visitor, CodeExtent::DestructionScope(blk.id), blk.span); + + visitor.cx = Context { + parent: InnermostEnclosingExpr::DestructionScope(blk.id), + ..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; } @@ -473,7 +681,9 @@ 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); + debug!("resolve_pat(pat.id={})", pat.id); + + record_superlifetime(visitor, CodeExtent::Misc(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. @@ -492,11 +702,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; } @@ -504,14 +722,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 { @@ -523,38 +757,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(..) | @@ -591,19 +825,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 @@ -839,7 +1067,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; } @@ -859,21 +1090,42 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, body.id, visitor.cx.parent); + let outer_cx = visitor.cx; + + match fk { + visit::FkFnBlock(..) => { + // A closure's body is enclosed by the closure's original + // expression. (and the block that forms that body is + // itself enclosed by the closure body.) + // + // FiXME (pnkfelix): clean all this up, there must be a + // cleaner construction and/or presentation. + record_superlifetime(visitor, CodeExtent::Closure(id), sp); + } + _ => {} + } + let body_scope = CodeExtent::from_node_id(body.id); visitor.region_maps.mark_as_terminating_scope(body_scope); - - let outer_cx = visitor.cx; + let dtor_scope = CodeExtent::DestructionScope(body.id); + visitor.region_maps.record_encl_scope(body_scope, dtor_scope); + record_superlifetime(visitor, dtor_scope, body.span); // 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; } @@ -885,8 +1137,19 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, // but the correct fix is a bit subtle, and I am also not sure // that the present approach is unsound -- it may not permit // any illegal programs. See issue for more details. - visitor.cx = outer_cx; + + if outer_cx.parent != InnermostEnclosingExpr::Some(id) { + visitor.sess.span_note( + sp, format!("resolve_fn id={} unexpected outer_cx: {}", + id, outer_cx).as_slice()); + } + visitor.cx = Context { + // parent: InnermostEnclosingExpr::Some(id), + parent: InnermostEnclosingExpr::Closure(id), + ..outer_cx + }; visitor.visit_block(body); + visitor.cx = outer_cx; } } } @@ -934,7 +1197,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); } @@ -947,7 +1213,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.rs b/src/librustc/middle/resolve.rs index 68a31c83ea484..ce929bfbf1fc8 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1403,7 +1403,8 @@ impl<'a> Resolver<'a> { // a trait and the name of an impl of that trait. let mod_name = path.segments.last().unwrap().identifier.name; - let parent_opt = parent.module().children.borrow() + let parent_mod = parent.module(); + let parent_opt = parent_mod.children.borrow() .get(&mod_name).cloned(); let new_parent = match parent_opt { // It already exists @@ -1767,11 +1768,12 @@ impl<'a> Resolver<'a> { true)); debug!("(build reduced graph for item) found extern `{}`", self.module_to_string(&*external_module)); + let parent_mod = parent.module(); self.check_for_conflicts_between_external_crates( - &*parent.module(), + &*parent_mod, name.name, view_item.span); - parent.module().external_module_children.borrow_mut() + parent_mod.external_module_children.borrow_mut() .insert(name.name, external_module.clone()); self.build_reduced_graph_for_external_crate(external_module); } @@ -2301,7 +2303,8 @@ impl<'a> Resolver<'a> { } } - 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()); } } @@ -3458,7 +3461,8 @@ impl<'a> Resolver<'a> { // Search for external modules. if namespace == TypeNS { - match module_.external_module_children.borrow().get(&name).cloned() { + let children = module_.external_module_children.borrow().get(&name).cloned(); + match children { None => {} Some(module) => { let name_bindings = @@ -3743,7 +3747,8 @@ impl<'a> Resolver<'a> { // Finally, search through external children. if namespace == TypeNS { - match module_.external_module_children.borrow().get(&name).cloned() { + let children = module_.external_module_children.borrow().get(&name).cloned(); + match children { None => {} Some(module) => { let name_bindings = @@ -3795,7 +3800,8 @@ impl<'a> Resolver<'a> { } } - 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()); } } @@ -3855,7 +3861,8 @@ impl<'a> Resolver<'a> { } } - 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/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index fae64ff924274..84807d2679a68 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -22,7 +22,7 @@ use self::ScopeChain::*; use session::Session; use middle::def; -use middle::region; +use middle::region::{mod, CodeExtent}; use middle::resolve::DefMap; use middle::subst; use middle::ty; @@ -310,7 +310,13 @@ impl<'a> LifetimeContext<'a> { loop { match *scope { BlockScope(blk_scope, s) => { - return self.resolve_free_lifetime_ref(blk_scope, lifetime_ref, s); + if let CodeExtent::Misc(node_id) = blk_scope { + let d = CodeExtent::DestructionScope(node_id); + return self.resolve_free_lifetime_ref(d, lifetime_ref, s); + } else { + self.sess.bug( + "found unexpected CodeExtent associated with blk_scope") + } } RootScope => { @@ -355,17 +361,41 @@ 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. let mut scope_data = scope_data; let mut scope = scope; let mut search_result = None; + let mut loop_count = 0u; loop { + loop_count += 1; + debug!("resolve_free_lifetime_ref loop: {} \ + scope_data: {} scope: {} search_result: {}", + loop_count, scope_data, scope, search_result); match *scope { BlockScope(blk_scope_data, s) => { - scope_data = blk_scope_data; - scope = s; + // FIXME (pnkfelix): I still need to work through + // the theoretical justification for this + // transition from the block itself to its + // enclosing destruction scope. (In particular, + // perhaps athis *actually* belongs as part of the + // `RootScope` case, or maybe following the loop + // (either of which I think would resolve my + // problem), but not here, where it has a broad + // effect. + if let CodeExtent::Misc(node_id) = blk_scope_data { + let d = CodeExtent::DestructionScope(node_id); + scope_data = d; + scope = s; + } else { + self.sess.bug( + "found unexpected CodeExtent associated with blk_scope") + } } RootScope => { @@ -386,6 +416,10 @@ impl<'a> LifetimeContext<'a> { match search_result { Some((_depth, decl_id)) => { let def = DefFreeRegion(scope_data, decl_id); + debug!("resolve_free_lifetime_ref: \ + from parent scope {} \ + insert_lifetime(lifetime_ref: {} def: {})", + lifetime_ref, *scope, def); self.insert_lifetime(lifetime_ref, def); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 47b296e46cd30..a7c55865e036e 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -837,7 +837,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. @@ -3559,12 +3561,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 @@ -5614,10 +5619,12 @@ pub fn construct_parameter_environment<'tcx>( generics.types.get_slice(space)); } + let free_id_outlive = region::CodeExtent::DestructionScope(free_id); + // map bound 'a => free 'a let mut regions = VecPerParamSpace::empty(); for &space in subst::ParamSpace::all().iter() { - push_region_params(&mut regions, space, free_id, + push_region_params(&mut regions, space, free_id_outlive, generics.regions.get_slice(space)); } @@ -5626,14 +5633,12 @@ pub fn construct_parameter_environment<'tcx>( 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, &bind(bounds)).value; + let bounds = liberate_late_bound_regions(tcx, free_id_outlive, &bind(bounds)).value; let obligations = traits::obligations_for_generics(tcx, traits::ObligationCause::misc(span), &bounds, @@ -5661,18 +5666,18 @@ pub fn construct_parameter_environment<'tcx>( return ty::ParameterEnvironment { free_substs: free_substs, bounds: bounds.types, - implicit_region_bound: ty::ReScope(free_id_scope), + implicit_region_bound: ty::ReScope(free_id_outlive), caller_obligations: obligations, selection_cache: traits::SelectionCache::new(), }; fn push_region_params(regions: &mut VecPerParamSpace, space: subst::ParamSpace, - free_id: ast::NodeId, + all_outlive_extent: region::CodeExtent, region_params: &[RegionParameterDef]) { for r in region_params.iter() { - regions.push(space, ty::free_region_from_def(free_id, r)); + regions.push(space, ty::free_region_from_def(all_outlive_extent, r)); } } @@ -5905,19 +5910,26 @@ impl<'tcx> AutoDerefRef<'tcx> { pub fn liberate_late_bound_regions<'tcx, HR>( tcx: &ty::ctxt<'tcx>, - scope: region::CodeExtent, + all_outlive_scope: region::CodeExtent, value: &HR) -> HR where HR : HigherRankedFoldable<'tcx> { /*! * Replace any late-bound regions bound in `value` with free variants - * attached to scope-id `scope_id`. + * guaranteed to outlive `all_outlive_scope`. */ replace_late_bound_regions( tcx, value, - |br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0 + |br, _| { + let ret = + ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, + bound_region: br}); + debug!("liberate_late_bound_regions replace_late_bound_regions \ + callback returns {}", ret); + ret + }).0 } pub fn erase_late_bound_regions<'tcx, HR>( diff --git a/src/librustc/middle/typeck/check/dropck.rs b/src/librustc/middle/typeck/check/dropck.rs new file mode 100644 index 0000000000000..e5bba98318796 --- /dev/null +++ b/src/librustc/middle/typeck/check/dropck.rs @@ -0,0 +1,209 @@ +// 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. + +use middle::region; +use middle::subst; +use middle::ty; +use middle::typeck::check::regionck::{Rcx}; +use middle::typeck::infer; +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); + iterate_over_potentially_unsafe_regions_in_type( + rcx, + typ, + span, + scope, + false, + 0); + rcx.reset_traversal(); +} + +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 mut could_have_been_re_function = false; + let parent_inner_region = + match rcx.tcx().region_maps.opt_encl_scope(inner_scope) { + None => rcx.tcx().sess.span_bug( + span, format!("no enclosing scope found for inner_scope: {}", + inner_scope).as_slice()), + // FIXME (onkfelix): if closures need not be handled specially, + // then perhaps I can/should do away with ReFunction entirely. + Some(parent_inner_scope @ region::CodeExtent::Closure(_)) => { + could_have_been_re_function = true; + // ty::ReFunction + ty::ReScope(parent_inner_scope) + } + Some(parent_inner_scope) => ty::ReScope(parent_inner_scope), + }; + + debug!("constrain_region_for_destructor_safety region: {} :> \ + parent_inner_region: {} (from inner_scope: {}){}", + region, parent_inner_region, inner_scope, + if could_have_been_re_function { " could_have_been_re_function" } else { "" }); + + rcx.mk_subr(infer::SafeDestructor(span), + parent_inner_region, + region); +} + +fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>( + rcx: &mut Rcx<'a, 'tcx>, + typ: ty::Ty<'tcx>, + span: Span, + scope: region::CodeExtent, + reachable_by_destructor: bool, + depth: uint) { + ty::maybe_walk_ty(typ, |typ| { + // Avoid recursing forever. + rcx.traverse_type_if_unseen(typ, |rcx| { + debug!("iterate_over_potentially_unsafe_regions_in_type \ + {}typ: {} scope: {} reachable_by_destructor: {}", + String::from_char(depth, ' '), + typ.repr(rcx.tcx()), scope, reachable_by_destructor); + + let keep_going = match typ.sty { + ty::ty_struct(structure_id, ref 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, + field_type, + span, + scope, + reachable_by_destructor, depth+1) + } + + false + } + ty::ty_enum(enumeration_id, ref 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, + *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_closure(ref closure_type) => { + match closure_type.store { + ty::RegionTraitStore(region, _) => { + if reachable_by_destructor { + constrain_region_for_destructor_safety(rcx, + region, + scope, + span) + } + } + ty::UniqTraitStore => {} + } + // Don't recurse, since closures don't own the types + // appearing in their signature. + false + } + 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, + }; + + keep_going + }) + }); +} diff --git a/src/librustc/middle/typeck/check/method/probe.rs b/src/librustc/middle/typeck/check/method/probe.rs index a98b4cf011d97..8bfa7664aef4c 100644 --- a/src/librustc/middle/typeck/check/method/probe.rs +++ b/src/librustc/middle/typeck/check/method/probe.rs @@ -486,12 +486,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_for_def = trait_impls.get(&trait_def_id); + let impl_def_ids = match impl_for_def { 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())); @@ -901,8 +903,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/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index d38c5bc0ca9cf..d611ff8f2ea1d 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -87,7 +87,7 @@ use middle::{const_eval, def, traits}; use middle::lang_items::IteratorItem; use middle::mem_categorization::{mod, McResult}; use middle::pat_util::{mod, pat_id_map}; -use middle::region::CodeExtent; +use middle::region::{CodeExtent}; use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace}; use middle::ty::{FnSig, VariantInfo, Polytype}; use middle::ty::{Disr, ParamTy, ParameterEnvironment}; @@ -119,6 +119,7 @@ use syntax::print::pprust; use syntax::ptr::P; use syntax::visit::{mod, Visitor}; +pub mod dropck; pub mod _match; pub mod vtable; pub mod writeback; @@ -393,8 +394,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, decl, id, body, &inh); vtable::select_all_fcx_obligations_or_error(&fcx); - regionck::regionck_fn(&fcx, id, body); fcx.default_diverging_type_variables_to_nil(); + regionck::regionck_fn(&fcx, id, body); writeback::resolve_type_vars_in_fn(&fcx, decl, body); } _ => ccx.tcx.sess.impossible_case(body.span, @@ -510,7 +511,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, // First, we have to replace any bound regions in the fn type with free ones. // The free region references will be bound the node_id of the body block. - let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig); + let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::DestructionScope(body.id), fn_sig); let arg_tys = fn_sig.inputs.as_slice(); let ret_ty = fn_sig.output; @@ -724,7 +725,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let body_id = method.pe_body().id; let fty = liberate_late_bound_regions( - ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value; + ccx.tcx, CodeExtent::DestructionScope(body_id), &ty::bind(fty)).value; debug!("fty (liberated): {}", fty.repr(ccx.tcx)); check_bare_fn(ccx, @@ -919,7 +920,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method(impl_trait_ref={})", impl_trait_ref.repr(tcx)); - let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id); + let impl_m_body_scope = CodeExtent::DestructionScope(impl_m_body_id); // The impl's trait ref may bind late-bound regions from the impl. // Liberate them and assign them the scope of the method body. @@ -1066,7 +1067,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, |d| ty::mk_param_from_def(tcx, d)); let skol_regions = impl_m.generics.regions.map( - |l| ty::free_region_from_def(impl_m_body_id, l)); + |l| ty::free_region_from_def(impl_m_body_scope, l)); let impl_to_skol_substs = subst::Substs::new(skol_tps.clone(), skol_regions.clone()); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 1e92dc573a954..08e7a483a4b6a 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -128,6 +128,7 @@ use middle::typeck::astconv::AstConv; use middle::typeck::check::FnCtxt; use middle::typeck::check::regionmanip; use middle::typeck::check::vtable; +use middle::typeck::check::dropck; use middle::typeck::infer::resolve_and_force_all_but_regions; use middle::typeck::infer::resolve_type; use middle::typeck::infer; @@ -234,6 +235,9 @@ pub struct Rcx<'a, 'tcx: 'a> { // id of innermost fn or loop repeating_scope: ast::NodeId, + /// Breadcrumbs used by the destructor checker. + breadcrumbs: Vec>, + // Possible region links we will establish if an upvar // turns out to be unique/mutable maybe_links: MaybeLinkMap<'tcx> @@ -270,13 +274,53 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { Rcx { fcx: fcx, repeating_scope: initial_repeating_scope, region_param_pairs: Vec::new(), + breadcrumbs: Vec::new(), maybe_links: RefCell::new(FnvHashMap::new()) } } + pub fn reset_traversal(&mut self) { + self.breadcrumbs.clear(); + self.breadcrumbs.shrink_to_fit(); + } + + pub fn traverse_type_if_unseen(&mut self, + typ: ty::Ty<'tcx>, + keep_going: |&mut Rcx<'a, 'tcx>| -> bool) -> bool { + let rcx = self; + + // Avoid recursing forever. + if !rcx.breadcrumbs.contains(&typ) { + rcx.breadcrumbs.push(typ); + let keep_going = keep_going(rcx); + + // FIXME: popping the breadcrumbs here is a reasonable + // idea, but then you fall victim to exponential time on + // examples like src/tests/compile-fail/huge-struct.rs. + // So pnkfelix is trying to experimentally not remove + // anything from the vector during any particular + // traversal, and instead clear it after the whole + // traversal is done. + // + // let top_t = rcx.breadcrumbs.pop(); + // assert_eq!(top_t, Some(typ)); + + keep_going + } else { + false + } + } + 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; @@ -315,7 +359,10 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> { match resolve_type(self.fcx.infcx(), None, unresolved_ty, resolve_and_force_all_but_regions) { Ok(t) => t, - Err(_) => ty::mk_err() + Err(e) => { + debug!("Rcx::resolved_type resolve_type err: {}", e); + ty::mk_err() + } } } @@ -461,7 +508,12 @@ impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> { fn node_ty(&self, id: ast::NodeId) -> mc::McResult> { let t = self.resolve_node_type(id); - if ty::type_is_error(t) {Err(())} else {Ok(t)} + if ty::type_is_error(t) { + debug!("Rcx::node_ty Errd because type_is_error t: {}", t); + Err(()) + } else { + Ok(t) + } } fn node_method_ty(&self, method_call: MethodCall) -> Option> { @@ -577,6 +629,12 @@ fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) { type_of_node_must_outlive( rcx, infer::BindingTypeIsNotValidAtDecl(span), id, var_region); + + debug!("constrain_bindings_in_pat pat.id: {} calling var_scope(id: {})", + pat.id, id); + 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); }) } @@ -625,6 +683,44 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { */ _ => {} } + + // If necessary, constrain destructors in the unadjusted form of this + // expression. + debug!("visit_expr constrain destructors \ + unadjusted expr.id: {}", expr.id); + let cmt_result = { + let mc = mc::MemCategorizationContext::new(rcx); + 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. + debug!("visit_expr constrain destructors \ + potentially adjusted expr.id: {}", expr.id); + let cmt_result = { + let mc = mc::MemCategorizationContext::new(rcx); + 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 { @@ -1090,6 +1186,8 @@ fn constrain_callee(rcx: &mut Rcx, callee_id: ast::NodeId, call_expr: &ast::Expr, callee_expr: &ast::Expr) { + debug!("constrain_callee callee_id: {} call_expr.id: {}", + callee_id, call_expr.id); let call_region = ty::ReScope(CodeExtent::from_node_id(call_expr.id)); let callee_ty = rcx.resolve_node_type(callee_id); @@ -1258,6 +1356,35 @@ 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) { + debug!("check_safety_of_rvalue_destructor_if_necessary cmt: {}", + cmt.repr(rcx.tcx())); + 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()); + } + } + } + _ => {} + } +} fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>, index_expr: &ast::Expr, @@ -1722,6 +1849,7 @@ fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx, * for upvars that are assigned to in an assignment * expression. */ + debug!("adjust_borrow_kind_for_assignment_lhs lhs.id: {}", lhs.id); let mc = mc::MemCategorizationContext::new(rcx); let cmt = ignore_err!(mc.cat_expr(lhs)); diff --git a/src/librustc/middle/typeck/check/wf.rs b/src/librustc/middle/typeck/check/wf.rs index d9c6c3cb6262a..4ab1084d063ab 100644 --- a/src/librustc/middle/typeck/check/wf.rs +++ b/src/librustc/middle/typeck/check/wf.rs @@ -9,7 +9,6 @@ // except according to those terms. use middle::region; -use middle::subst; use middle::subst::{Subst}; use middle::traits; use middle::ty::{mod, Ty}; @@ -23,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::visit; use syntax::visit::Visitor; @@ -171,6 +169,12 @@ 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, @@ -198,22 +202,6 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs); let trait_ref = liberate_late_bound_regions(fcx.tcx(), item_scope, &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, self_ty, def_id); - } - _ => { - // Coherence already reports an error in this case. - } - } - } - // We are stricter on the trait-ref in an impl than the // self-type. In particular, we enforce region // relationships. The reason for this is that (at least @@ -278,8 +266,11 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> { scope: region::CodeExtent, cache: Option<&'cx mut HashSet>>) -> BoundsChecker<'cx,'tcx> { - BoundsChecker { fcx: fcx, span: span, scope: scope, - cache: cache, binding_count: 0 } + let ret = BoundsChecker { fcx: fcx, span: span, scope: scope, + cache: cache, binding_count: 0 }; + debug!("BoundsChecker::new returns b with: b.scope: {} b.binding_count: {}", + ret.scope, ret.binding_count); + ret } pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { @@ -470,33 +461,3 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }) .collect() } - -/////////////////////////////////////////////////////////////////////////// -// Special drop trait checking - -fn check_struct_safe_for_destructor<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, - span: Span, - self_ty: Ty<'tcx>, - 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) - { - let cause = traits::ObligationCause::new(span, traits::DropTrait); - let obligation = traits::obligation_for_builtin_bound(fcx.tcx(), - cause, - self_ty, - ty::BoundSend); - match obligation { - Ok(obligation) => fcx.register_obligation(obligation), - _ => {} - } - } else { - 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/middle/typeck/coherence/mod.rs b/src/librustc/middle/typeck/coherence/mod.rs index 1f32110a09338..9eb42e4aa32a6 100644 --- a/src/librustc/middle/typeck/coherence/mod.rs +++ b/src/librustc/middle/typeck/coherence/mod.rs @@ -432,7 +432,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/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 13a0bf0bdcb52..1b2803862f0d9 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -2162,7 +2162,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/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index bc36a2bd801b4..dd182350f591a 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -754,6 +754,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, @@ -851,6 +867,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.as_slice()); let node_inner = match parent_node { Some(ref node) => match *node { ast_map::NodeItem(ref item) => { @@ -893,8 +911,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }; let (fn_decl, generics, fn_style, 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.as_slice()); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); @@ -1670,6 +1686,12 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { format!("...so that the declared lifetime parameter bounds \ are satisfied").as_slice()); } + infer::SafeDestructor(span) => { + self.tcx.sess.span_note( + span, + "...so that references are valid when the destructor \ + runs") + } } } } diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 93c11693091c2..3439c0e28d447 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -225,6 +225,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: @@ -1083,6 +1086,7 @@ impl<'tcx> SubregionOrigin<'tcx> { CallReturn(a) => a, AddrOf(a) => a, AutoBorrow(a) => a, + SafeDestructor(a) => a, } } } @@ -1154,6 +1158,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/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 6a447d467cfce..8f5679fe2b012 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -714,7 +714,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { } fn lub_concrete_regions(&self, a: Region, b: Region) -> Region { - match (a, b) { + debug!("lub_concrete_regions(a: {}, b: {})", a, b); + let ret = match (a, b) { (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReEarlyBound(..), _) | @@ -749,7 +750,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // at least as big as the block fr.scope_id". So, we can // reasonably compare free regions and scopes: match self.tcx.region_maps.nearest_common_ancestor(fr.scope, s_id) { - // if the free region's scope `fr.scope_id` is bigger than + // if the free region's scope `fr.scope` is bigger than // the scope region `s_id`, then the LUB is the free // region itself: Some(r_id) if r_id == fr.scope => f, @@ -780,7 +781,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { (_, ReInfer(ReSkolemized(..))) => { if a == b {a} else {ReStatic} } - } + }; + debug!("lub_concrete_regions(a: {}, b: {}) returns {}", a, b, ret); + ret } fn lub_free_regions(&self, @@ -793,11 +796,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { * in any order, a consistent result is returned. */ - return match a.cmp(b) { + debug!("lub_free_regions(a: {}, b: {})", a, b); + let ret = match a.cmp(b) { Less => helper(self, a, b), Greater => helper(self, b, a), Equal => ty::ReFree(*a) }; + debug!("lub_free_regions(a: {}, b: {}) returns {}", a, b, ret); + return ret; fn helper(this: &RegionVarBindings, a: &FreeRegion, @@ -818,7 +824,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { b: Region) -> cres<'tcx, Region> { debug!("glb_concrete_regions({}, {})", a, b); - match (a, b) { + let ret = match (a, b) { (ReLateBound(..), _) | (_, ReLateBound(..)) | (ReEarlyBound(..), _) | @@ -881,7 +887,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { Err(ty::terr_regions_no_overlap(b, a)) } } - } + }; + debug!("glb_concrete_regions(a: {}, b: {}) returns {}", a, b, ret); + ret } fn glb_free_regions(&self, @@ -894,11 +902,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { * in any order, a consistent result is returned. */ - return match a.cmp(b) { + debug!("glb_free_regions(a: {}, b: {})", a, b); + let ret = match a.cmp(b) { Less => helper(self, a, b), Greater => helper(self, b, a), Equal => Ok(ty::ReFree(*a)) }; + debug!("glb_free_regions(a: {}, b: {}) returns {}", a, b, ret); + return ret; fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>, a: &FreeRegion, @@ -927,11 +938,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { // it. Otherwise fail. debug!("intersect_scopes(scope_a={}, scope_b={}, region_a={}, region_b={})", scope_a, scope_b, region_a, region_b); - match self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b) { + let ret = match self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b) { Some(r_id) if scope_a == r_id => Ok(ReScope(scope_b)), Some(r_id) if scope_b == r_id => Ok(ReScope(scope_a)), _ => Err(ty::terr_regions_no_overlap(region_a, region_b)) - } + }; + debug!("intersect_scopes(scope_a={}, scope_b={}, region_a={}, region_b={}) returns {}", + scope_a, scope_b, region_a, region_b, ret); + return ret; } } @@ -1146,6 +1160,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { a_region: Region, b_region: Region) -> bool { + debug!("check_node a_region: {} b_region: {}", + a_region.repr(this.tcx), b_region.repr(this.tcx)); if !this.is_subregion_of(a_region, b_region) { debug!("Setting {} to ErrorValue: {} not subregion of {}", a_vid, @@ -1192,7 +1208,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { errors: &mut Vec>) { let mut reg_reg_dups = FnvHashSet::new(); - for verify in self.verifys.borrow().iter() { + for (i, verify) in self.verifys.borrow().iter().enumerate() { + debug!("collect_concrete_region_errors i: {}", i); match *verify { VerifyRegSubReg(ref origin, sub, sup) => { if self.is_subregion_of(sub, sup) { @@ -1218,8 +1235,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { continue; } - let sups = sups.iter().map(|&sup| normalize(values, sup)) - .collect(); + let sups : Vec<_> = sups.iter().map(|&sup| normalize(values, sup)) + .collect(); + debug!("ParamBoundFailrue: all sup in sups !(sub <= sup): sub={}, sups={}", + sub.repr(self.tcx), + sups.repr(self.tcx)); errors.push( ParamBoundFailure( (*origin).clone(), *param_ty, sub, sups)); @@ -1385,10 +1405,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { lower_bounds.sort_by(|a, b| { free_regions_first(a, b) }); upper_bounds.sort_by(|a, b| { free_regions_first(a, b) }); - for lower_bound in lower_bounds.iter() { - for upper_bound in upper_bounds.iter() { + for (i, lower_bound) in lower_bounds.iter().enumerate() { + for (j, upper_bound) in upper_bounds.iter().enumerate() { + debug!("collect_error_for_expanding_node {}", (i,j)); if !self.is_subregion_of(lower_bound.region, upper_bound.region) { + debug!("SubSupConflict: !(sub.region <= sup.region): sub={}, sup={}", + lower_bound.repr(self.tcx), + upper_bound.repr(self.tcx)); errors.push(SubSupConflict( (*self.var_origins.borrow())[node_idx.index].clone(), lower_bound.origin.clone(), @@ -1433,13 +1457,16 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> { upper_bound_2.region) { Ok(_) => {} Err(_) => { - errors.push(SupSupConflict( - (*self.var_origins.borrow())[node_idx.index].clone(), - upper_bound_1.origin.clone(), - upper_bound_1.region, - upper_bound_2.origin.clone(), - upper_bound_2.region)); - return; + debug!("SubSupConflict: no glb for upper_bound_1: {} upper_bound_2: {}", + upper_bound_1.repr(self.tcx), + upper_bound_2.repr(self.tcx)); + errors.push(SupSupConflict( + (*self.var_origins.borrow())[node_idx.index].clone(), + upper_bound_1.origin.clone(), + upper_bound_1.region, + upper_bound_2.origin.clone(), + upper_bound_2.region)); + return; } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 761a1f66501ca..b9420361cb383 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -12,6 +12,7 @@ use middle::def; use middle::subst::{VecPerParamSpace,Subst}; use middle::subst; +use middle::region::{mod, CodeExtent}; use middle::ty::{BoundRegion, BrAnon, BrNamed}; use middle::ty::{ReEarlyBound, BrFresh, ctxt}; use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty}; @@ -84,31 +85,56 @@ fn item_scope_tag(item: &ast::Item) -> &'static str { pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) -> (String, Option) { return match region { - ReScope(scope) => { - match cx.map.find(scope.node_id()) { + ReScope(scope @ CodeExtent::Misc(_)) | + ReScope(scope @ CodeExtent::Closure(_)) | + ReScope(scope @ CodeExtent::DestructionScope(_)) => { + let node_id = scope.node_id(); + let prefix = if let CodeExtent::DestructionScope(_) = scope { + "destruction scope surrounding " + } else { + "" + }; + match cx.map.find(node_id) { Some(ast_map::NodeBlock(ref blk)) => { - explain_span(cx, "block", blk.span) + let place = format!("{}{}", prefix, "block"); + explain_span(cx, place.as_slice(), blk.span) } Some(ast_map::NodeExpr(expr)) => { match expr.node { - ast::ExprCall(..) => explain_span(cx, "call", expr.span), + ast::ExprCall(..) => { + let place = format!("{}{}", prefix, "call"); + explain_span(cx, place.as_slice(), expr.span) + }, ast::ExprMethodCall(..) => { - explain_span(cx, "method call", expr.span) + let place = format!("{}{}", prefix, "method call"); + explain_span(cx, place.as_slice(), expr.span) + }, + ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => { + let place = format!("{}{}", prefix, "if let"); + explain_span(cx, place.as_slice(), expr.span) }, - ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => explain_span(cx, "if let", expr.span), ast::ExprMatch(_, _, ast::MatchWhileLetDesugar) => { - explain_span(cx, "while let", expr.span) + let place = format!("{}{}", prefix, "while let"); + explain_span(cx, place.as_slice(), expr.span) + }, + ast::ExprMatch(..) => { + let place = format!("{}{}", prefix, "match"); + explain_span(cx, place.as_slice(), expr.span) }, - ast::ExprMatch(..) => explain_span(cx, "match", expr.span), - _ => explain_span(cx, "expression", expr.span) + _ => { + let place = format!("{}{}", prefix, "expression"); + explain_span(cx, place.as_slice(), expr.span) + } } } Some(ast_map::NodeStmt(stmt)) => { - explain_span(cx, "statement", stmt.span) + let place = format!("{}{}", prefix, "statement"); + explain_span(cx, place.as_slice(), stmt.span) } Some(ast_map::NodeItem(it)) => { let tag = item_scope_tag(&*it); - explain_span(cx, tag, it.span) + let place = format!("{}{}", prefix, tag); + explain_span(cx, place.as_slice(), it.span) } Some(_) | None => { // this really should not happen @@ -117,6 +143,20 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region) } } + ReScope(CodeExtent::Remainder( + region::BlockRemainder { block: block_id, first_statement_index })) => { + match cx.map.find(block_id) { + Some(ast_map::NodeBlock(ref blk)) => { + let stmt_span = blk.stmts[first_statement_index].span; + let place = "block suffix"; + explain_span(cx, place, Span { lo: stmt_span.hi, ..blk.span }) + } + _ => { + cx.sess.bug("failed to find block for BlockRemainder") + } + } + } + ReFree(ref fr) => { let prefix = match fr.bound_region { BrAnon(idx) => { @@ -879,11 +919,27 @@ 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, _: &ctxt) -> String { + match *self { + region::CodeExtent::Misc(node_id) => + format!("Misc({})", node_id), + region::CodeExtent::DestructionScope(node_id) => + format!("DestructionScope({})", node_id), + region::CodeExtent::Closure(node_id) => + format!("Closure({})", node_id), + region::CodeExtent::Remainder(region::BlockRemainder { + block: node_id, first_statement_index, }) => + format!("Remainder({}, {})", node_id, 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_trans/driver/driver.rs b/src/librustc_trans/driver/driver.rs index b3b68d0c22b38..2dcc4fe7f7b72 100644 --- a/src/librustc_trans/driver/driver.rs +++ b/src/librustc_trans/driver/driver.rs @@ -76,13 +76,13 @@ pub fn compile_input(sess: Session, }; let mut forest = ast_map::Forest::new(expanded_crate); + let type_arena = TypedArena::new(); let ast_map = assign_node_ids_and_map(&sess, &mut forest); write_out_deps(&sess, input, &outputs, id.as_slice()); if stop_after_phase_2(&sess) { return; } - let type_arena = TypedArena::new(); let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id); phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir); if stop_after_phase_3(&analysis.ty_cx.sess) { return; } diff --git a/src/librustc_trans/test.rs b/src/librustc_trans/test.rs index 1e8c1fd14787d..50bcc698e896c 100644 --- a/src/librustc_trans/test.rs +++ b/src/librustc_trans/test.rs @@ -118,6 +118,7 @@ fn test_env(source_string: &str, .expect("phase 2 aborted"); let mut forest = ast_map::Forest::new(krate); + let type_arena = TypedArena::new(); let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest); let krate = ast_map.krate(); @@ -128,7 +129,6 @@ fn test_env(source_string: &str, let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map); let region_map = region::resolve_crate(&sess, krate); let stability_index = stability::Index::build(krate); - let type_arena = TypedArena::new(); let tcx = ty::mk_ctxt(sess, &type_arena, def_map, diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index d23e53d2e69bf..1c8276a994594 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -274,7 +274,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 { @@ -312,10 +312,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>) } #[deriving(Clone)] @@ -344,8 +344,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> } @@ -356,13 +356,13 @@ struct ArmData<'p, 'blk, 'tcx: 'blk> { * 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 @@ -383,11 +383,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()), @@ -420,13 +420,13 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, type EnterPatterns<'a, 'p> = |&[&'p ast::Pat]|: 'a -> Option>; -fn enter_match<'a, 'b, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn enter_match<'a, 'b, '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, e: EnterPatterns<'b, 'p>) - -> Vec> { + -> Vec> { debug!("enter_match(bcx={}, m={}, col={}, val={})", bcx.to_str(), m.repr(bcx.tcx()), @@ -466,12 +466,12 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx>(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()), @@ -519,16 +519,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()), @@ -562,8 +562,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(); @@ -602,16 +602,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 = Vec::from_fn(adt::num_args(repr, disr_val), |i| { adt::trans_field_ptr(bcx, repr, val, disr_val, i) @@ -654,12 +654,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); @@ -787,16 +787,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 `{}`", @@ -831,10 +831,10 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, } } -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 each binding in `data.bindings_map`, adds an appropriate entry into * the `fcx.lllocals` map @@ -887,14 +887,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), @@ -935,8 +935,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) { @@ -991,13 +991,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, @@ -1098,7 +1098,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 }; @@ -1118,11 +1118,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; } _ => { @@ -1169,14 +1169,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; @@ -1216,7 +1216,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 @@ -1236,12 +1236,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) } @@ -1256,7 +1256,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 @@ -1288,7 +1288,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 @@ -1344,11 +1344,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; @@ -1356,7 +1356,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; } @@ -1415,9 +1415,9 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, return bcx; } -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> { /*! * Generates code for a local variable declaration like * `let ;` or `let = `. @@ -1427,9 +1427,9 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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(); @@ -1481,11 +1481,11 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -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> { /*! * Generates code for argument patterns like `fn foo(: T)`. * Creates entries in the `lllocals` map for each of the bindings @@ -1534,11 +1534,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() { @@ -1556,14 +1556,14 @@ 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>(bcx: Block<'blk, 'tcx>, +fn mk_binding_alloca<'fcx, 'blk, 'tcx, A>(bcx: Block<'fcx, 'blk, 'tcx>, p_id: ast::NodeId, ident: &ast::Ident, cleanup_scope: cleanup::ScopeId, arg: A, - populate: |A, Block<'blk, 'tcx>, ValueRef, Ty<'tcx>| - -> Block<'blk, 'tcx>) - -> Block<'blk, 'tcx> { + populate: |A, Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>| + -> Block<'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let var_ty = node_id_type(bcx, p_id); // Allocate memory on stack for the binding. @@ -1582,11 +1582,11 @@ fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, bcx } -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> { /*! * A simple version of the pattern matching code that only handles * irrefutable patterns. This is used in let/argument patterns, diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index e7d1b9726a1b1..1a9a1445b8722 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -144,7 +144,7 @@ pub struct Struct<'tcx> { * 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)) } @@ -626,7 +626,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, * * 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 { @@ -643,7 +643,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; @@ -719,8 +719,8 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr) * * 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), @@ -745,7 +745,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) => { @@ -824,7 +824,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 @@ -863,8 +863,11 @@ 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::>(); @@ -877,10 +880,10 @@ 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>( - bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, value: ValueRef, - f: |Block<'blk, 'tcx>, &Struct<'tcx>, ValueRef| -> Block<'blk, 'tcx>) - -> Block<'blk, 'tcx> { +pub fn fold_variants<'fcx, 'blk, 'tcx>( + bcx: Block<'fcx, 'blk, 'tcx>, r: &Repr<'tcx>, value: ValueRef, + f: |Block<'fcx, 'blk, 'tcx>, &Struct<'tcx>, ValueRef| -> Block<'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let fcx = bcx.fcx; match *r { Univariant(ref st, _) => { @@ -892,7 +895,7 @@ pub fn fold_variants<'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() { @@ -900,7 +903,7 @@ pub fn fold_variants<'blk, 'tcx>( format!("enum-variant-iter-{}", discr.to_string()).as_slice() ); 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::>(); @@ -908,7 +911,7 @@ pub fn fold_variants<'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 @@ -918,8 +921,10 @@ pub fn fold_variants<'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 ptr_ty = ty::mk_imm_ptr(bcx.tcx(), ty::mk_bool()); match *r { Univariant(ref st, true) => { diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index 9b499b6d1a147..96ce12124e169 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -28,8 +28,8 @@ use syntax::ast; 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 bdf2eca21d6ec..1b4d148e19680 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -345,7 +345,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(); @@ -354,7 +354,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, @@ -369,12 +369,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: @@ -386,8 +386,8 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) } -pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>) - -> Result<'blk, 'tcx> { +pub fn malloc_raw_dyn_proc<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, t: Ty<'tcx>) + -> Result<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("malloc_raw_dyn_proc"); let ccx = bcx.ccx(); @@ -560,12 +560,12 @@ pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) { // Used only for creating scalar comparison glue. 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 { @@ -581,7 +581,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, @@ -641,8 +641,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,24 +679,24 @@ pub fn compare_simd_types<'blk, 'tcx>( } } -pub type val_and_ty_fn<'a, 'blk, 'tcx> = - |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'blk, 'tcx>; +pub type val_and_ty_fn<'a, 'fcx, 'blk, 'tcx> = + |Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'fcx, 'blk, 'tcx>; // Iterates through the elements of a structural type. -pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn iter_structural_ty<'a, 'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, av: ValueRef, t: Ty<'tcx>, - f: val_and_ty_fn<'a, 'blk, 'tcx>) - -> Block<'blk, 'tcx> { + f: val_and_ty_fn<'a, 'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("iter_structural_ty"); - fn iter_variant<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, + fn iter_variant<'a, 'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, repr: &adt::Repr<'tcx>, av: ValueRef, variant: &ty::VariantInfo<'tcx>, substs: &subst::Substs<'tcx>, - f: val_and_ty_fn<'a, 'blk, 'tcx>) - -> Block<'blk, 'tcx> { + f: val_and_ty_fn<'a, 'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("iter_variant"); let tcx = cx.tcx(); let mut cx = cx; @@ -779,7 +779,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, cx = f(cx, lldiscrim_a, ty::mk_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"); @@ -791,7 +791,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, .as_slice()); 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") @@ -803,7 +803,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>, &**variant, substs, |x,y,z| f(x,y,z)); - Br(variant_cx, next_cx.llbb); + Br(variant_cx, next_cx.data.llbb); } cx = next_cx; } @@ -863,14 +863,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") @@ -963,7 +963,7 @@ 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: Vec , fn_ty: Ty<'tcx>, @@ -971,9 +971,9 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // FIXME(15064) is_lang_item is a horrible hack, please remove it // at the soonest opportunity. is_lang_item: bool) - -> (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); } @@ -985,7 +985,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, get_fn_llvm_attributes(bcx.ccx(), fn_ty) }; - match bcx.opt_node_id { + match bcx.data.opt_node_id { None => { debug!("invoke at ???"); } @@ -995,7 +995,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } if need_invoke(bcx) { - debug!("invoking {} at {}", llfn, bcx.llbb); + debug!("invoking {} at {}", llfn, bcx.data.llbb); for &llarg in llargs.iter() { debug!("arg: {}", llarg); } @@ -1010,12 +1010,12 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llresult = Invoke(bcx, llfn, llargs.as_slice(), - normal_bcx.llbb, + normal_bcx.data.llbb, landing_pad, Some(attributes)); return (llresult, normal_bcx); } else { - debug!("calling {} at {}", llfn, bcx.llbb); + debug!("calling {} at {}", llfn, bcx.data.llbb); for &llarg in llargs.iter() { debug!("arg: {}", llarg); } @@ -1036,21 +1036,21 @@ 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); } return v; } -pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, +pub fn load_ty<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, ptr: ValueRef, t: Ty<'tcx>) -> ValueRef { /*! * Helper for loading values from memory. Does the necessary conversion if @@ -1089,33 +1089,33 @@ pub fn ignore_lhs(_bcx: Block, local: &ast::Local) -> bool { } } -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> { - common::BlockS::new(llbb, is_lpad, None, fcx) + -> Block<'fcx, 'blk, 'tcx> { + common::Block::new(llbb, is_lpad, None, fcx) } -pub fn with_cond<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn with_cond<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, - f: |Block<'blk, 'tcx>| -> Block<'blk, 'tcx>) - -> Block<'blk, 'tcx> { + f: |Block<'fcx, 'blk, 'tcx>| -> 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 } @@ -1165,7 +1165,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"); @@ -1180,8 +1180,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); @@ -1213,7 +1213,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); @@ -1230,7 +1232,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()); } @@ -1239,10 +1241,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()); } @@ -1256,7 +1258,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()); } @@ -1423,15 +1425,15 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool { // // 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={})", @@ -1481,17 +1483,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 { @@ -1554,8 +1556,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> { @@ -1615,12 +1617,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"); @@ -1647,13 +1649,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); @@ -1701,14 +1703,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) @@ -1726,8 +1728,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) { @@ -1921,7 +1923,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); } } @@ -1973,13 +1975,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 6d0f598044235..299249b473d6c 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -83,13 +83,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())); @@ -104,8 +104,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 {mut bcx, datum} = expr::trans(bcx, expr); match datum.ty.sty { ty::ty_bare_fn(..) => { @@ -133,18 +133,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 { @@ -237,11 +237,11 @@ pub fn trans_fn_ref(bcx: Block, def_id: ast::DefId, node: ExprOrMethodCall) -> V trans_fn_ref_with_substs(bcx, def_id, node, 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, @@ -253,7 +253,7 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Translates the adapter that deconstructs a `Box` object into /// `Trait` so that a by-value self method can be called. -pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_unboxing_shim<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, llshimmedfn: ValueRef, fty: &ty::BareFnTy<'tcx>, method_id: ast::DefId, @@ -318,9 +318,9 @@ pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, boxed_function_type, function_name.as_slice()); - let block_arena = TypedArena::new(); let empty_param_substs = Substs::trans_empty(); let return_type = ty::ty_fn_ret(boxed_function_type); + let block_arena = TypedArena::new(); let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, @@ -398,8 +398,8 @@ pub fn trans_unboxing_shim<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llfn } -pub fn trans_fn_ref_with_substs<'blk, 'tcx>( - bcx: Block<'blk, 'tcx>, // +pub fn trans_fn_ref_with_substs<'fcx, 'blk, 'tcx>( + bcx: Block<'fcx, 'blk, 'tcx>, // def_id: ast::DefId, // def id of fn node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A substs: subst::Substs<'tcx>) // vtables for the call @@ -609,12 +609,12 @@ pub fn trans_fn_ref_with_substs<'blk, '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)), @@ -624,12 +624,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); @@ -645,11 +645,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 { @@ -668,15 +668,15 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, dest) } -pub fn trans_call_inner<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn trans_call_inner<'a, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, call_info: Option, callee_ty: Ty<'tcx>, - get_callee: |bcx: Block<'blk, 'tcx>, + get_callee: |bcx: Block<'fcx, 'blk, 'tcx>, arg_cleanup_scope: cleanup::ScopeId| - -> Callee<'blk, 'tcx>, + -> Callee<'fcx, 'blk, 'tcx>, args: CallArgs<'a, 'tcx>, dest: Option) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { /*! * This behemoth of a function translates function calls. * Unfortunately, in order to generate more efficient LLVM @@ -909,14 +909,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> { // Translate the `self` argument first. if !ignore_self { let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &*arg_exprs[0])); @@ -968,14 +968,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::ty_fn_args(fn_ty); if !ignore_self { @@ -1014,14 +1014,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"); @@ -1105,12 +1105,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 b0235be7497ea..d294dcb97575c 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -23,7 +23,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; @@ -33,13 +33,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>, @@ -61,13 +61,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"), @@ -99,10 +99,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>; @@ -135,12 +135,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), @@ -149,7 +154,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()); @@ -189,10 +194,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { CustomScopeIndex { index: index } } - 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> { /*! * Removes the cleanup scope for id `cleanup_scope`, which * must be at the top of the cleanup stack, and generates the @@ -238,10 +243,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { let _ = self.pop_scope(); } - 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> { /*! * Removes the top cleanup scope from the stack, which must be * a temporary scope, and generates the code to do its @@ -271,7 +276,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.ccx.sess().bug("no loop scope found"); } - fn normal_exit_block(&'blk self, + fn normal_exit_block(&self, cleanup_scope: ast::NodeId, exit: uint) -> BasicBlockRef { /*! @@ -283,7 +288,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit)) } - fn return_exit_block(&'blk self) -> BasicBlockRef { + fn return_exit_block(&self) -> BasicBlockRef { /*! * Returns a block to branch to which will perform all pending * cleanups and then return from this function @@ -490,7 +495,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> { self.scopes.borrow().iter().rev().any(|s| s.needs_invoke()) } - fn get_landing_pad(&'blk self) -> BasicBlockRef { + fn get_landing_pad(&self) -> BasicBlockRef { /*! * Returns a basic block to branch to in the event of a panic. * This block will run the panic cleanups and eventually @@ -559,13 +564,13 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx (*scopes)[custom_scope.index].kind.is_temp() } - 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> { /*! Generates the cleanups for `scope` into `bcx` */ 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); } @@ -593,7 +598,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx f(self.scopes.borrow().last().unwrap()) } - fn trans_cleanups_to_exit_scope(&'blk self, + fn trans_cleanups_to_exit_scope(&self, label: EarlyExitLabel) -> BasicBlockRef { /*! @@ -649,7 +654,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; } @@ -740,7 +745,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")); @@ -756,7 +761,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx prev_llbb } - fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef { + fn get_or_create_landing_pad(&self) -> BasicBlockRef { /*! * Creates a landing pad for the top scope, if one does not * exist. The landing pad will perform all cleanups necessary @@ -783,7 +788,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.as_slice(), None); - last_scope.cached_landing_pad = Some(pad_bcx.llbb); + last_scope.cached_landing_pad = Some(pad_bcx.data.llbb); } } } @@ -845,12 +850,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 { @@ -908,7 +913,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, @@ -978,10 +983,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 { @@ -1018,10 +1023,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 { @@ -1052,10 +1057,10 @@ impl<'tcx> Cleanup<'tcx> for FreeSlice { false } - fn trans<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk, 'tcx>(&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 { @@ -1083,10 +1088,10 @@ impl<'tcx> Cleanup<'tcx> for LifetimeEnd { true } - fn trans<'blk, 'tcx>(&self, - bcx: Block<'blk, 'tcx>, + fn trans<'fcx, 'blk, 'tcx>(&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 @@ -1140,28 +1145,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); @@ -1198,7 +1203,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> { @@ -1206,13 +1211,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 ca955975dfb30..796d5ad3f51be 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -137,10 +137,10 @@ fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> { ty::mk_tup(tcx, vec!(ty::mk_uint(), ty::mk_nil_ptr(tcx), ptr, ptr, t)) } -fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn allocate_cbox<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, store: ty::TraitStore, cdata_ty: Ty<'tcx>) - -> Result<'blk, 'tcx> { + -> Result<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::allocate_cbox"); let tcx = bcx.tcx(); @@ -157,20 +157,20 @@ fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -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> , store: ty::TraitStore) - -> ClosureResult<'blk, 'tcx> { + -> ClosureResult<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("closure::store_environment"); let ccx = bcx.ccx(); let tcx = ccx.tcx(); @@ -225,11 +225,11 @@ 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, store: ty::TraitStore) - -> 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 @@ -248,11 +248,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: @@ -296,12 +296,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. @@ -367,8 +367,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; @@ -386,13 +386,13 @@ impl<'a, 'tcx> ClosureEnv<'a, 'tcx> { } } -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> { /*! * * Translates the body of a closure expression. @@ -453,7 +453,7 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, /// Returns the LLVM function declaration for an unboxed closure, creating it /// if necessary. If the ID does not correspond to a closure ID, returns None. -pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn get_or_create_declaration_if_unboxed_closure<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>) -> Option { @@ -505,13 +505,13 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, Some(llfn) } -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"); debug!("trans_unboxed_closure()"); @@ -632,8 +632,8 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let _icx = push_ctxt("closure::get_wrapper_for_bare_fn"); - let arena = TypedArena::new(); let empty_param_substs = Substs::trans_empty(); + let arena = TypedArena::new(); let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, true, f.sig.output, &empty_param_substs, None, &arena); let bcx = init_function(&fcx, true, f.sig.output); @@ -672,11 +672,11 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn } -pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn make_closure_from_bare_fn<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, closure_ty: Ty<'tcx>, def: def::Def, fn_ptr: ValueRef) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust"); let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true); fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx()))); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index 235805a7c8308..5d3042df2b906 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -200,7 +200,7 @@ pub 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 @@ -251,26 +251,26 @@ 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>>, } -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() { @@ -314,7 +314,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 { @@ -327,43 +327,43 @@ 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 llbb = name.with_c_str(|buf| { llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf) }); - BlockS::new(llbb, is_lpad, opt_node_id, self) + Block::new(llbb, is_lpad, opt_node_id, self) } } - 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; } } @@ -379,7 +379,16 @@ 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, +} + +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 @@ -396,29 +405,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 } @@ -461,18 +450,41 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> { t.repr(self.tcx()) } + pub fn to_str(&self) -> String { + self.data.to_str() + } + + pub fn new(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, + } + } +} + +impl BlockS { pub fn to_str(&self) -> String { format!("[block {:p}]", self) } } -impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> { +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 node_method_ty(&self, method_call: typeck::MethodCall) -> Option> { @@ -480,7 +492,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 adjustments<'a>(&'a self) -> &'a RefCell>> { @@ -510,13 +522,13 @@ impl<'blk, 'tcx> mc::Typer<'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, @@ -750,21 +762,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> { t.subst(bcx.tcx(), bcx.fcx.param_substs) } -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: Block<'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: Block<'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)) } @@ -885,9 +898,9 @@ pub enum ExprOrMethodCall { MethodCall(typeck::MethodCall) } -pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - node: ExprOrMethodCall) - -> subst::Substs<'tcx> +pub fn node_id_substs<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + node: ExprOrMethodCall) + -> subst::Substs<'tcx> { let tcx = bcx.tcx(); diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index 10a73033b64af..9019db2dfefd6 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>, - s: &ast::Stmt) - -> Block<'blk, 'tcx> { +pub fn trans_stmt<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, + s: &ast::Stmt) + -> 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 ty::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>, - b: &ast::Block, - mut dest: expr::Dest) - -> Block<'blk, 'tcx> { +pub fn trans_block<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + b: &ast::Block, + mut dest: expr::Dest) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_block"); let fcx = bcx.fcx; let mut bcx = bcx; @@ -122,7 +122,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()); } } @@ -131,13 +131,13 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - if_id: ast::NodeId, - cond: &ast::Expr, - thn: &ast::Block, - els: Option<&ast::Expr>, - dest: expr::Dest) - -> 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<'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())); @@ -190,13 +190,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); } } @@ -207,11 +207,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, next_bcx } -pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - loop_id: ast::NodeId, - cond: &ast::Expr, - body: &ast::Block) - -> 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<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_while"); let fcx = bcx.fcx; @@ -230,9 +230,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); @@ -240,23 +240,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>, - loop_info: NodeInfo, - pat: &ast::Pat, - head: &ast::Expr, - body: &ast::Block) - -> 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<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_for"); // bcx @@ -284,8 +284,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); @@ -338,7 +338,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. @@ -366,17 +366,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>, - loop_id: ast::NodeId, - body: &ast::Block) - -> Block<'blk, 'tcx> { +pub fn trans_loop<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + loop_id: ast::NodeId, + body: &ast::Block) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_loop"); let fcx = bcx.fcx; @@ -394,26 +394,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>, - expr_id: ast::NodeId, - opt_label: Option, - exit: uint) - -> 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<'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; } @@ -438,23 +438,23 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - expr_id: ast::NodeId, - label_opt: Option) - -> Block<'blk, 'tcx> { +pub fn trans_break<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + expr_id: ast::NodeId, + label_opt: Option) + -> 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>, - expr_id: ast::NodeId, - label_opt: Option) - -> Block<'blk, 'tcx> { +pub fn trans_cont<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + expr_id: ast::NodeId, + label_opt: Option) + -> 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; @@ -483,10 +483,10 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return bcx; } -pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - sp: Span, - fail_str: InternedString) - -> Block<'blk, 'tcx> { +pub fn trans_fail<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + sp: Span, + fail_str: InternedString) + -> Block<'fcx, 'blk, 'tcx> { let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_value"); @@ -507,11 +507,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>, - sp: Span, - index: ValueRef, - len: ValueRef) - -> Block<'blk, 'tcx> { +pub fn trans_fail_bounds_check<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, + sp: Span, + index: ValueRef, + len: ValueRef) + -> 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 354a607220715..8e28bf7bc0519 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -50,8 +50,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>, } @@ -99,23 +99,23 @@ 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)) } -pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, +pub fn lvalue_scratch_datum<'fcx, 'blk, 'tcx, A>(bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, name: &str, zero: bool, scope: cleanup::ScopeId, arg: A, - populate: |A, Block<'blk, 'tcx>, ValueRef| - -> Block<'blk, 'tcx>) - -> DatumBlock<'blk, 'tcx, Lvalue> { + populate: |A, Block<'fcx, 'blk, 'tcx>, ValueRef| + -> Block<'fcx, 'blk, 'tcx>) + -> DatumBlock<'fcx, 'blk, 'tcx, Lvalue> { /*! * Allocates temporary space on the stack using alloca() and * returns a by-ref Datum pointing to it. The memory will be @@ -140,7 +140,7 @@ pub fn lvalue_scratch_datum<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(scratch, ty, Lvalue)) } -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> { @@ -174,8 +174,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>) { @@ -194,11 +194,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>, + fn post_store<'fcx, 'blk, 'tcx>(&self, + bcx: Block<'fcx, 'blk, 'tcx>, val: ValueRef, ty: Ty<'tcx>) - -> Block<'blk, 'tcx>; + -> Block<'fcx, 'blk, 'tcx>; /** * True if this mode is a reference mode, meaning that the datum's @@ -214,11 +214,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 @@ -234,11 +234,11 @@ impl KindOps for Rvalue { } impl KindOps for Lvalue { - 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 an lvalue is moved, we must zero out the memory in which * it resides so as to cancel cleanup. If an @T lvalue is @@ -264,11 +264,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), @@ -288,8 +288,8 @@ impl KindOps for Expr { } impl<'tcx> Datum<'tcx, Rvalue> { - pub fn add_clean<'a>(self, - fcx: &FunctionContext<'a, 'tcx>, + pub fn add_clean<'blk>(self, + fcx: &FunctionContext<'blk, 'tcx>, scope: cleanup::ScopeId) -> ValueRef { /*! @@ -303,11 +303,11 @@ impl<'tcx> Datum<'tcx, Rvalue> { self.val } - 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> { /*! * Returns an lvalue datum (that is, a by ref datum with * cleanup scheduled). If `self` is not already an lvalue, @@ -329,8 +329,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), @@ -342,8 +342,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) @@ -402,11 +402,11 @@ impl<'tcx> Datum<'tcx, Expr> { |r| r) } - 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); @@ -418,8 +418,8 @@ impl<'tcx> Datum<'tcx, Expr> { } } - 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) { /*! * Arranges cleanup for `self` if it is an rvalue. Use when @@ -434,11 +434,11 @@ impl<'tcx> Datum<'tcx, Expr> { }) } - 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> { /*! * Ensures that `self` will get cleaned up, if it is not an lvalue * already. @@ -447,11 +447,11 @@ impl<'tcx> Datum<'tcx, Expr> { 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!(ty::lltype_is_sized(bcx.tcx(), self.ty), @@ -464,10 +464,10 @@ impl<'tcx> Datum<'tcx, Expr> { }) } - 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> { /*! * Ensures that we have an rvalue datum (that is, a datum with * no cleanup scheduled). @@ -515,7 +515,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>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>, + pub fn get_element<'fcx, 'blk>(&self, bcx: Block<'fcx, 'blk, 'tcx>, ty: Ty<'tcx>, gep: |ValueRef| -> ValueRef) -> Datum<'tcx, Lvalue> { let val = match self.ty.sty { @@ -555,10 +555,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { Datum { val: val, ty: ty, kind: kind.to_expr_kind() } } - 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> { /*! * Moves or copies this value into a new home, as appropriate * depending on the type of the datum. This method consumes @@ -572,10 +572,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { self.kind.post_store(bcx, self.val, self.ty) } - 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> { /*! * Helper function that performs a shallow copy of this value * into `dst`, which should be a pointer to a memory location @@ -604,10 +604,10 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { return bcx; } - 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> { + -> Block<'fcx, 'blk, 'tcx> { /*! * Copies the value into a new location. This function always * preserves the existing datum as a valid value. Therefore, @@ -634,7 +634,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> { appropriate_rvalue_mode(ccx, self.ty) } - pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef { + pub fn to_llscalarish<'fcx, 'blk>(self, bcx: Block<'fcx, 'blk, 'tcx>) -> ValueRef { /*! * Converts `self` into a by-value `ValueRef`. Consumes this * datum (i.e., absolves you of responsibility to cleanup the @@ -653,34 +653,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 a3472e194cf58..aeffc5fb0deba 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -881,7 +881,7 @@ 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_data_type: Ty<'tcx>, env_pointer: ValueRef, @@ -968,7 +968,7 @@ 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 fn_should_be_ignored(bcx.fcx) { @@ -1586,7 +1586,7 @@ fn compile_unit_metadata(cx: &CrateContext) { } } -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, @@ -1653,7 +1653,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 482b318e37202..9382b2f19d9b9 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -82,10 +82,10 @@ impl Dest { } } -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> { /*! * This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` * but it may generate better optimized LLVM code. @@ -124,9 +124,9 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id) } -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> { /*! * Translates an expression, returning a datum (and new block) * encapsulating the result. When possible, it is preferred to @@ -157,10 +157,10 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { GEPi(bcx, fat_ptr, &[0u, abi::FAT_PTR_ADDR]) } -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> { /*! * Helper for trans that apply adjustments from `expr` to `datum`, * which should be the unadjusted translation of `expr`. @@ -235,11 +235,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; @@ -272,10 +272,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())); @@ -298,7 +298,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>(bcx: Block<'blk, 'tcx>, + fn unsized_info<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, kind: &ty::UnsizeKind<'tcx>, id: ast::NodeId, unadjusted_ty: Ty<'tcx>, @@ -331,11 +331,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); @@ -367,10 +367,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, into_fat_ptr(bcx, expr, datum, dest_ty, base, info) } - 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)); @@ -378,13 +378,13 @@ 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>(bcx: Block<'blk, 'tcx>, + fn into_fat_ptr<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, dest_ty: Ty<'tcx>, - base: |Block<'blk, 'tcx>, ValueRef| -> ValueRef, - info: |Block<'blk, 'tcx>, ValueRef| -> ValueRef) - -> DatumBlock<'blk, 'tcx, Expr> { + base: |Block<'fcx, 'blk, 'tcx>, ValueRef| -> ValueRef, + info: |Block<'fcx, 'blk, 'tcx>, ValueRef| -> ValueRef) + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; // Arrange cleanup @@ -400,11 +400,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(); @@ -428,11 +428,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(); @@ -463,10 +463,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, scratch.to_expr_datum()) } - fn add_env<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + fn add_env<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { // This is not the most efficient thing possible; since closures // are two words it'd be better if this were compiled in // 'dest' mode, but I can't find a nice way to structure the @@ -480,10 +480,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -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> { /*! * Translates an expression in "lvalue" mode -- meaning that it * returns a reference to the memory that the expr represents. @@ -500,9 +500,9 @@ pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return datum.to_lvalue_datum(bcx, name, expr.id); } -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> { /*! * A version of `trans` that ignores adjustments. You almost * certainly do not want to call this directly. @@ -556,17 +556,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"); @@ -666,10 +666,10 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_field<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, base: &ast::Expr, get_idx: |&'blk ty::ctxt<'tcx>, &[ty::field<'tcx>]| -> uint) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let mut bcx = bcx; let _icx = push_ctxt("trans_rec_field"); @@ -699,27 +699,27 @@ fn trans_field<'blk, 'tcx>(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"); @@ -825,10 +825,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"); @@ -847,7 +847,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 { @@ -901,13 +901,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; } @@ -988,10 +988,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(); @@ -1140,11 +1140,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 { @@ -1188,10 +1188,10 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +fn trans_def_fn_unadjusted<'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, ref_expr: &ast::Expr, def: def::Def) - -> DatumBlock<'blk, 'tcx, Expr> { + -> DatumBlock<'fcx, 'blk, 'tcx, Expr> { let _icx = push_ctxt("trans_def_datum_unadjusted"); let llfn = match def { @@ -1218,7 +1218,7 @@ fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(llfn, fn_ty, RvalueExpr(Rvalue::new(ByValue)))) } -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> { /*! @@ -1320,12 +1320,12 @@ pub fn with_field_tys<'tcx, R>(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, - dest: Dest) -> Block<'blk, 'tcx> { + dest: Dest) -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_rec"); let ty = node_id_type(bcx, expr_id); @@ -1402,14 +1402,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); @@ -1508,10 +1508,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); @@ -1519,11 +1519,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"); @@ -1567,11 +1567,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!(ty::type_is_sized(bcx.tcx(), contents_ty)); @@ -1596,10 +1596,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")); @@ -1629,7 +1629,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, @@ -1637,7 +1637,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(); @@ -1725,12 +1725,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; @@ -1738,7 +1738,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(); } @@ -1746,30 +1746,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(); @@ -1806,13 +1806,13 @@ 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) - -> 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)), @@ -1827,12 +1827,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 @@ -1932,10 +1932,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(); @@ -2024,12 +2024,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; @@ -2056,10 +2056,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 @@ -2080,11 +2080,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) { @@ -2094,11 +2094,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={})", @@ -2189,11 +2189,11 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return r; - 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> { /*! * We microoptimize derefs of owned pointers a bit here. * Basically, the idea is to make the deref of an rvalue diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 1f6aeacc86058..04c3759d69bc1 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -201,13 +201,13 @@ pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, llfn } -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> { /*! * Prepares a call to a native function. This requires adapting * from the Rust argument passing rules to the native rules. diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 4ed7983789696..e3fb2529a4ee9 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -44,9 +44,9 @@ use libc::c_uint; use syntax::ast; use syntax::parse::token; -pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, - size: ValueRef, align: ValueRef) - -> Block<'blk, 'tcx> { +pub fn trans_exchange_free_dyn<'fcx, 'blk, 'tcx>(cx: Block<'fcx, 'blk, 'tcx>, v: ValueRef, + size: ValueRef, align: ValueRef) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("trans_exchange_free"); let ccx = cx.ccx(); callee::trans_lang_call(cx, @@ -55,14 +55,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!(ty::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); @@ -102,11 +102,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"); @@ -130,11 +130,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(bcx, v, vp); @@ -185,13 +185,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 ty::type_is_sized(bcx.tcx(), t) { v0 @@ -205,13 +205,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); // Find and call the actual destructor @@ -298,8 +298,9 @@ 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 ty::type_is_sized(bcx.tcx(), t) { @@ -354,8 +355,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 { @@ -532,8 +533,8 @@ fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, fn make_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, llfn: ValueRef, - helper: for<'blk> |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>| - -> Block<'blk, 'tcx>, + helper: for<'fcx, 'blk> |Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>| + -> Block<'fcx, 'blk, 'tcx>, name: &str) -> ValueRef { let _icx = push_ctxt("make_generic_glue"); diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 6bdb35f8d6074..7dd55ef9b5753 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -135,7 +135,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, @@ -143,7 +143,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; @@ -557,7 +557,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(); @@ -587,7 +587,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); @@ -612,7 +612,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 0ff7f3ee71cc6..74271176e9698 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -106,11 +106,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) = @@ -323,12 +323,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) => { @@ -377,7 +377,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -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> @@ -422,12 +422,12 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -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> { /*! * Create a method callee where the method is coming from a trait * object (e.g., Box type). In this case, we must pull the fn @@ -466,11 +466,11 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_trait_callee_from_llval(bcx, method_ty, n_method, llval) } -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> { /*! * Same as `trans_trait_callee()` above, except that it is given * a by-ref pointer to the object pair. @@ -525,7 +525,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, '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: Rc>) -> ValueRef @@ -674,7 +674,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 { @@ -731,12 +731,12 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }).collect() } -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: Rc>, dest: expr::Dest) - -> Block<'blk, 'tcx> { + -> Block<'fcx, 'blk, 'tcx> { /*! * Generates the code to convert from a pointer (`Box`, `&T`, etc) * into an object (`Box`, `&Trait`, etc). This means creating a diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 8e986defb6a36..28cfaa81e11c1 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -50,11 +50,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(); @@ -107,10 +107,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". @@ -134,10 +134,10 @@ pub fn trans_fixed_vstore<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, }; } -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> { /*! * &[...] allocates memory on the stack and writes the values into it, * returning the vector (the caller must make the reference). "..." is @@ -208,11 +208,11 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, immediate_rvalue_bcx(bcx, llfixed, vec_ty).to_expr_datumblock() } -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> { /*! * Literal strings translate to slices into static memory. This is * different from trans_slice_vstore() above because it doesn't need to copy @@ -239,12 +239,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; @@ -337,14 +337,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(); @@ -440,15 +440,15 @@ pub fn get_base_and_len(bcx: Block, } } -pub type iter_vec_block<'a, 'blk, 'tcx> = - |Block<'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'blk, 'tcx>; +pub type iter_vec_block<'a, 'fcx, 'blk, 'tcx> = + |Block<'fcx, 'blk, 'tcx>, ValueRef, Ty<'tcx>|: 'a -> Block<'fcx, 'blk, 'tcx>; -pub fn iter_vec_loop<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn iter_vec_loop<'a, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, data_ptr: ValueRef, vt: &VecTypes<'tcx>, count: ValueRef, - f: iter_vec_block<'a, 'blk, 'tcx>) - -> Block<'blk, 'tcx> { + f: iter_vec_block<'a, 'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("tvec::iter_vec_loop"); let fcx = bcx.fcx; @@ -457,14 +457,14 @@ pub fn iter_vec_loop<'a, 'blk, 'tcx>(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 }; @@ -473,7 +473,7 @@ pub fn iter_vec_loop<'a, 'blk, 'tcx>(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 @@ -485,7 +485,7 @@ pub fn iter_vec_loop<'a, 'blk, 'tcx>(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 @@ -493,18 +493,18 @@ pub fn iter_vec_loop<'a, 'blk, 'tcx>(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<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, +pub fn iter_vec_raw<'a, 'fcx, 'blk, 'tcx>(bcx: Block<'fcx, 'blk, 'tcx>, data_ptr: ValueRef, unit_ty: Ty<'tcx>, len: ValueRef, - f: iter_vec_block<'a, 'blk, 'tcx>) - -> Block<'blk, 'tcx> { + f: iter_vec_block<'a, 'fcx, 'blk, 'tcx>) + -> Block<'fcx, 'blk, 'tcx> { let _icx = push_ctxt("tvec::iter_vec_raw"); let fcx = bcx.fcx; @@ -523,19 +523,19 @@ pub fn iter_vec_raw<'a, 'blk, 'tcx>(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 8d74275c92ac7..4352b46ad5794 100644 --- a/src/librustc_trans/trans/value.rs +++ b/src/librustc_trans/trans/value.rs @@ -59,7 +59,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/librustdoc/core.rs b/src/librustdoc/core.rs index b040a4bfd2a09..9b319bb328c8f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -119,9 +119,9 @@ pub fn run_core(libs: Vec, cfgs: Vec, externs: Externs, .expect("phase_2_configure_and_expand aborted in rustdoc!"); let mut forest = ast_map::Forest::new(krate); + let type_arena = TypedArena::new(); let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest); - let type_arena = TypedArena::new(); let driver::CrateAnalysis { exported_items, public_items, ty_cx, .. } = driver::phase_3_run_analysis_passes(sess, ast_map, &type_arena, name); diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index d4d24c1e12fc8..c007196a9f878 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -1065,13 +1065,13 @@ mod tests { #[test] fn test_override_env() { use os; + let path_val: String; let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")]; // In some build environments (such as chrooted Nix builds), `env` can // only be found in the explicitly-provided PATH env variable, not in // default places such as /bin or /usr/bin. So we need to pass through // PATH to our sub-process. - let path_val: String; match os::getenv("PATH") { None => {} Some(val) => { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9635f0175f075..340c3667a26b9 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -220,9 +220,8 @@ impl<'a, 'v> Visitor<'v> for Context<'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") } for item in items.iter() { 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/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs index f2ff5f86f6393..538dfa0a2518b 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs @@ -14,10 +14,11 @@ extern crate collections; use std::collections::HashMap; fn main() { + let tmp; let mut buggy_map: HashMap = HashMap::new(); buggy_map.insert(42, &*box 1); //~ ERROR borrowed value does not live long enough - // but it is ok if we use a temporary - let tmp = box 2; + // but it is ok if we use a temporary that outlives `buggy_map`. + tmp = box 2; buggy_map.insert(43, &*tmp); } diff --git a/src/test/compile-fail/borrowck-let-suggestion.rs b/src/test/compile-fail/borrowck-let-suggestion.rs index cd1101c05d15f..961ecd4d4114d 100644 --- a/src/test/compile-fail/borrowck-let-suggestion.rs +++ b/src/test/compile-fail/borrowck-let-suggestion.rs @@ -10,7 +10,7 @@ fn f() { let x = [1i].iter(); //~ ERROR borrowed value does not live long enough - //~^^ NOTE reference must be valid for the block + //~^ NOTE reference must be valid for the block //~^^ HELP consider using a `let` binding to increase its lifetime } diff --git a/src/test/compile-fail/issue-16465.rs b/src/test/compile-fail/destructor-restrictions.rs similarity index 67% rename from src/test/compile-fail/issue-16465.rs rename to src/test/compile-fail/destructor-restrictions.rs index 280f19cfe9cc7..02887d18a681b 100644 --- a/src/test/compile-fail/issue-16465.rs +++ b/src/test/compile-fail/destructor-restrictions.rs @@ -8,17 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Used to cause an ICE +// Tests the new destructor semantics. -struct Foo{ - x : T -} - -type FooInt = Foo; +use std::cell::RefCell; -impl Drop for FooInt { -//~^ ERROR cannot implement a destructor on a structure with type parameters - fn drop(&mut self){} +fn main() { + let b = { + let a = box RefCell::new(4i); + *a.borrow() + 1i //~ ERROR `*a` does not live long enough + }; + println!("{}", b); } - -fn main() {} diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs deleted file mode 100644 index 26b0c5503e32f..0000000000000 --- a/src/test/compile-fail/kindck-destructor-owned.rs +++ /dev/null @@ -1,44 +0,0 @@ -// 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. - - -use std::rc::Rc; - -struct Foo { - f: Rc, -} - -impl Drop for Foo { -//~^ ERROR the trait `core::kinds::Send` is not implemented for the type `Foo` -//~^^ NOTE cannot implement a destructor on a structure or enumeration that does not satisfy Send - fn drop(&mut self) { - } -} - -struct Bar<'a> { - f: &'a int, -} - -impl<'a> Drop for Bar<'a> { -//~^ ERROR E0141 - fn drop(&mut self) { - } -} - -struct Baz { - f: &'static int, -} - -impl Drop for Baz { - fn drop(&mut self) { - } -} - -fn main() { } diff --git a/src/test/compile-fail/regionck-closure-lifetimes.rs b/src/test/compile-fail/regionck-closure-lifetimes.rs index bb895a318ff17..1e1e7f40d9c4c 100644 --- a/src/test/compile-fail/regionck-closure-lifetimes.rs +++ b/src/test/compile-fail/regionck-closure-lifetimes.rs @@ -16,6 +16,7 @@ fn env<'a>(blk: |p: ||: 'a|) { let mut state = 0i; let statep = &mut state; blk(|| *statep = 1i); //~ ERROR captured variable `statep` does not outlive + //~^ ERROR closure outlives stack frame } fn no_env_no_for<'a>(blk: |p: |||: 'a) { diff --git a/src/test/compile-fail/regions-freevar.rs b/src/test/compile-fail/regions-freevar.rs index 76bbe71cf75b5..1a186ddb8bd1a 100644 --- a/src/test/compile-fail/regions-freevar.rs +++ b/src/test/compile-fail/regions-freevar.rs @@ -12,7 +12,7 @@ fn wants_static_fn(_x: ||: 'static) {} fn main() { let i = 3i; - wants_static_fn(|| { + wants_static_fn(|| { //~ ERROR closure outlives stack frame println!("i={}", i); //~ ERROR captured variable `i` does not outlive }) } diff --git a/src/test/compile-fail/unsafe-destructor-check-crash.rs b/src/test/compile-fail/unsafe-destructor-check-crash.rs deleted file mode 100644 index af675587728be..0000000000000 --- a/src/test/compile-fail/unsafe-destructor-check-crash.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - - - -// Regression test for issue #15557 - -#![allow(dead_code)] -struct AReg1<'a>(&'a u32); - -impl<'a> Drop for AReg1<'a> { -//~^ ERROR: cannot implement a destructor on a structure with type parameters - fn drop(&mut self) {} -} - -fn main() {} diff --git a/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot index d89a37308de06..566b09bcf84eb 100644 --- a/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot @@ -34,7 +34,7 @@ digraph block { N11 -> N12; N12 -> N13; N13 -> N14; - N14 -> N6[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 2i { break ; \"unreachable\"; },\lexiting scope_4 block { x -= 1i; if x == 2i { break ; \"unreachable\"; } }"]; + N14 -> N6[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if x == 2i { break ; \"unreachable\"; },\lexiting scope_6 block { x -= 1i; if x == 2i { break ; \"unreachable\"; } },\lexiting scope_7 block { x -= 1i; if x == 2i { break ; \"unreachable\"; } }"]; N15 -> N16; N16 -> N17; N17 -> N18; diff --git a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot index 4bd9fc9ec1ad1..394cbcb060232 100644 --- a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot @@ -61,7 +61,7 @@ digraph block { N12 -> N13; N13 -> N14; N14 -> N15; - N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l y -= 4i;\l x -= 5i;\l}\l"]; + N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 stmt break \'outer ;,\lexiting scope_3 block { break \'outer ; \"unreachable\"; },\lexiting scope_4 block { break \'outer ; \"unreachable\"; },\lexiting scope_5 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_6 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_7 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l,\lexiting scope_9 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l,\lexiting scope_10 expr \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_11 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_12 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_13 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l y -= 4i;\l x -= 5i;\l}\l,\lexiting scope_14 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l y -= 4i;\l x -= 5i;\l}\l"]; N16 -> N17; N17 -> N18; N18 -> N19; @@ -73,7 +73,7 @@ digraph block { N23 -> N24; N24 -> N25; N25 -> N26; - N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 2i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 2i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l"]; + N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if y >= 2i { break ; \"unreachable\"; },\lexiting scope_6 stmt if y >= 2i { break ; \"unreachable\"; },\lexiting scope_7 stmt if y >= 2i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l,\lexiting scope_9 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l"]; N27 -> N28; N28 -> N29; N29 -> N30; diff --git a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot index 16b871bd844bf..b27154418b4c5 100644 --- a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot @@ -64,7 +64,7 @@ digraph block { N12 -> N13; N13 -> N14; N14 -> N15; - N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l y -= 1i;\l x -= 1i;\l}\l"]; + N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 stmt continue \'outer ;,\lexiting scope_3 block { continue \'outer ; \"unreachable\"; },\lexiting scope_4 block { continue \'outer ; \"unreachable\"; },\lexiting scope_5 expr if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_6 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_7 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l,\lexiting scope_9 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l,\lexiting scope_10 expr \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l,\lexiting scope_11 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l,\lexiting scope_12 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l,\lexiting scope_13 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l y -= 1i;\l x -= 1i;\l}\l,\lexiting scope_14 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l }\l y -= 1i;\l x -= 1i;\l}\l"]; N16 -> N17; N17 -> N18; N18 -> N19; @@ -76,7 +76,7 @@ digraph block { N23 -> N24; N24 -> N25; N25 -> N26; - N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 1i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 1i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l"]; + N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if y >= 1i { break ; \"unreachable\"; },\lexiting scope_6 stmt if y >= 1i { break ; \"unreachable\"; },\lexiting scope_7 stmt if y >= 1i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l,\lexiting scope_9 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l"]; N27 -> N28; N28 -> N29; N29 -> N30; diff --git a/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot index ad2ef60ce2918..431711179d71f 100644 --- a/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot @@ -59,7 +59,7 @@ digraph block { N12 -> N13; N13 -> N14; N14 -> N15; - N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l \"unreachable\";\l}\l"]; + N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 stmt break \'outer ;,\lexiting scope_3 block { break \'outer ; \"unreachable\"; },\lexiting scope_4 block { break \'outer ; \"unreachable\"; },\lexiting scope_5 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_6 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_7 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l}\l,\lexiting scope_9 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l}\l,\lexiting scope_10 expr \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l,\lexiting scope_11 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l,\lexiting scope_12 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l,\lexiting scope_13 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l \"unreachable\";\l}\l,\lexiting scope_14 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l y -= 3i;\l x -= 5i;\l }\l \"unreachable\";\l}\l"]; N16 -> N17; N17 -> N18; N18 -> N19; diff --git a/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot index dcceb5bb937da..babdf6f410dd9 100644 --- a/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot @@ -62,7 +62,7 @@ digraph block { N12 -> N13; N13 -> N14; N14 -> N15; - N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l \"unreachable\";\l}\l"]; + N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 stmt continue \'outer ;,\lexiting scope_3 block { continue \'outer ; \"unreachable\"; },\lexiting scope_4 block { continue \'outer ; \"unreachable\"; },\lexiting scope_5 expr if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_6 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_7 stmt if x == 1i { continue \'outer ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l}\l,\lexiting scope_9 block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l}\l,\lexiting scope_10 expr \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l,\lexiting scope_11 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l,\lexiting scope_12 stmt \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l,\lexiting scope_13 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l \"unreachable\";\l}\l,\lexiting scope_14 block {\l \'inner:\l loop {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 2i { return; \"unreachable\"; }\l x -= 1i;\l y -= 3i;\l }\l \"unreachable\";\l}\l"]; N16 -> N17; N17 -> N18; N18 -> N19; diff --git a/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot index ddb5b865c2edb..6620a28dbe435 100644 --- a/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot @@ -90,7 +90,7 @@ digraph block { N13 -> N14; N14 -> N15; N15 -> N16; - N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l }\l}\l"]; + N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if x == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l }\l}\l,\lexiting scope_9 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l }\l}\l"]; N17 -> N18; N18 -> N19; N19 -> N20; @@ -107,7 +107,7 @@ digraph block { N30 -> N31; N31 -> N32; N32 -> N33; - N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l}\l"]; + N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if y == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l}\l,\lexiting scope_9 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { return; \"unreachable\"; }\l}\l"]; N34 -> N35; N35 -> N36; N36 -> N37; @@ -124,7 +124,7 @@ digraph block { N47 -> N48; N48 -> N49; N49 -> N50; - N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if z == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_5 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; }"]; + N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if z == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_8 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; },\lexiting scope_9 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; }"]; N51 -> N52; N52 -> N53; N53 -> N54; diff --git a/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot index 9fd4dbfc39553..1204b800213af 100644 --- a/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot @@ -90,7 +90,7 @@ digraph block { N13 -> N14; N14 -> N15; N15 -> N16; - N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l \'a:\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l }\l}\l"]; + N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if x == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if x == 0i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l \'a:\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l }\l}\l,\lexiting scope_9 block {\l if x == 0i { break ; \"unreachable\"; }\l x -= 1i;\l \'a:\l loop {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l }\l}\l"]; N17 -> N18; N18 -> N19; N19 -> N20; @@ -107,7 +107,7 @@ digraph block { N30 -> N31; N31 -> N32; N32 -> N33; - N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_5 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l"]; + N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if y == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if y == 0i { break ; \"unreachable\"; },\lexiting scope_8 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l,\lexiting scope_9 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l"]; N34 -> N35; N35 -> N36; N36 -> N37; @@ -124,7 +124,7 @@ digraph block { N47 -> N48; N48 -> N49; N49 -> N50; - N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if z == 0i { break ; \"unreachable\"; },\lexiting scope_4 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_5 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; }"]; + N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 stmt break ;,\lexiting scope_3 block { break ; \"unreachable\"; },\lexiting scope_4 block { break ; \"unreachable\"; },\lexiting scope_5 expr if z == 0i { break ; \"unreachable\"; },\lexiting scope_6 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_7 stmt if z == 0i { break ; \"unreachable\"; },\lexiting scope_8 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; },\lexiting scope_9 block { if z == 0i { break ; \"unreachable\"; } z -= 1i; }"]; N51 -> N52; N52 -> N53; N53 -> N54; @@ -143,7 +143,7 @@ digraph block { N64 -> N65; N65 -> N66; N66 -> N67; - N67 -> N28[label="exiting scope_0 expr continue \'a,\lexiting scope_1 stmt continue \'a ;,\lexiting scope_2 block { continue \'a ; \"unreachable\"; },\lexiting scope_3 expr if x > 10i { continue \'a ; \"unreachable\"; },\lexiting scope_4 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l"]; + N67 -> N28[label="exiting scope_0 expr continue \'a,\lexiting scope_1 stmt continue \'a ;,\lexiting scope_2 stmt continue \'a ;,\lexiting scope_3 block { continue \'a ; \"unreachable\"; },\lexiting scope_4 block { continue \'a ; \"unreachable\"; },\lexiting scope_5 expr if x > 10i { continue \'a ; \"unreachable\"; },\lexiting scope_6 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l,\lexiting scope_7 block {\l if y == 0i { break ; \"unreachable\"; }\l y -= 1i;\l \'a: loop { if z == 0i { break ; \"unreachable\"; } z -= 1i; }\l if x > 10i { continue \'a ; \"unreachable\"; }\l}\l"]; N68 -> N69; N69 -> N70; N70 -> N71; diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index b30c0a117a805..377507dcc77f3 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -14,7 +14,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..858a0d250d6e6 --- /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 uint, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b uint { self.f } +} + +pub struct P<'c> { + pub g: &'c uint, +} +pub trait M { + fn n(&self) -> uint; +} +impl<'d> M for P<'d> { + fn n(&self) -> uint { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return box p as Box; + } +} + +fn main() { + let w = E { f: &10u }; + let o = extension(&w); + assert_eq!(o.n(), 10u); +} 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..71f307387c768 --- /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 uint, +} +impl<'b> E<'b> { + pub fn m(&self) -> &'b uint { self.f } +} + +pub struct P<'c> { + pub g: &'c uint, +} +pub trait M { + fn n(&self) -> uint; +} +impl<'d> M for P<'d> { + fn n(&self) -> uint { *self.g } +} + +fn extension<'e>(x: &'e E<'e>) -> Box { + loop { + let p = P { g: x.m() }; + return box p as Box; + } +} + +fn main() { + let w = E { f: &10u }; + let o = extension(&w); + assert_eq!(o.n(), 10u); +}