From e02ddff816f7d599f9a4b884fca25c1380d1aae6 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 5 Oct 2015 12:31:48 -0400 Subject: [PATCH] strip out the hair trait and use concrete types instead --- src/librustc_mir/build/block.rs | 9 +- src/librustc_mir/build/cfg.rs | 28 +- src/librustc_mir/build/expr/as_constant.rs | 8 +- src/librustc_mir/build/expr/as_lvalue.rs | 10 +- src/librustc_mir/build/expr/as_operand.rs | 10 +- src/librustc_mir/build/expr/as_rvalue.rs | 10 +- src/librustc_mir/build/expr/as_temp.rs | 10 +- src/librustc_mir/build/expr/category.rs | 2 +- src/librustc_mir/build/expr/into.rs | 14 +- src/librustc_mir/build/into.rs | 48 +-- src/librustc_mir/build/matches/mod.rs | 102 +++--- src/librustc_mir/build/matches/simplify.rs | 10 +- src/librustc_mir/build/matches/test.rs | 39 +-- src/librustc_mir/build/matches/util.rs | 32 +- src/librustc_mir/build/misc.rs | 25 +- src/librustc_mir/build/mod.rs | 60 ++-- src/librustc_mir/build/scope.rs | 60 ++-- src/librustc_mir/build/stmt.rs | 6 +- src/librustc_mir/dump.rs | 6 +- src/librustc_mir/graphviz/mod.rs | 5 +- src/librustc_mir/hair.rs | 367 +++++++++------------ src/librustc_mir/lib.rs | 3 + src/librustc_mir/repr.rs | 179 +++++----- src/librustc_mir/tcx/block.rs | 24 +- src/librustc_mir/tcx/expr.rs | 44 +-- src/librustc_mir/tcx/mod.rs | 90 +++-- src/librustc_mir/tcx/pattern.rs | 34 +- src/librustc_mir/tcx/to_ref.rs | 51 ++- 28 files changed, 617 insertions(+), 669 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 5604c78e098..21a77bbd232 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -8,15 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use build::{BlockAnd, Builder}; use hair::*; use repr::*; -use build::{BlockAnd, Builder}; +use rustc_front::hir; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { pub fn ast_block(&mut self, - destination: &Lvalue, + destination: &Lvalue<'tcx>, mut block: BasicBlock, - ast_block: H::Block) + ast_block: &'tcx hir::Block) -> BlockAnd<()> { let this = self; let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block); diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 955e1b7146a..09166a76f70 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -14,15 +14,15 @@ //! Routines for manipulating the control-flow graph. use build::CFG; -use hair::*; use repr::*; +use syntax::codemap::Span; -impl CFG { - pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData { +impl<'tcx> CFG<'tcx> { + pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> { &self.basic_blocks[blk.index()] } - pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData { + pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> { &mut self.basic_blocks[blk.index()] } @@ -39,21 +39,21 @@ impl CFG { BasicBlock::new(node_index) } - pub fn push(&mut self, block: BasicBlock, statement: Statement) { + pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) { debug!("push({:?}, {:?})", block, statement); self.block_data_mut(block).statements.push(statement); } pub fn push_assign_constant(&mut self, block: BasicBlock, - span: H::Span, - temp: &Lvalue, - constant: Constant) { + span: Span, + temp: &Lvalue<'tcx>, + constant: Constant<'tcx>) { self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant))); } - pub fn push_drop(&mut self, block: BasicBlock, span: H::Span, - kind: DropKind, lvalue: &Lvalue) { + pub fn push_drop(&mut self, block: BasicBlock, span: Span, + kind: DropKind, lvalue: &Lvalue<'tcx>) { self.push(block, Statement { span: span, kind: StatementKind::Drop(kind, lvalue.clone()) @@ -62,9 +62,9 @@ impl CFG { pub fn push_assign(&mut self, block: BasicBlock, - span: H::Span, - lvalue: &Lvalue, - rvalue: Rvalue) { + span: Span, + lvalue: &Lvalue<'tcx>, + rvalue: Rvalue<'tcx>) { self.push(block, Statement { span: span, kind: StatementKind::Assign(lvalue.clone(), rvalue) @@ -73,7 +73,7 @@ impl CFG { pub fn terminate(&mut self, block: BasicBlock, - terminator: Terminator) { + terminator: Terminator<'tcx>) { // Check whether this block has already been terminated. For // this, we rely on the fact that the initial state is to have // a Diverge terminator and an empty list of targets (which diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index 6cc99a56933..d6de68b18d8 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -14,17 +14,17 @@ use build::{Builder}; use hair::*; use repr::*; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! - pub fn as_constant(&mut self, expr: M) -> Constant - where M: Mirror> + pub fn as_constant(&mut self, expr: M) -> Constant<'tcx> + where M: Mirror<'tcx, Output=Expr<'tcx>> { let expr = self.hir.mirror(expr); self.expr_as_constant(expr) } - fn expr_as_constant(&mut self, expr: Expr) -> Constant { + fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> { let this = self; let Expr { ty, temp_lifetime: _, span, kind } = expr; match kind { diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index ffbb9781bdc..c14c8649e30 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -15,13 +15,13 @@ use build::expr::category::Category; use hair::*; use repr::*; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr`, yielding an lvalue that we can move from etc. pub fn as_lvalue(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror> + -> BlockAnd> + where M: Mirror<'tcx, Output=Expr<'tcx>> { let expr = self.hir.mirror(expr); self.expr_as_lvalue(block, expr) @@ -29,8 +29,8 @@ impl Builder { fn expr_as_lvalue(&mut self, mut block: BasicBlock, - expr: Expr) - -> BlockAnd> + expr: Expr<'tcx>) + -> BlockAnd> { debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index 0b236f3a1dc..7fcbf4f5144 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -15,7 +15,7 @@ use build::expr::category::Category; use hair::*; use repr::*; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr` into a value that can be used as an operand. /// If `expr` is an lvalue like `x`, this will introduce a /// temporary `tmp = x`, so that we capture the value of `x` at @@ -23,8 +23,8 @@ impl Builder { pub fn as_operand(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror> + -> BlockAnd> + where M: Mirror<'tcx, Output=Expr<'tcx>> { let expr = self.hir.mirror(expr); self.expr_as_operand(block, expr) @@ -32,8 +32,8 @@ impl Builder { fn expr_as_operand(&mut self, mut block: BasicBlock, - expr: Expr) - -> BlockAnd> + expr: Expr<'tcx>) + -> BlockAnd> { debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 0f0303525e3..be29964f3b0 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -17,13 +17,13 @@ use build::expr::category::{Category, RvalueFunc}; use hair::*; use repr::*; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr`, yielding an rvalue. pub fn as_rvalue(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror> + -> BlockAnd> + where M: Mirror<'tcx, Output=Expr<'tcx>> { let expr = self.hir.mirror(expr); self.expr_as_rvalue(block, expr) @@ -31,8 +31,8 @@ impl Builder { fn expr_as_rvalue(&mut self, mut block: BasicBlock, - expr: Expr) - -> BlockAnd> + expr: Expr<'tcx>) + -> BlockAnd> { debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index cb652c8a594..6f2814de8d6 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -15,14 +15,14 @@ use build::expr::category::Category; use hair::*; use repr::*; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr` into a fresh temporary. This is used when building /// up rvalues so as to freeze the value that will be consumed. pub fn as_temp(&mut self, block: BasicBlock, expr: M) - -> BlockAnd> - where M: Mirror> + -> BlockAnd> + where M: Mirror<'tcx, Output=Expr<'tcx>> { let expr = self.hir.mirror(expr); self.expr_as_temp(block, expr) @@ -30,8 +30,8 @@ impl Builder { fn expr_as_temp(&mut self, mut block: BasicBlock, - expr: Expr) - -> BlockAnd> + expr: Expr<'tcx>) + -> BlockAnd> { debug!("expr_as_temp(block={:?}, expr={:?})", block, expr); diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 9cab2976b2c..658b7779b44 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -41,7 +41,7 @@ pub enum RvalueFunc { /// Determines the category for a given expression. Note that scope /// and paren expressions have no category. impl Category { - pub fn of(ek: &ExprKind) -> Option { + pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option { match *ek { ExprKind::Scope { .. } => None, diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 61eeac30c0f..a2365c8bead 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -15,14 +15,16 @@ use build::expr::category::{Category, RvalueFunc}; use build::scope::LoopScope; use hair::*; use repr::*; +use rustc::middle::region::CodeExtent; +use syntax::codemap::Span; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. pub fn into_expr(&mut self, - destination: &Lvalue, + destination: &Lvalue<'tcx>, mut block: BasicBlock, - expr: Expr) + expr: Expr<'tcx>) -> BlockAnd<()> { debug!("into_expr(destination={:?}, block={:?}, expr={:?})", @@ -266,12 +268,12 @@ impl Builder { } fn break_or_continue(&mut self, - span: H::Span, - label: Option, + span: Span, + label: Option, block: BasicBlock, exit_selector: F) -> BlockAnd<()> - where F: FnOnce(&LoopScope) -> BasicBlock + where F: FnOnce(&LoopScope) -> BasicBlock { let loop_scope = self.find_loop_scope(span, label); let exit_block = exit_selector(&loop_scope); diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs index 426e59f1c40..ac8aae9ed0a 100644 --- a/src/librustc_mir/build/into.rs +++ b/src/librustc_mir/build/into.rs @@ -18,50 +18,50 @@ use build::{BlockAnd, Builder}; use hair::*; use repr::*; -pub trait EvalInto { - fn eval_into(self, builder: &mut Builder, destination: &Lvalue, - block: BasicBlock) -> BlockAnd<()>; +pub trait EvalInto<'tcx> { + fn eval_into<'a>(self, builder: &mut Builder<'a,'tcx>, destination: &Lvalue<'tcx>, + block: BasicBlock) -> BlockAnd<()>; } -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { pub fn into(&mut self, - destination: &Lvalue, + destination: &Lvalue<'tcx>, block: BasicBlock, expr: E) -> BlockAnd<()> - where E: EvalInto + where E: EvalInto<'tcx> { expr.eval_into(self, destination, block) } } -impl EvalInto for ExprRef { - fn eval_into(self, - builder: &mut Builder, - destination: &Lvalue, - block: BasicBlock) - -> BlockAnd<()> { +impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { + fn eval_into<'a>(self, + builder: &mut Builder<'a,'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()> { let expr = builder.hir.mirror(self); builder.into_expr(destination, block, expr) } } -impl EvalInto for Expr { - fn eval_into(self, - builder: &mut Builder, - destination: &Lvalue, - block: BasicBlock) - -> BlockAnd<()> { +impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { + fn eval_into<'a>(self, + builder: &mut Builder<'a,'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()> { builder.into_expr(destination, block, self) } } -impl EvalInto for Option> { - fn eval_into(self, - builder: &mut Builder, - destination: &Lvalue, - block: BasicBlock) - -> BlockAnd<()> { +impl<'tcx> EvalInto<'tcx> for Option> { + fn eval_into<'a>(self, + builder: &mut Builder<'a,'tcx>, + destination: &Lvalue<'tcx>, + block: BasicBlock) + -> BlockAnd<()> { match self { Some(expr) => builder.into(destination, block, expr), None => block.unit() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 4d0acd5fac9..ad6a218b07c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -15,20 +15,24 @@ use build::{BlockAnd, Builder}; use repr::*; +use rustc::middle::region::CodeExtent; +use rustc::middle::ty::{AdtDef, Ty}; use hair::*; +use syntax::ast::{Name, NodeId}; +use syntax::codemap::Span; // helper functions, broken out by category: mod simplify; mod test; mod util; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { pub fn match_expr(&mut self, - destination: &Lvalue, - span: H::Span, + destination: &Lvalue<'tcx>, + span: Span, mut block: BasicBlock, - discriminant: ExprRef, - arms: Vec>) + discriminant: ExprRef<'tcx>, + arms: Vec>) -> BlockAnd<()> { let discriminant_lvalue = @@ -49,7 +53,7 @@ impl Builder { .collect(), }; - let arm_bodies: Vec> = + let arm_bodies: Vec> = arms.iter() .map(|arm| arm.body.clone()) .collect(); @@ -60,7 +64,7 @@ impl Builder { // highest priority candidate comes last in the list. This the // reverse of the order in which candidates are written in the // source. - let candidates: Vec> = + let candidates: Vec> = arms.iter() .enumerate() .rev() // highest priority comes last @@ -97,9 +101,9 @@ impl Builder { pub fn expr_into_pattern(&mut self, mut block: BasicBlock, - var_extent: H::CodeExtent, // lifetime of vars - irrefutable_pat: PatternRef, - initializer: ExprRef) + var_extent: CodeExtent, // lifetime of vars + irrefutable_pat: PatternRef<'tcx>, + initializer: ExprRef<'tcx>) -> BlockAnd<()> { // optimize the case of `let x = ...` @@ -125,16 +129,16 @@ impl Builder { pub fn lvalue_into_pattern(&mut self, mut block: BasicBlock, - var_extent: H::CodeExtent, - irrefutable_pat: PatternRef, - initializer: &Lvalue) + var_extent: CodeExtent, + irrefutable_pat: PatternRef<'tcx>, + initializer: &Lvalue<'tcx>) -> BlockAnd<()> { // first, creating the bindings self.declare_bindings(var_extent, irrefutable_pat.clone()); // create a dummy candidate - let mut candidate = Candidate:: { + let mut candidate = Candidate::<'tcx> { match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())], bindings: vec![], guard: None, @@ -159,8 +163,8 @@ impl Builder { } pub fn declare_bindings(&mut self, - var_extent: H::CodeExtent, - pattern: PatternRef) + var_extent: CodeExtent, + pattern: PatternRef<'tcx>) { let pattern = self.hir.mirror(pattern); match pattern.kind { @@ -198,69 +202,69 @@ struct ArmBlocks { } #[derive(Clone, Debug)] -struct Candidate { +struct Candidate<'tcx> { // all of these must be satisfied... - match_pairs: Vec>, + match_pairs: Vec>, // ...these bindings established... - bindings: Vec>, + bindings: Vec>, // ...and the guard must be evaluated... - guard: Option>, + guard: Option>, // ...and then we branch to arm with this index. arm_index: usize, } #[derive(Clone, Debug)] -struct Binding { - span: H::Span, - source: Lvalue, - name: H::Name, - var_id: H::VarId, - var_ty: H::Ty, +struct Binding<'tcx> { + span: Span, + source: Lvalue<'tcx>, + name: Name, + var_id: NodeId, + var_ty: Ty<'tcx>, mutability: Mutability, - binding_mode: BindingMode, + binding_mode: BindingMode, } #[derive(Clone, Debug)] -struct MatchPair { +struct MatchPair<'tcx> { // this lvalue... - lvalue: Lvalue, + lvalue: Lvalue<'tcx>, // ... must match this pattern. - pattern: Pattern, + pattern: Pattern<'tcx>, } #[derive(Clone, Debug, PartialEq)] -enum TestKind { +enum TestKind<'tcx> { // test the branches of enum - Switch { adt_def: H::AdtDef }, + Switch { adt_def: AdtDef<'tcx> }, // test for equality - Eq { value: Literal, ty: H::Ty }, + Eq { value: Literal<'tcx>, ty: Ty<'tcx> }, // test whether the value falls within an inclusive range - Range { lo: Literal, hi: Literal, ty: H::Ty }, + Range { lo: Literal<'tcx>, hi: Literal<'tcx>, ty: Ty<'tcx> }, // test length of the slice is equal to len Len { len: usize, op: BinOp }, } #[derive(Debug)] -struct Test { - span: H::Span, - kind: TestKind, +struct Test<'tcx> { + span: Span, + kind: TestKind<'tcx>, } /////////////////////////////////////////////////////////////////////////// // Main matching algorithm -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { fn match_candidates(&mut self, - span: H::Span, + span: Span, arm_blocks: &mut ArmBlocks, - mut candidates: Vec>, + mut candidates: Vec>, mut block: BasicBlock) { debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})", @@ -306,7 +310,7 @@ impl Builder { let target_blocks = self.perform_test(block, &match_pair.lvalue, &test); for (outcome, mut target_block) in target_blocks.into_iter().enumerate() { - let applicable_candidates: Vec> = + let applicable_candidates: Vec> = candidates.iter() .filter_map(|candidate| { unpack!(target_block = @@ -336,7 +340,7 @@ impl Builder { fn bind_and_guard_matched_candidate(&mut self, mut block: BasicBlock, arm_blocks: &mut ArmBlocks, - candidate: Candidate) + candidate: Candidate<'tcx>) -> Option { debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", block, candidate); @@ -363,7 +367,7 @@ impl Builder { fn bind_matched_candidate(&mut self, block: BasicBlock, - bindings: Vec>) { + bindings: Vec>) { debug!("bind_matched_candidate(block={:?}, bindings={:?})", block, bindings); @@ -386,19 +390,19 @@ impl Builder { } fn declare_binding(&mut self, - var_extent: H::CodeExtent, + var_extent: CodeExtent, mutability: Mutability, - name: H::Name, - var_id: H::VarId, - var_ty: H::Ty, - span: H::Span) + name: Name, + var_id: NodeId, + var_ty: Ty<'tcx>, + span: Span) -> u32 { debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_extent={:?}, span={:?})", var_id, name, var_ty, var_extent, span); let index = self.var_decls.len(); - self.var_decls.push(VarDecl:: { + self.var_decls.push(VarDecl::<'tcx> { mutability: mutability, name: name, ty: var_ty.clone(), diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index f15b2ed5d4e..9114463d61d 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -29,10 +29,10 @@ use repr::*; use std::mem; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { pub fn simplify_candidate(&mut self, mut block: BasicBlock, - candidate: &mut Candidate) + candidate: &mut Candidate<'tcx>) -> BlockAnd<()> { // repeatedly simplify match pairs until fixed point is reached @@ -60,9 +60,9 @@ impl Builder { /// returned), no changes are made to candidate. fn simplify_match_pair(&mut self, mut block: BasicBlock, - match_pair: MatchPair, - candidate: &mut Candidate) - -> Result> // returns Err() if cannot simplify + match_pair: MatchPair<'tcx>, + candidate: &mut Candidate<'tcx>) + -> Result> // returns Err() if cannot simplify { match match_pair.pattern.kind { PatternKind::Wild(..) => { diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 2d034baef16..a7ef97e12a0 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -19,12 +19,13 @@ use build::{BlockAnd, Builder}; use build::matches::{Candidate, MatchPair, Test, TestKind}; use hair::*; use repr::*; +use syntax::codemap::Span; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Identifies what test is needed to decide if `match_pair` is applicable. /// /// It is a bug to call this with a simplifyable pattern. - pub fn test(&mut self, match_pair: &MatchPair) -> Test { + pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> { match match_pair.pattern.kind { PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => { Test { @@ -72,8 +73,8 @@ impl Builder { /// Generates the code to perform a test. pub fn perform_test(&mut self, block: BasicBlock, - lvalue: &Lvalue, - test: &Test) + lvalue: &Lvalue<'tcx>, + test: &Test<'tcx>) -> Vec { match test.kind.clone() { TestKind::Switch { adt_def } => { @@ -149,10 +150,10 @@ impl Builder { fn call_comparison_fn(&mut self, block: BasicBlock, - span: H::Span, - item_ref: ItemRef, - lvalue1: Lvalue, - lvalue2: Lvalue) + span: Span, + item_ref: ItemRef<'tcx>, + lvalue1: Lvalue<'tcx>, + lvalue2: Lvalue<'tcx>) -> Vec { let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()]; @@ -194,11 +195,11 @@ impl Builder { /// @ 22])`. pub fn candidate_under_assumption(&mut self, mut block: BasicBlock, - test_lvalue: &Lvalue, - test_kind: &TestKind, + test_lvalue: &Lvalue<'tcx>, + test_kind: &TestKind<'tcx>, test_outcome: usize, - candidate: &Candidate) - -> BlockAnd>> { + candidate: &Candidate<'tcx>) + -> BlockAnd>> { let candidate = candidate.clone(); let match_pairs = candidate.match_pairs; let result = unpack!(block = self.match_pairs_under_assumption(block, @@ -216,11 +217,11 @@ impl Builder { /// work of transforming the list of match pairs. fn match_pairs_under_assumption(&mut self, mut block: BasicBlock, - test_lvalue: &Lvalue, - test_kind: &TestKind, + test_lvalue: &Lvalue<'tcx>, + test_kind: &TestKind<'tcx>, test_outcome: usize, - match_pairs: Vec>) - -> BlockAnd>>> { + match_pairs: Vec>) + -> BlockAnd>>> { let mut result = vec![]; for match_pair in match_pairs { @@ -279,9 +280,9 @@ impl Builder { /// It is a bug to call this with a simplifyable pattern. pub fn consequent_match_pairs_under_assumption(&mut self, mut block: BasicBlock, - match_pair: MatchPair, + match_pair: MatchPair<'tcx>, test_outcome: usize) - -> BlockAnd>>> { + -> BlockAnd>>> { match match_pair.pattern.kind { PatternKind::Variant { adt_def, variant_index, subpatterns } => { if test_outcome != variant_index { @@ -339,7 +340,7 @@ impl Builder { } } - fn error_simplifyable(&mut self, match_pair: &MatchPair) -> ! { + fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! { self.hir.span_bug( match_pair.pattern.span, &format!("simplifyable pattern found: {:?}", match_pair.pattern)) diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index 65a08868666..d6cc1d088f9 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -14,11 +14,11 @@ use hair::*; use repr::*; use std::u32; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { pub fn field_match_pairs(&mut self, - lvalue: Lvalue, - subpatterns: Vec>) - -> Vec> { + lvalue: Lvalue<'tcx>, + subpatterns: Vec>) + -> Vec> { subpatterns.into_iter() .map(|fieldpat| { let lvalue = lvalue.clone().field(fieldpat.field); @@ -27,7 +27,7 @@ impl Builder { .collect() } - pub fn match_pair(&mut self, lvalue: Lvalue, pattern: PatternRef) -> MatchPair { + pub fn match_pair(&mut self, lvalue: Lvalue<'tcx>, pattern: PatternRef<'tcx>) -> MatchPair<'tcx> { let pattern = self.hir.mirror(pattern); MatchPair::new(lvalue, pattern) } @@ -47,12 +47,12 @@ impl Builder { /// /// and creates a match pair `tmp0 @ s` pub fn prefix_suffix_slice(&mut self, - match_pairs: &mut Vec>, + match_pairs: &mut Vec>, block: BasicBlock, - lvalue: Lvalue, - prefix: Vec>, - opt_slice: Option>, - suffix: Vec>) + lvalue: Lvalue<'tcx>, + prefix: Vec>, + opt_slice: Option>, + suffix: Vec>) -> BlockAnd<()> { // If there is a `..P` pattern, create a temporary `t0` for @@ -76,10 +76,10 @@ impl Builder { /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix. fn prefix_suffix(&mut self, - match_pairs: &mut Vec>, - lvalue: Lvalue, - prefix: Vec>, - suffix: Vec>) + match_pairs: &mut Vec>, + lvalue: Lvalue<'tcx>, + prefix: Vec>, + suffix: Vec>) { let min_length = prefix.len() + suffix.len(); assert!(min_length < u32::MAX as usize); @@ -118,8 +118,8 @@ impl Builder { } } -impl MatchPair { - pub fn new(lvalue: Lvalue, pattern: Pattern) -> MatchPair { +impl<'tcx> MatchPair<'tcx> { + pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> { MatchPair { lvalue: lvalue, pattern: pattern } } } diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 9fa1d55e82f..8ebe0bc7154 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -14,16 +14,17 @@ use build::Builder; use hair::*; use repr::*; - +use rustc::middle::ty::Ty; use std::u32; +use syntax::codemap::Span; -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Add a new temporary value of type `ty` storing the result of /// evaluating `expr`. /// /// NB: **No cleanup is scheduled for this temporary.** You should /// call `schedule_drop` once the temporary is initialized. - pub fn temp(&mut self, ty: H::Ty) -> Lvalue { + pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> { let index = self.temp_decls.len(); self.temp_decls.push(TempDecl { ty: ty }); assert!(index < (u32::MAX) as usize); @@ -35,10 +36,10 @@ impl Builder { pub fn push_literal(&mut self, block: BasicBlock, - span: H::Span, - ty: H::Ty, - literal: Literal) - -> Lvalue { + span: Span, + ty: Ty<'tcx>, + literal: Literal<'tcx>) + -> Lvalue<'tcx> { let temp = self.temp(ty.clone()); let constant = Constant { span: span, ty: ty, literal: literal }; self.cfg.push_assign_constant(block, span, &temp, constant); @@ -47,9 +48,9 @@ impl Builder { pub fn push_usize(&mut self, block: BasicBlock, - span: H::Span, + span: Span, value: usize) - -> Lvalue { + -> Lvalue<'tcx> { let usize_ty = self.hir.usize_ty(); let temp = self.temp(usize_ty); self.cfg.push_assign_constant( @@ -64,9 +65,9 @@ impl Builder { pub fn push_item_ref(&mut self, block: BasicBlock, - span: H::Span, - item_ref: ItemRef) - -> Lvalue { + span: Span, + item_ref: ItemRef<'tcx>) + -> Lvalue<'tcx> { let literal = Literal::Item { def_id: item_ref.def_id, substs: item_ref.substs }; self.push_literal(block, span, item_ref.ty, literal) } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9d00044c660..cf4dc9227c4 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -8,24 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hair::{self, Hair}; +use hair; +use rustc::middle::region::CodeExtent; +use rustc::middle::ty::Ty; use rustc_data_structures::fnv::FnvHashMap; +use rustc_front::hir; use repr::*; +use syntax::ast; +use syntax::codemap::Span; +use tcx::{Cx, PatNode}; -struct Builder { - hir: H, - extents: FnvHashMap>, - cfg: CFG, - scopes: Vec>, - loop_scopes: Vec>, - unit_temp: Lvalue, - var_decls: Vec>, - var_indices: FnvHashMap, - temp_decls: Vec>, +struct Builder<'a,'tcx:'a> { + hir: Cx<'a, 'tcx>, + extents: FnvHashMap>, + cfg: CFG<'tcx>, + scopes: Vec>, + loop_scopes: Vec, + unit_temp: Lvalue<'tcx>, + var_decls: Vec>, + var_indices: FnvHashMap, + temp_decls: Vec>, } -struct CFG { - basic_blocks: Vec> +struct CFG<'tcx> { + basic_blocks: Vec> } /////////////////////////////////////////////////////////////////////////// @@ -69,18 +75,18 @@ macro_rules! unpack { /////////////////////////////////////////////////////////////////////////// // construct() -- the main entry point for building MIR for a function -pub fn construct(mut hir: H, - _span: H::Span, - implicit_arguments: Vec, - explicit_arguments: Vec<(H::Ty, H::Pattern)>, - argument_extent: H::CodeExtent, - ast_block: H::Block) - -> Mir { +pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>, + _span: Span, + implicit_arguments: Vec>, + explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, + argument_extent: CodeExtent, + ast_block: &'tcx hir::Block) + -> Mir<'tcx> { let cfg = CFG { basic_blocks: vec![] }; // it's handy to have a temporary of type `()` sometimes, so make // one from the start and keep it available - let temp_decls = vec![TempDecl:: { ty: hir.unit_ty() }]; + let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }]; let unit_temp = Lvalue::Temp(0); let mut builder = Builder { @@ -118,14 +124,14 @@ pub fn construct(mut hir: H, } } -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { fn args_and_body(&mut self, mut block: BasicBlock, - implicit_arguments: Vec, - explicit_arguments: Vec<(H::Ty, H::Pattern)>, - argument_extent: H::CodeExtent, - ast_block: H::Block) - -> BlockAnd>> + implicit_arguments: Vec>, + explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>, + argument_extent: CodeExtent, + ast_block: &'tcx hir::Block) + -> BlockAnd>> { self.in_scope(argument_extent, block, |this| { let arg_decls = { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 87a4731ac74..4b76bc737fd 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -12,7 +12,7 @@ Managing the scope stack. The scopes are tied to lexical scopes, so as we descend the HAIR, we push a scope on the stack, translate ite contents, and then pop it off. Every scope is named by a -`H::CodeExtent`. +`CodeExtent`. ### SEME Regions @@ -23,7 +23,7 @@ via a `break` or `return` or just by fallthrough, that marks an exit from the scope. Each lexical scope thus corresponds to a single-entry, multiple-exit (SEME) region in the control-flow graph. -For now, we keep a mapping from each `H::CodeExtent` to its +For now, we keep a mapping from each `CodeExtent` to its corresponding SEME region for later reference (see caveat in next paragraph). This is because region scopes are tied to them. Eventually, when we shift to non-lexical lifetimes, three should @@ -87,24 +87,26 @@ should go to. */ use build::{BlockAnd, Builder, CFG}; -use hair::Hair; use repr::*; +use rustc::middle::region::CodeExtent; +use rustc::middle::ty::Ty; +use syntax::codemap::Span; -pub struct Scope { - extent: H::CodeExtent, +pub struct Scope<'tcx> { + extent: CodeExtent, exits: Vec, - drops: Vec<(DropKind, H::Span, Lvalue)>, + drops: Vec<(DropKind, Span, Lvalue<'tcx>)>, cached_block: Option, } #[derive(Clone, Debug)] -pub struct LoopScope { - pub extent: H::CodeExtent, // extent of the loop +pub struct LoopScope { + pub extent: CodeExtent, // extent of the loop pub continue_block: BasicBlock, // where to go on a `loop` pub break_block: BasicBlock, // where to go on a `break } -impl Builder { +impl<'a,'tcx> Builder<'a,'tcx> { /// Start a loop scope, which tracks where `continue` and `break` /// should branch to. See module comment for more details. pub fn in_loop_scope(&mut self, @@ -112,12 +114,12 @@ impl Builder { break_block: BasicBlock, f: F) -> BlockAnd - where F: FnOnce(&mut Builder) -> BlockAnd + where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd { let extent = self.extent_of_innermost_scope().unwrap(); - let loop_scope = LoopScope:: { extent: extent.clone(), - continue_block: loop_block, - break_block: break_block }; + let loop_scope = LoopScope { extent: extent.clone(), + continue_block: loop_block, + break_block: break_block }; self.loop_scopes.push(loop_scope); let r = f(self); assert!(self.loop_scopes.pop().unwrap().extent == extent); @@ -127,11 +129,11 @@ impl Builder { /// Start a scope. The closure `f` should translate the contents /// of the scope. See module comment for more details. pub fn in_scope(&mut self, - extent: H::CodeExtent, + extent: CodeExtent, block: BasicBlock, f: F) -> BlockAnd - where F: FnOnce(&mut Builder) -> BlockAnd + where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd { debug!("in_scope(extent={:?}, block={:?})", extent, block); @@ -180,9 +182,9 @@ impl Builder { /// Finds the loop scope for a given label. This is used for /// resolving `break` and `continue`. pub fn find_loop_scope(&mut self, - span: H::Span, - label: Option) - -> LoopScope { + span: Span, + label: Option) + -> LoopScope { let loop_scope = match label { None => { @@ -211,8 +213,8 @@ impl Builder { /// needed, as well as tracking this exit for the SEME region. See /// module comment for details. pub fn exit_scope(&mut self, - span: H::Span, - extent: H::CodeExtent, + span: Span, + extent: CodeExtent, block: BasicBlock, target: BasicBlock) { let popped_scopes = @@ -249,11 +251,11 @@ impl Builder { /// Indicates that `lvalue` should be dropped on exit from /// `extent`. pub fn schedule_drop(&mut self, - span: H::Span, - extent: H::CodeExtent, + span: Span, + extent: CodeExtent, kind: DropKind, - lvalue: &Lvalue, - lvalue_ty: H::Ty) + lvalue: &Lvalue<'tcx>, + lvalue_ty: Ty<'tcx>) { if self.hir.needs_drop(lvalue_ty, span) { match self.scopes.iter_mut().rev().find(|s| s.extent == extent) { @@ -267,18 +269,18 @@ impl Builder { } } - pub fn extent_of_innermost_scope(&self) -> Option { + pub fn extent_of_innermost_scope(&self) -> Option { self.scopes.last().map(|scope| scope.extent) } - pub fn extent_of_outermost_scope(&self) -> Option { + pub fn extent_of_outermost_scope(&self) -> Option { self.scopes.first().map(|scope| scope.extent) } } -fn diverge_cleanup_helper(cfg: &mut CFG, - scopes: &mut [Scope]) - -> BasicBlock { +fn diverge_cleanup_helper<'tcx>(cfg: &mut CFG<'tcx>, + scopes: &mut [Scope<'tcx>]) + -> BasicBlock { let len = scopes.len(); if len == 0 { diff --git a/src/librustc_mir/build/stmt.rs b/src/librustc_mir/build/stmt.rs index 3dd4f5f253c..01fda2498f7 100644 --- a/src/librustc_mir/build/stmt.rs +++ b/src/librustc_mir/build/stmt.rs @@ -12,15 +12,15 @@ use build::{BlockAnd, Builder}; use hair::*; use repr::*; -impl Builder { - pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec>) -> BlockAnd<()> { +impl<'a,'tcx> Builder<'a,'tcx> { + pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec>) -> BlockAnd<()> { for stmt in stmts { unpack!(block = self.stmt(block, stmt)); } block.unit() } - pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef) -> BlockAnd<()> { + pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef<'tcx>) -> BlockAnd<()> { let this = self; let Stmt { span, kind } = this.hir.mirror(stmt); match kind { diff --git a/src/librustc_mir/dump.rs b/src/librustc_mir/dump.rs index 4251b550cfc..5e68e5cc995 100644 --- a/src/librustc_mir/dump.rs +++ b/src/librustc_mir/dump.rs @@ -169,18 +169,18 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>, span: Span, decl: &'tcx hir::FnDecl, body: &'tcx hir::Block) - -> Result>, ErrorReported> { + -> Result, ErrorReported> { let arguments = decl.inputs .iter() .map(|arg| { - let ty = cx.tcx.node_id_to_type(arg.id); + let ty = cx.tcx().node_id_to_type(arg.id); (ty, PatNode::irrefutable(&arg.pat)) }) .collect(); let parameter_scope = - cx.tcx.region_maps.lookup_code_extent( + cx.tcx().region_maps.lookup_code_extent( CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id }); Ok(build::construct(cx, span, diff --git a/src/librustc_mir/graphviz/mod.rs b/src/librustc_mir/graphviz/mod.rs index 01ccf20ae06..0acf59bf357 100644 --- a/src/librustc_mir/graphviz/mod.rs +++ b/src/librustc_mir/graphviz/mod.rs @@ -9,7 +9,6 @@ // except according to those terms. use dot; -use hair::Hair; use repr::*; use std::borrow::IntoCow; @@ -20,7 +19,7 @@ pub struct EdgeIndex { index: usize, } -impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir { +impl<'a,'tcx> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<'tcx> { fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("Mir").unwrap() } @@ -62,7 +61,7 @@ impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir { } } -impl<'a,H:Hair> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir { +impl<'a,'tcx> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<'tcx> { fn nodes(&'a self) -> dot::Nodes<'a, BasicBlock> { self.all_basic_blocks().into_cow() } diff --git a/src/librustc_mir/hair.rs b/src/librustc_mir/hair.rs index 18f2dd6dc6e..ed776717d37 100644 --- a/src/librustc_mir/hair.rs +++ b/src/librustc_mir/hair.rs @@ -15,144 +15,78 @@ //! structures. use repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp}; -use std::fmt::Debug; -use std::hash::Hash; +use rustc::middle::def_id::DefId; +use rustc::middle::region::CodeExtent; +use rustc::middle::subst::Substs; +use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty}; +use rustc_front::hir; +use syntax::ast; +use syntax::codemap::Span; +use tcx::{Cx, PatNode}; -pub trait Hair: Sized+Debug+Clone+Eq+Hash { // (*) - - // (*) the `Sized` and Debug` bounds are the only ones that really - // make sense. The rest are just there so that we can - // `#[derive(Clone)]` on things that are parameterized over - // `H:HAIR`. It's kind of lame. - - type VarId: Copy+Debug+Eq+Hash; // e.g., NodeId for a variable - type DefId: Copy+Debug+Eq+Hash; // e.g., DefId - type AdtDef: Copy+Debug+Eq+Hash; // e.g., AdtDef<'tcx> - type Name: Copy+Debug+Eq+Hash; // e.g., ast::Name - type InternedString: Clone+Debug+Eq+Hash; // e.g., InternedString - type Bytes: Clone+Debug+Eq+Hash; // e.g., Rc> - type Span: Copy+Debug+Eq; // e.g., syntax::codemap::Span - type Projection: Clone+Debug+Eq; // e.g., ty::ProjectionTy<'tcx> - type Substs: Clone+Debug+Eq; // e.g., substs::Substs<'tcx> - type ClosureSubsts: Clone+Debug+Eq; // e.g., ty::ClosureSubsts<'tcx> - type Ty: Clone+Debug+Eq; // e.g., ty::Ty<'tcx> - type Region: Copy+Debug; // e.g., ty::Region - type CodeExtent: Copy+Debug+Hash+Eq; // e.g., region::CodeExtent - type ConstVal: Clone+Debug+PartialEq; // e.g., ConstVal - type Pattern: Clone+Debug+Mirror>; // e.g., &P - type Expr: Clone+Debug+Mirror>; // e.g., &P - type Stmt: Clone+Debug+Mirror>; // e.g., &P - type Block: Clone+Debug+Mirror>; // e.g., &P - type InlineAsm: Clone+Debug+Eq+Hash; // e.g., ast::InlineAsm - - /// Normalizes `ast` into the appropriate `mirror` type. - fn mirror>(&mut self, ast: M) -> M::Output { - ast.make_mirror(self) - } - - /// Returns the unit type `()` - fn unit_ty(&mut self) -> Self::Ty; - - /// Returns the type `usize`. - fn usize_ty(&mut self) -> Self::Ty; - - /// Returns the literal for `value` as a `usize`. - fn usize_literal(&mut self, value: usize) -> Literal; - - /// Returns the type `bool`. - fn bool_ty(&mut self) -> Self::Ty; - - /// Returns the literal for `true` - fn true_literal(&mut self) -> Literal; - - /// Returns the literal for `false` - fn false_literal(&mut self) -> Literal; - - /// Returns a reference to `PartialEq::::eq` - fn partial_eq(&mut self, ty: Self::Ty) -> ItemRef; - - /// Returns a reference to `PartialOrd::::le` - fn partial_le(&mut self, ty: Self::Ty) -> ItemRef; - - /// Returns the number of variants for the given enum - fn num_variants(&mut self, adt: Self::AdtDef) -> usize; - - fn fields(&mut self, adt: Self::AdtDef, variant_index: usize) -> Vec>; - - /// true if a value of type `ty` (may) need to be dropped; this - /// may return false even for non-Copy types if there is no - /// destructor to execute. If correct result is not known, may be - /// approximated by returning `true`; this will result in more - /// drops but not incorrect code. - fn needs_drop(&mut self, ty: Self::Ty, span: Self::Span) -> bool; - - /// Report an internal inconsistency. - fn span_bug(&mut self, span: Self::Span, message: &str) -> !; +#[derive(Clone, Debug)] +pub struct ItemRef<'tcx> { + pub ty: Ty<'tcx>, + pub def_id: DefId, + pub substs: &'tcx Substs<'tcx>, } #[derive(Clone, Debug)] -pub struct ItemRef { - pub ty: H::Ty, - pub def_id: H::DefId, - pub substs: H::Substs, +pub struct Block<'tcx> { + pub extent: CodeExtent, + pub span: Span, + pub stmts: Vec>, + pub expr: Option>, } #[derive(Clone, Debug)] -pub struct Block { - pub extent: H::CodeExtent, - pub span: H::Span, - pub stmts: Vec>, - pub expr: Option>, +pub enum StmtRef<'tcx> { + Hair(&'tcx hir::Stmt), + Mirror(Box>), } #[derive(Clone, Debug)] -pub enum StmtRef { - Hair(H::Stmt), - Mirror(Box>), +pub struct Stmt<'tcx> { + pub span: Span, + pub kind: StmtKind<'tcx>, } #[derive(Clone, Debug)] -pub struct Stmt { - pub span: H::Span, - pub kind: StmtKind, -} - -#[derive(Clone, Debug)] -pub enum StmtKind { +pub enum StmtKind<'tcx> { Expr { /// scope for this statement; may be used as lifetime of temporaries - scope: H::CodeExtent, + scope: CodeExtent, /// expression being evaluated in this statement - expr: ExprRef + expr: ExprRef<'tcx> }, Let { /// scope for variables bound in this let; covers this and /// remaining statements in block - remainder_scope: H::CodeExtent, + remainder_scope: CodeExtent, /// scope for the initialization itself; might be used as /// lifetime of temporaries - init_scope: H::CodeExtent, + init_scope: CodeExtent, /// let = ... - pattern: PatternRef, + pattern: PatternRef<'tcx>, /// let pat = ... - initializer: Option>, + initializer: Option>, /// let pat = init; - stmts: Vec> + stmts: Vec> }, } -// The Hair trait implementor translates their expressions (`H::Expr`) +// The Hair trait implementor translates their expressions (`&'tcx H::Expr`) // into instances of this `Expr` enum. This translation can be done // basically as lazilly or as eagerly as desired: every recursive -// reference to an expression in this enum is an `ExprRef`, which +// reference to an expression in this enum is an `ExprRef<'tcx>`, which // may in turn be another instance of this enum (boxed), or else an -// untranslated `H::Expr`. Note that instances of `Expr` are very +// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very // shortlived. They are created by `Hair::to_expr`, analyzed and // converted into MIR, and then discarded. // @@ -162,87 +96,88 @@ pub enum StmtKind { // example, method calls and overloaded operators are absent: they are // expected to be converted into `Expr::Call` instances. #[derive(Clone, Debug)] -pub struct Expr { +pub struct Expr<'tcx> { // type of this expression - pub ty: H::Ty, + pub ty: Ty<'tcx>, // lifetime of this expression if it should be spilled into a // temporary; should be None only if in a constant context - pub temp_lifetime: Option, + pub temp_lifetime: Option, // span of the expression in the source - pub span: H::Span, + pub span: Span, // kind of expression - pub kind: ExprKind, + pub kind: ExprKind<'tcx>, } #[derive(Clone, Debug)] -pub enum ExprKind { - Scope { extent: H::CodeExtent, value: ExprRef }, - Box { value: ExprRef }, - Call { fun: ExprRef, args: Vec> }, - Deref { arg: ExprRef }, // NOT overloaded! - Binary { op: BinOp, lhs: ExprRef, rhs: ExprRef }, // NOT overloaded! - LogicalOp { op: LogicalOp, lhs: ExprRef, rhs: ExprRef }, - Unary { op: UnOp, arg: ExprRef }, // NOT overloaded! - Cast { source: ExprRef }, - ReifyFnPointer { source: ExprRef }, - UnsafeFnPointer { source: ExprRef }, - Unsize { source: ExprRef }, - If { condition: ExprRef, then: ExprRef, otherwise: Option> }, - Loop { condition: Option>, body: ExprRef, }, - Match { discriminant: ExprRef, arms: Vec> }, - Block { body: H::Block }, - Assign { lhs: ExprRef, rhs: ExprRef }, - AssignOp { op: BinOp, lhs: ExprRef, rhs: ExprRef }, - Field { lhs: ExprRef, name: Field }, - Index { lhs: ExprRef, index: ExprRef }, - VarRef { id: H::VarId }, +pub enum ExprKind<'tcx> { + Scope { extent: CodeExtent, value: ExprRef<'tcx> }, + Box { value: ExprRef<'tcx> }, + Call { fun: ExprRef<'tcx>, args: Vec> }, + Deref { arg: ExprRef<'tcx> }, // NOT overloaded! + Binary { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, // NOT overloaded! + LogicalOp { op: LogicalOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, + Unary { op: UnOp, arg: ExprRef<'tcx> }, // NOT overloaded! + Cast { source: ExprRef<'tcx> }, + ReifyFnPointer { source: ExprRef<'tcx> }, + UnsafeFnPointer { source: ExprRef<'tcx> }, + Unsize { source: ExprRef<'tcx> }, + If { condition: ExprRef<'tcx>, then: ExprRef<'tcx>, otherwise: Option> }, + Loop { condition: Option>, body: ExprRef<'tcx>, }, + Match { discriminant: ExprRef<'tcx>, arms: Vec> }, + Block { body: &'tcx hir::Block }, + Assign { lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, + AssignOp { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, + Field { lhs: ExprRef<'tcx>, name: Field }, + Index { lhs: ExprRef<'tcx>, index: ExprRef<'tcx> }, + VarRef { id: ast::NodeId }, SelfRef, // first argument, used for self in a closure - StaticRef { id: H::DefId }, - Borrow { region: H::Region, borrow_kind: BorrowKind, arg: ExprRef }, - Break { label: Option }, - Continue { label: Option }, - Return { value: Option> }, - Repeat { value: ExprRef, count: ExprRef }, - Vec { fields: Vec> }, - Tuple { fields: Vec> }, - Adt { adt_def: H::AdtDef, + StaticRef { id: DefId }, + Borrow { region: Region, borrow_kind: BorrowKind, arg: ExprRef<'tcx> }, + Break { label: Option }, + Continue { label: Option }, + Return { value: Option> }, + Repeat { value: ExprRef<'tcx>, count: ExprRef<'tcx> }, + Vec { fields: Vec> }, + Tuple { fields: Vec> }, + Adt { adt_def: AdtDef<'tcx>, variant_index: usize, - substs: H::Substs, - fields: Vec>, - base: Option> }, - Closure { closure_id: H::DefId, substs: H::ClosureSubsts, - upvars: Vec> }, - Literal { literal: Literal }, - InlineAsm { asm: H::InlineAsm }, + substs: &'tcx Substs<'tcx>, + fields: Vec>, + base: Option> }, + Closure { closure_id: DefId, + substs: &'tcx ClosureSubsts<'tcx>, + upvars: Vec> }, + Literal { literal: Literal<'tcx> }, + InlineAsm { asm: &'tcx hir::InlineAsm }, } #[derive(Clone, Debug)] -pub enum ExprRef { - Hair(H::Expr), - Mirror(Box>), +pub enum ExprRef<'tcx> { + Hair(&'tcx hir::Expr), + Mirror(Box>), } #[derive(Clone, Debug)] -pub struct FieldExprRef { - pub name: Field, - pub expr: ExprRef, +pub struct FieldExprRef<'tcx> { + pub name: Field, + pub expr: ExprRef<'tcx>, } #[derive(Clone, Debug)] -pub struct Arm { - pub patterns: Vec>, - pub guard: Option>, - pub body: ExprRef, +pub struct Arm<'tcx> { + pub patterns: Vec>, + pub guard: Option>, + pub body: ExprRef<'tcx>, } #[derive(Clone, Debug)] -pub struct Pattern { - pub ty: H::Ty, - pub span: H::Span, - pub kind: PatternKind, +pub struct Pattern<'tcx> { + pub ty: Ty<'tcx>, + pub span: Span, + pub kind: PatternKind<'tcx>, } #[derive(Copy, Clone, Debug)] @@ -252,89 +187,91 @@ pub enum LogicalOp { } #[derive(Clone, Debug)] -pub enum PatternKind { +pub enum PatternKind<'tcx> { Wild, // x, ref x, x @ P, etc Binding { mutability: Mutability, - name: H::Name, - mode: BindingMode, - var: H::VarId, - ty: H::Ty, - subpattern: Option> }, + name: ast::Name, + mode: BindingMode, + var: ast::NodeId, + ty: Ty<'tcx>, + subpattern: Option> }, // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants - Variant { adt_def: H::AdtDef, variant_index: usize, subpatterns: Vec> }, + Variant { adt_def: AdtDef<'tcx>, variant_index: usize, subpatterns: Vec> }, // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant - Leaf { subpatterns: Vec> }, + Leaf { subpatterns: Vec> }, - Deref { subpattern: PatternRef }, // box P, &P, &mut P, etc + Deref { subpattern: PatternRef<'tcx> }, // box P, &P, &mut P, etc - Constant { value: Literal }, + Constant { value: Literal<'tcx> }, - Range { lo: Literal, hi: Literal }, + Range { lo: Literal<'tcx>, hi: Literal<'tcx> }, // matches against a slice, checking the length and extracting elements - Slice { prefix: Vec>, - slice: Option>, - suffix: Vec> }, + Slice { prefix: Vec>, + slice: Option>, + suffix: Vec> }, // fixed match against an array, irrefutable - Array { prefix: Vec>, - slice: Option>, - suffix: Vec> }, + Array { prefix: Vec>, + slice: Option>, + suffix: Vec> }, } #[derive(Copy, Clone, Debug)] -pub enum BindingMode { +pub enum BindingMode { ByValue, - ByRef(H::Region, BorrowKind), + ByRef(Region, BorrowKind), } #[derive(Clone, Debug)] -pub enum PatternRef { - Hair(H::Pattern), - Mirror(Box>), +pub enum PatternRef<'tcx> { + Hair(PatNode<'tcx>), + Mirror(Box>), } #[derive(Clone, Debug)] -pub struct FieldPatternRef { - pub field: Field, - pub pattern: PatternRef, +pub struct FieldPatternRef<'tcx> { + pub field: Field, + pub pattern: PatternRef<'tcx>, } /////////////////////////////////////////////////////////////////////////// // The Mirror trait -/// "Mirroring" is the process of converting from a Hair type into one -/// of the types in this file. For example, the mirror of a `H::Expr` -/// is an `Expr`. Mirroring is the point at which the actual IR is -/// converting into the more idealized representation described in -/// this file. Mirroring is gradual: when you mirror an outer -/// expression like `e1 + e2`, the references to the inner expressions -/// `e1` and `e2` are `ExprRef` instances, and they may or may not -/// be eagerly mirrored. This allows a single AST node from the -/// compiler to expand into one or more Hair nodes, which lets the Hair -/// nodes be simpler. -pub trait Mirror { +/// "Mirroring" is the process of converting from a HIR type into one +/// of the HAIR types defined in this file. This is basically a "on +/// the fly" desugaring step that hides a lot of the messiness in the +/// tcx. For example, the mirror of a `&'tcx hir::Expr` is an +/// `Expr<'tcx>`. +/// +/// Mirroring is gradual: when you mirror an outer expression like `e1 +/// + e2`, the references to the inner expressions `e1` and `e2` are +/// `ExprRef<'tcx>` instances, and they may or may not be eagerly +/// mirrored. This allows a single AST node from the compiler to +/// expand into one or more Hair nodes, which lets the Hair nodes be +/// simpler. +pub trait Mirror<'tcx> { type Output; - fn make_mirror(self, hir: &mut H) -> Self::Output; + fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Self::Output; } -impl Mirror for Expr { - type Output = Expr; +impl<'tcx> Mirror<'tcx> for Expr<'tcx> { + type Output = Expr<'tcx>; - fn make_mirror(self, _: &mut H) -> Expr { + fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Expr<'tcx> { self } } -impl Mirror for ExprRef { - type Output = Expr; +impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> { + type Output = Expr<'tcx>; - fn make_mirror(self, hir: &mut H) -> Expr { + fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Expr<'tcx> { match self { ExprRef::Hair(h) => h.make_mirror(hir), ExprRef::Mirror(m) => *m, @@ -342,18 +279,18 @@ impl Mirror for ExprRef { } } -impl Mirror for Stmt { - type Output = Stmt; +impl<'tcx> Mirror<'tcx> for Stmt<'tcx> { + type Output = Stmt<'tcx>; - fn make_mirror(self, _: &mut H) -> Stmt { + fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> { self } } -impl Mirror for StmtRef { - type Output = Stmt; +impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { + type Output = Stmt<'tcx>; - fn make_mirror(self, hir: &mut H) -> Stmt { + fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Stmt<'tcx> { match self { StmtRef::Hair(h) => h.make_mirror(hir), StmtRef::Mirror(m) => *m, @@ -361,18 +298,18 @@ impl Mirror for StmtRef { } } -impl Mirror for Pattern { - type Output = Pattern; +impl<'tcx> Mirror<'tcx> for Pattern<'tcx> { + type Output = Pattern<'tcx>; - fn make_mirror(self, _: &mut H) -> Pattern { + fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Pattern<'tcx> { self } } -impl Mirror for PatternRef { - type Output = Pattern; +impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> { + type Output = Pattern<'tcx>; - fn make_mirror(self, hir: &mut H) -> Pattern { + fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Pattern<'tcx> { match self { PatternRef::Hair(h) => h.make_mirror(hir), PatternRef::Mirror(m) => *m, @@ -380,10 +317,10 @@ impl Mirror for PatternRef { } } -impl Mirror for Block { - type Output = Block; +impl<'tcx> Mirror<'tcx> for Block<'tcx> { + type Output = Block<'tcx>; - fn make_mirror(self, _: &mut H) -> Block { + fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Block<'tcx> { self } } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index ebec1609959..8dc5ba37e6e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -24,7 +24,10 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #[macro_use] extern crate log; extern crate graphviz as dot; +extern crate rustc; extern crate rustc_data_structures; +extern crate rustc_front; +extern crate syntax; pub mod build; pub mod dump; diff --git a/src/librustc_mir/repr.rs b/src/librustc_mir/repr.rs index d522518a3d4..bffc44bccbd 100644 --- a/src/librustc_mir/repr.rs +++ b/src/librustc_mir/repr.rs @@ -8,22 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hair::Hair; +use rustc::middle::const_eval::ConstVal; +use rustc::middle::def_id::DefId; +use rustc::middle::region::CodeExtent; +use rustc::middle::subst::Substs; +use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty}; use rustc_data_structures::fnv::FnvHashMap; +use rustc_front::hir::InlineAsm; +use syntax::ast::Name; +use syntax::codemap::Span; use std::fmt::{Debug, Formatter, Error}; use std::slice; use std::u32; /// Lowered representation of a single function. -pub struct Mir { - pub basic_blocks: Vec>, +pub struct Mir<'tcx> { + pub basic_blocks: Vec>, // for every node id - pub extents: FnvHashMap>, + pub extents: FnvHashMap>, - pub var_decls: Vec>, - pub arg_decls: Vec>, - pub temp_decls: Vec>, + pub var_decls: Vec>, + pub arg_decls: Vec>, + pub temp_decls: Vec>, } /// where execution begins @@ -35,18 +42,18 @@ pub const END_BLOCK: BasicBlock = BasicBlock(1); /// where execution ends, on panic pub const DIVERGE_BLOCK: BasicBlock = BasicBlock(2); -impl Mir { +impl<'tcx> Mir<'tcx> { pub fn all_basic_blocks(&self) -> Vec { (0..self.basic_blocks.len()) .map(|i| BasicBlock::new(i)) .collect() } - pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData { + pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> { &self.basic_blocks[bb.index()] } - pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData { + pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> { &mut self.basic_blocks[bb.index()] } } @@ -111,16 +118,16 @@ pub enum BorrowKind { // A "variable" is a binding declared by the user as part of the fn // decl, a let, etc. -pub struct VarDecl { +pub struct VarDecl<'tcx> { pub mutability: Mutability, - pub name: H::Name, - pub ty: H::Ty, + pub name: Name, + pub ty: Ty<'tcx>, } // A "temp" is a temporary that we place on the stack. They are // anonymous, always mutable, and have only a type. -pub struct TempDecl { - pub ty: H::Ty, +pub struct TempDecl<'tcx> { + pub ty: Ty<'tcx>, } // A "arg" is one of the function's formal arguments. These are @@ -134,8 +141,8 @@ pub struct TempDecl { // // there is only one argument, of type `(i32, u32)`, but two bindings // (`x` and `y`). -pub struct ArgDecl { - pub ty: H::Ty, +pub struct ArgDecl<'tcx> { + pub ty: Ty<'tcx>, } /////////////////////////////////////////////////////////////////////////// @@ -212,12 +219,12 @@ impl Debug for BasicBlock { // BasicBlock and Terminator #[derive(Debug)] -pub struct BasicBlockData { - pub statements: Vec>, - pub terminator: Terminator, +pub struct BasicBlockData<'tcx> { + pub statements: Vec>, + pub terminator: Terminator<'tcx>, } -pub enum Terminator { +pub enum Terminator<'tcx> { /// block should have one successor in the graph; we jump there Goto { target: BasicBlock }, @@ -226,10 +233,10 @@ pub enum Terminator { Panic { target: BasicBlock }, /// jump to branch 0 if this lvalue evaluates to true - If { cond: Operand, targets: [BasicBlock; 2] }, + If { cond: Operand<'tcx>, targets: [BasicBlock; 2] }, /// lvalue evaluates to some enum; jump depending on the branch - Switch { discr: Lvalue, targets: Vec }, + Switch { discr: Lvalue<'tcx>, targets: Vec }, /// Indicates that the last statement in the block panics, aborts, /// etc. No successors. This terminator appears on exactly one @@ -247,10 +254,10 @@ pub enum Terminator { /// block ends with a call; it should have two successors. The /// first successor indicates normal return. The second indicates /// unwinding. - Call { data: CallData, targets: [BasicBlock; 2] }, + Call { data: CallData<'tcx>, targets: [BasicBlock; 2] }, } -impl Terminator { +impl<'tcx> Terminator<'tcx> { pub fn successors(&self) -> &[BasicBlock] { use self::Terminator::*; match *self { @@ -266,19 +273,19 @@ impl Terminator { } #[derive(Debug)] -pub struct CallData { +pub struct CallData<'tcx> { /// where the return value is written to - pub destination: Lvalue, + pub destination: Lvalue<'tcx>, /// the fn being called - pub func: Lvalue, + pub func: Lvalue<'tcx>, /// the arguments - pub args: Vec>, + pub args: Vec>, } -impl BasicBlockData { - pub fn new(terminator: Terminator) -> BasicBlockData { +impl<'tcx> BasicBlockData<'tcx> { + pub fn new(terminator: Terminator<'tcx>) -> BasicBlockData<'tcx> { BasicBlockData { statements: vec![], terminator: terminator, @@ -286,7 +293,7 @@ impl BasicBlockData { } } -impl Debug for Terminator { +impl<'tcx> Debug for Terminator<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::Terminator::*; match *self { @@ -318,15 +325,15 @@ impl Debug for Terminator { /////////////////////////////////////////////////////////////////////////// // Statements -pub struct Statement { - pub span: H::Span, - pub kind: StatementKind, +pub struct Statement<'tcx> { + pub span: Span, + pub kind: StatementKind<'tcx>, } #[derive(Debug)] -pub enum StatementKind { - Assign(Lvalue, Rvalue), - Drop(DropKind, Lvalue), +pub enum StatementKind<'tcx> { + Assign(Lvalue<'tcx>, Rvalue<'tcx>), + Drop(DropKind, Lvalue<'tcx>), } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -335,7 +342,7 @@ pub enum DropKind { Deep } -impl Debug for Statement { +impl<'tcx> Debug for Statement<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::StatementKind::*; match self.kind { @@ -351,7 +358,7 @@ impl Debug for Statement { /// A path to a value; something that can be evaluated without /// changing or disturbing program state. #[derive(Clone, PartialEq)] -pub enum Lvalue { +pub enum Lvalue<'tcx> { /// local variable declared by the user Var(u32), @@ -363,13 +370,13 @@ pub enum Lvalue { Arg(u32), /// static or static mut variable - Static(H::DefId), + Static(DefId), /// the return pointer of the fn ReturnPointer, /// projection out of an lvalue (access a field, deref a pointer, etc) - Projection(Box>) + Projection(Box>) } /// The `Projection` data structure defines things of the form `B.x` @@ -377,15 +384,15 @@ pub enum Lvalue { /// shared between `Constant` and `Lvalue`. See the aliases /// `LvalueProjection` etc below. #[derive(Clone, Debug, PartialEq)] -pub struct Projection { +pub struct Projection<'tcx,B,V> { pub base: B, - pub elem: ProjectionElem, + pub elem: ProjectionElem<'tcx,V>, } #[derive(Clone, Debug, PartialEq)] -pub enum ProjectionElem { +pub enum ProjectionElem<'tcx,V> { Deref, - Field(Field), + Field(Field), Index(V), // These indices are generated by slice patterns. Easiest to explain @@ -406,44 +413,44 @@ pub enum ProjectionElem { // "Downcast" to a variant of an ADT. Currently, we only introduce // this for ADTs with more than one variant. It may be better to // just introduce it always, or always for enums. - Downcast(H::AdtDef, usize), + Downcast(AdtDef<'tcx>, usize), } /// Alias for projections as they appear in lvalues, where the base is an lvalue /// and the index is an operand. -pub type LvalueProjection = - Projection,Operand>; +pub type LvalueProjection<'tcx> = + Projection<'tcx,Lvalue<'tcx>,Operand<'tcx>>; /// Alias for projections as they appear in lvalues, where the base is an lvalue /// and the index is an operand. -pub type LvalueElem = - ProjectionElem>; +pub type LvalueElem<'tcx> = + ProjectionElem<'tcx,Operand<'tcx>>; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum Field { - Named(H::Name), +pub enum Field { + Named(Name), Indexed(usize), } -impl Lvalue { - pub fn field(self, f: Field) -> Lvalue { +impl<'tcx> Lvalue<'tcx> { + pub fn field(self, f: Field) -> Lvalue<'tcx> { self.elem(ProjectionElem::Field(f)) } - pub fn deref(self) -> Lvalue { + pub fn deref(self) -> Lvalue<'tcx> { self.elem(ProjectionElem::Deref) } - pub fn index(self, index: Operand) -> Lvalue { + pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> { self.elem(ProjectionElem::Index(index)) } - pub fn elem(self, elem: LvalueElem) -> Lvalue { + pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> { Lvalue::Projection(Box::new(LvalueProjection { base: self, elem: elem })) } } -impl Debug for Lvalue { +impl<'tcx> Debug for Lvalue<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::Lvalue::*; @@ -487,12 +494,12 @@ impl Debug for Lvalue { // being nested in one another. #[derive(Clone, PartialEq)] -pub enum Operand { - Consume(Lvalue), - Constant(Constant), +pub enum Operand<'tcx> { + Consume(Lvalue<'tcx>), + Constant(Constant<'tcx>), } -impl Debug for Operand { +impl<'tcx> Debug for Operand<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::Operand::*; match *self { @@ -506,34 +513,34 @@ impl Debug for Operand { // Rvalues #[derive(Clone)] -pub enum Rvalue { +pub enum Rvalue<'tcx> { // x (either a move or copy, depending on type of x) - Use(Operand), + Use(Operand<'tcx>), // [x; 32] - Repeat(Operand, Operand), + Repeat(Operand<'tcx>, Operand<'tcx>), // &x or &mut x - Ref(H::Region, BorrowKind, Lvalue), + Ref(Region, BorrowKind, Lvalue<'tcx>), // length of a [X] or [X;n] value - Len(Lvalue), + Len(Lvalue<'tcx>), - Cast(CastKind, Operand, H::Ty), + Cast(CastKind, Operand<'tcx>, Ty<'tcx>), - BinaryOp(BinOp, Operand, Operand), + BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>), - UnaryOp(UnOp, Operand), + UnaryOp(UnOp, Operand<'tcx>), // Creates an *uninitialized* Box - Box(H::Ty), + Box(Ty<'tcx>), // Create an aggregate value, like a tuple or struct. This is // only needed because we want to distinguish `dest = Foo { x: // ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case // that `Foo` has a destructor. These rvalues can be optimized // away after type-checking and before lowering. - Aggregate(AggregateKind, Vec>), + Aggregate(AggregateKind<'tcx>, Vec>), // Generates a slice of the form `&input[from_start..L-from_end]` // where `L` is the length of the slice. This is only created by @@ -541,12 +548,12 @@ pub enum Rvalue { // .., z]` might create a slice with `from_start=2` and // `from_end=1`. Slice { - input: Lvalue, + input: Lvalue<'tcx>, from_start: usize, from_end: usize, }, - InlineAsm(H::InlineAsm), + InlineAsm(&'tcx InlineAsm), } #[derive(Clone, Debug, PartialEq, Eq)] @@ -568,11 +575,11 @@ pub enum CastKind { } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum AggregateKind { +pub enum AggregateKind<'tcx> { Vec, Tuple, - Adt(H::AdtDef, usize, H::Substs), - Closure(H::DefId, H::ClosureSubsts), + Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>), + Closure(DefId, &'tcx ClosureSubsts<'tcx>), } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -619,7 +626,7 @@ pub enum UnOp { Neg } -impl Debug for Rvalue { +impl<'tcx> Debug for Rvalue<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { use self::Rvalue::*; @@ -648,15 +655,15 @@ impl Debug for Rvalue { // particular one must be wary of `NaN`! #[derive(Clone, Debug, PartialEq)] -pub struct Constant { - pub span: H::Span, - pub ty: H::Ty, - pub literal: Literal +pub struct Constant<'tcx> { + pub span: Span, + pub ty: Ty<'tcx>, + pub literal: Literal<'tcx> } #[derive(Clone, Debug, PartialEq)] -pub enum Literal { - Item { def_id: H::DefId, substs: H::Substs }, - Value { value: H::ConstVal }, +pub enum Literal<'tcx> { + Item { def_id: DefId, substs: &'tcx Substs<'tcx> }, + Value { value: ConstVal }, } diff --git a/src/librustc_mir/tcx/block.rs b/src/librustc_mir/tcx/block.rs index 033e6ed2968..69cbe4b67e5 100644 --- a/src/librustc_mir/tcx/block.rs +++ b/src/librustc_mir/tcx/block.rs @@ -12,16 +12,16 @@ use hair::*; use tcx::Cx; use tcx::pattern::PatNode; -use tcx::rustc::middle::region::{BlockRemainder, CodeExtentData}; -use tcx::rustc_front::hir; -use tcx::syntax::ast; -use tcx::syntax::ptr::P; use tcx::to_ref::ToRef; +use rustc::middle::region::{BlockRemainder, CodeExtentData}; +use rustc_front::hir; +use syntax::ast; +use syntax::ptr::P; -impl<'a,'tcx:'a> Mirror> for &'tcx hir::Block { - type Output = Block>; +impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { + type Output = Block<'tcx>; - fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Block> { + fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Block<'tcx> { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate()); @@ -34,10 +34,10 @@ impl<'a,'tcx:'a> Mirror> for &'tcx hir::Block { } } -impl<'a,'tcx:'a> Mirror> for &'tcx hir::Stmt { - type Output = Stmt>; +impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt { + type Output = Stmt<'tcx>; - fn make_mirror(self, _cx: &mut Cx<'a,'tcx>) -> Stmt> { + fn make_mirror<'a>(self, _cx: &mut Cx<'a,'tcx>) -> Stmt<'tcx> { // In order to get the scoping correct, we eagerly mirror // statements when we translate the enclosing block, so we // should in fact never get to this point. @@ -48,7 +48,7 @@ impl<'a,'tcx:'a> Mirror> for &'tcx hir::Stmt { fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>, block_id: ast::NodeId, mut stmts: STMTS) - -> Vec>> + -> Vec> where STMTS: Iterator)> { let mut result = vec![]; @@ -101,7 +101,7 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>, pub fn to_expr_ref<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, block: &'tcx hir::Block) - -> ExprRef> { + -> ExprRef<'tcx> { let block_ty = cx.tcx.node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { diff --git a/src/librustc_mir/tcx/expr.rs b/src/librustc_mir/tcx/expr.rs index 098a85514eb..c14b83c9370 100644 --- a/src/librustc_mir/tcx/expr.rs +++ b/src/librustc_mir/tcx/expr.rs @@ -15,22 +15,22 @@ use std::rc::Rc; use tcx::Cx; use tcx::block; use tcx::pattern::PatNode; -use tcx::rustc::front::map; -use tcx::rustc::middle::const_eval; -use tcx::rustc::middle::def; -use tcx::rustc::middle::region::CodeExtent; -use tcx::rustc::middle::pat_util; -use tcx::rustc::middle::ty::{self, Ty}; -use tcx::rustc_front::hir; -use tcx::rustc_front::util as hir_util; -use tcx::syntax::parse::token; -use tcx::syntax::ptr::P; use tcx::to_ref::ToRef; +use rustc::front::map; +use rustc::middle::const_eval; +use rustc::middle::def; +use rustc::middle::region::CodeExtent; +use rustc::middle::pat_util; +use rustc::middle::ty::{self, Ty}; +use rustc_front::hir; +use rustc_front::util as hir_util; +use syntax::parse::token; +use syntax::ptr::P; -impl<'a,'tcx:'a> Mirror> for &'tcx hir::Expr { - type Output = Expr>; +impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { + type Output = Expr<'tcx>; - fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr> { + fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Expr<'tcx> { debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)! @@ -427,7 +427,7 @@ impl<'a,'tcx:'a> Mirror> for &'tcx hir::Expr { fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, expr: &hir::Expr, method_call: ty::MethodCall) - -> Expr> { + -> Expr<'tcx> { let tables = cx.tcx.tables.borrow(); let callee = &tables.method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); @@ -451,7 +451,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { } } -fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm> { +fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { let map = if arm.pats.len() == 1 { None } else { @@ -469,7 +469,7 @@ fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm(cx: &mut Cx<'a,'tcx>, expr: &'tcx hir::Expr) - -> ExprKind> + -> ExprKind<'tcx> { let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs); match cx.tcx.def_map.borrow()[&expr.id].full_def() { @@ -502,7 +502,7 @@ fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, expr: &'tcx hir::Expr, def: def::Def) - -> ExprKind> + -> ExprKind<'tcx> { let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); @@ -665,9 +665,9 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, expr: &'tcx hir::Expr, method_call: ty::MethodCall, pass_args: PassArgs, - receiver: ExprRef>, + receiver: ExprRef<'tcx>, args: Vec<&'tcx P>) - -> ExprKind> + -> ExprKind<'tcx> { // the receiver has all the adjustments that are needed, so we can // just push a reference to it @@ -718,9 +718,9 @@ fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, expr: &'tcx hir::Expr, method_call: ty::MethodCall, pass_args: PassArgs, - receiver: ExprRef>, + receiver: ExprRef<'tcx>, args: Vec<&'tcx P>) - -> ExprKind> + -> ExprKind<'tcx> { // For an overloaded *x or x[y] expression of type T, the method // call returns an &T and we must add the deref so that the types @@ -754,7 +754,7 @@ fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, closure_expr: &'tcx hir::Expr, freevar: &ty::Freevar, freevar_ty: Ty<'tcx>) - -> ExprRef> { + -> ExprRef<'tcx> { let id_var = freevar.def.var_id(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap(); diff --git a/src/librustc_mir/tcx/mod.rs b/src/librustc_mir/tcx/mod.rs index 04f52a52464..32694bd509e 100644 --- a/src/librustc_mir/tcx/mod.rs +++ b/src/librustc_mir/tcx/mod.rs @@ -8,31 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! + * This module contains the code to convert from the wacky tcx data + * structures into the hair. The `builder` is generally ignorant of + * the tcx etc, and instead goes through the `Cx` for most of its + * work. + */ + use hair::*; use repr::*; use std::fmt::{Debug, Formatter, Error}; use std::hash::{Hash, Hasher}; -use std::rc::Rc; -use self::rustc::middle::const_eval::ConstVal; -use self::rustc::middle::def_id::DefId; -use self::rustc::middle::infer::InferCtxt; -use self::rustc::middle::region::CodeExtent; -use self::rustc::middle::subst::{self, Subst, Substs}; -use self::rustc::middle::ty::{self, Ty}; -use self::rustc_front::hir; -use self::syntax::ast; -use self::syntax::codemap::Span; -use self::syntax::parse::token::{self, special_idents, InternedString}; - -extern crate rustc; -extern crate rustc_front; -extern crate syntax; +use rustc::middle::const_eval::ConstVal; +use rustc::middle::def_id::DefId; +use rustc::middle::infer::InferCtxt; +use rustc::middle::subst::{Subst, Substs}; +use rustc::middle::ty::{self, Ty}; +use syntax::codemap::Span; +use syntax::parse::token::{self, special_idents}; #[derive(Copy, Clone)] pub struct Cx<'a,'tcx:'a> { - pub tcx: &'a ty::ctxt<'tcx>, - pub infcx: &'a InferCtxt<'a,'tcx>, + tcx: &'a ty::ctxt<'tcx>, + infcx: &'a InferCtxt<'a,'tcx>, } impl<'a,'tcx> Cx<'a,'tcx> { @@ -43,66 +42,51 @@ impl<'a,'tcx> Cx<'a,'tcx> { pub use self::pattern::PatNode; -impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> { - type VarId = ast::NodeId; - type DefId = DefId; - type AdtDef = ty::AdtDef<'tcx>; - type Name = ast::Name; - type InternedString = InternedString; - type Bytes = Rc>; - type Span = Span; - type Projection = ty::ProjectionTy<'tcx>; - type Substs = &'tcx subst::Substs<'tcx>; - type ClosureSubsts = &'tcx ty::ClosureSubsts<'tcx>; - type Ty = Ty<'tcx>; - type Region = ty::Region; - type CodeExtent = CodeExtent; - type ConstVal = ConstVal; - type Pattern = PatNode<'tcx>; - type Expr = &'tcx hir::Expr; - type Stmt = &'tcx hir::Stmt; - type Block = &'tcx hir::Block; - type InlineAsm = &'tcx hir::InlineAsm; +impl<'a,'tcx:'a> Cx<'a, 'tcx> { + /// Normalizes `ast` into the appropriate `mirror` type. + pub fn mirror>(&mut self, ast: M) -> M::Output { + ast.make_mirror(self) + } - fn unit_ty(&mut self) -> Ty<'tcx> { + pub fn unit_ty(&mut self) -> Ty<'tcx> { self.tcx.mk_nil() } - fn usize_ty(&mut self) -> Ty<'tcx> { + pub fn usize_ty(&mut self) -> Ty<'tcx> { self.tcx.types.usize } - fn usize_literal(&mut self, value: usize) -> Literal { + pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> { Literal::Value { value: ConstVal::Uint(value as u64) } } - fn bool_ty(&mut self) -> Ty<'tcx> { + pub fn bool_ty(&mut self) -> Ty<'tcx> { self.tcx.types.bool } - fn true_literal(&mut self) -> Literal { + pub fn true_literal(&mut self) -> Literal<'tcx> { Literal::Value { value: ConstVal::Bool(true) } } - fn false_literal(&mut self) -> Literal { + pub fn false_literal(&mut self) -> Literal<'tcx> { Literal::Value { value: ConstVal::Bool(false) } } - fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef { + pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); self.cmp_method_ref(eq_def_id, "eq", ty) } - fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef { + pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> { let ord_def_id = self.tcx.lang_items.ord_trait().unwrap(); self.cmp_method_ref(ord_def_id, "le", ty) } - fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { + pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize { adt_def.variants.len() } - fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec> { + pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec { adt_def.variants[variant_index] .fields .iter() @@ -117,7 +101,7 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> { .collect() } - fn needs_drop(&mut self, ty: Ty<'tcx>, span: Self::Span) -> bool { + pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool { if self.infcx.type_moves_by_default(ty, span) { // FIXME(#21859) we should do an add'l check here to determine if // any dtor will execute, but the relevant fn @@ -130,17 +114,19 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> { } } - fn span_bug(&mut self, span: Self::Span, message: &str) -> ! { + pub fn span_bug(&mut self, span: Span, message: &str) -> ! { self.tcx.sess.span_bug(span, message) } -} -impl<'a,'tcx:'a> Cx<'a,'tcx> { + pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { + self.tcx + } + fn cmp_method_ref(&mut self, trait_def_id: DefId, method_name: &str, arg_ty: Ty<'tcx>) - -> ItemRef> { + -> ItemRef<'tcx> { let method_name = token::intern(method_name); let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty); for trait_item in self.tcx.trait_items(trait_def_id).iter() { diff --git a/src/librustc_mir/tcx/pattern.rs b/src/librustc_mir/tcx/pattern.rs index fe0c2c6c76a..9407f9e7600 100644 --- a/src/librustc_mir/tcx/pattern.rs +++ b/src/librustc_mir/tcx/pattern.rs @@ -14,15 +14,15 @@ use repr::*; use rustc_data_structures::fnv::FnvHashMap; use std::rc::Rc; use tcx::Cx; -use tcx::rustc::middle::const_eval; -use tcx::rustc::middle::def; -use tcx::rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding}; -use tcx::rustc::middle::subst::Substs; -use tcx::rustc::middle::ty::{self, Ty}; -use tcx::rustc_front::hir; -use tcx::syntax::ast; -use tcx::syntax::ptr::P; use tcx::to_ref::ToRef; +use rustc::middle::const_eval; +use rustc::middle::def; +use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding}; +use rustc::middle::subst::Substs; +use rustc::middle::ty::{self, Ty}; +use rustc_front::hir; +use syntax::ast; +use syntax::ptr::P; /// When there are multiple patterns in a single arm, each one has its /// own node-ids for the bindings. References to the variables always @@ -58,15 +58,15 @@ impl<'tcx> PatNode<'tcx> { PatNode::new(pat, None) } - fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef> { + fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> { PatNode::new(pat, self.binding_map.clone()).to_ref() } - fn pat_refs<'a>(&self, pats: &'tcx Vec>) -> Vec>> { + fn pat_refs<'a>(&self, pats: &'tcx Vec>) -> Vec> { pats.iter().map(|p| self.pat_ref(p)).collect() } - fn opt_pat_ref<'a>(&self, pat: &'tcx Option>) -> Option>> { + fn opt_pat_ref<'a>(&self, pat: &'tcx Option>) -> Option> { pat.as_ref().map(|p| self.pat_ref(p)) } @@ -76,7 +76,7 @@ impl<'tcx> PatNode<'tcx> { prefix: &'tcx Vec>, slice: &'tcx Option>, suffix: &'tcx Vec>) - -> PatternKind> + -> PatternKind<'tcx> { match ty.sty { ty::TySlice(..) => @@ -107,8 +107,8 @@ impl<'tcx> PatNode<'tcx> { fn variant_or_leaf<'a>(&self, cx: &mut Cx<'a, 'tcx>, - subpatterns: Vec>>) - -> PatternKind> + subpatterns: Vec>) + -> PatternKind<'tcx> { let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); match def { @@ -138,10 +138,10 @@ impl<'tcx> PatNode<'tcx> { } } -impl<'a,'tcx:'a> Mirror> for PatNode<'tcx> { - type Output = Pattern>; +impl<'tcx> Mirror<'tcx> for PatNode<'tcx> { + type Output = Pattern<'tcx>; - fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Pattern> { + fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Pattern<'tcx> { let kind = match self.pat.node { hir::PatWild(..) => PatternKind::Wild, diff --git a/src/librustc_mir/tcx/to_ref.rs b/src/librustc_mir/tcx/to_ref.rs index 3c8a5534e1a..7da8d7deefd 100644 --- a/src/librustc_mir/tcx/to_ref.rs +++ b/src/librustc_mir/tcx/to_ref.rs @@ -11,58 +11,57 @@ use hair::*; use repr::*; -use tcx::Cx; use tcx::pattern::PatNode; -use tcx::rustc_front::hir; -use tcx::syntax::ptr::P; +use rustc_front::hir; +use syntax::ptr::P; -pub trait ToRef { +pub trait ToRef { type Output; fn to_ref(self) -> Self::Output; } -impl<'a,'tcx:'a> ToRef> for &'tcx hir::Expr { - type Output = ExprRef>; +impl<'a,'tcx:'a> ToRef for &'tcx hir::Expr { + type Output = ExprRef<'tcx>; - fn to_ref(self) -> ExprRef> { + fn to_ref(self) -> ExprRef<'tcx> { ExprRef::Hair(self) } } -impl<'a,'tcx:'a> ToRef> for &'tcx P { - type Output = ExprRef>; +impl<'a,'tcx:'a> ToRef for &'tcx P { + type Output = ExprRef<'tcx>; - fn to_ref(self) -> ExprRef> { + fn to_ref(self) -> ExprRef<'tcx> { ExprRef::Hair(&**self) } } -impl<'a,'tcx:'a> ToRef> for Expr> { - type Output = ExprRef>; +impl<'a,'tcx:'a> ToRef for Expr<'tcx> { + type Output = ExprRef<'tcx>; - fn to_ref(self) -> ExprRef> { + fn to_ref(self) -> ExprRef<'tcx> { ExprRef::Mirror(Box::new(self)) } } -impl<'a,'tcx:'a> ToRef> for PatNode<'tcx> { - type Output = PatternRef>; +impl<'a,'tcx:'a> ToRef for PatNode<'tcx> { + type Output = PatternRef<'tcx>; - fn to_ref(self) -> PatternRef> { + fn to_ref(self) -> PatternRef<'tcx> { PatternRef::Hair(self) } } -impl<'a,'tcx:'a> ToRef> for Pattern> { - type Output = PatternRef>; +impl<'a,'tcx:'a> ToRef for Pattern<'tcx> { + type Output = PatternRef<'tcx>; - fn to_ref(self) -> PatternRef> { + fn to_ref(self) -> PatternRef<'tcx> { PatternRef::Mirror(Box::new(self)) } } -impl<'a,'tcx:'a,T,U> ToRef> for &'tcx Option - where &'tcx T: ToRef, Output=U> +impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option + where &'tcx T: ToRef { type Output = Option; @@ -71,8 +70,8 @@ impl<'a,'tcx:'a,T,U> ToRef> for &'tcx Option } } -impl<'a,'tcx:'a,T,U> ToRef> for &'tcx Vec - where &'tcx T: ToRef, Output=U> +impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec + where &'tcx T: ToRef { type Output = Vec; @@ -81,10 +80,10 @@ impl<'a,'tcx:'a,T,U> ToRef> for &'tcx Vec } } -impl<'a,'tcx:'a> ToRef> for &'tcx hir::Field { - type Output = FieldExprRef>; +impl<'a,'tcx:'a> ToRef for &'tcx hir::Field { + type Output = FieldExprRef<'tcx>; - fn to_ref(self) -> FieldExprRef> { + fn to_ref(self) -> FieldExprRef<'tcx> { FieldExprRef { name: Field::Named(self.name.node), expr: self.expr.to_ref()