1
Fork 0

Auto merge of #28866 - nikomatsakis:remove-hair-trait, r=nrc

As the subject says. This PR also removes the `Hair` trait, which was impeding the ability to build such a map, as described in this thread on internals:

https://internals.rust-lang.org/t/removing-the-hair-trait-from-mir-construction/2732

r? @nrc
This commit is contained in:
bors 2015-10-07 05:11:44 +00:00
commit a63b0f045d
31 changed files with 671 additions and 736 deletions

View file

@ -175,18 +175,6 @@ ifdef CFG_DISABLE_STAGE0_LANDING_PADS
RUSTFLAGS_STAGE0 += -Z no-landing-pads RUSTFLAGS_STAGE0 += -Z no-landing-pads
endif endif
# Enable MIR to "always build" for crates where this works. This is
# just temporary while MIR is being actively built up -- it's just a
# poor man's unit testing infrastructure. Anyway we only want this for
# stage1/stage2.
define ADD_MIR_FLAG
RUSTFLAGS1_$(1) += -Z always-build-mir
RUSTFLAGS2_$(1) += -Z always-build-mir
endef
$(foreach crate,$(TARGET_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
$(foreach crate,$(RUSTC_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
$(foreach crate,$(HOST_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
# platform-specific auto-configuration # platform-specific auto-configuration
include $(CFG_SRC_DIR)mk/platform.mk include $(CFG_SRC_DIR)mk/platform.mk

View file

@ -101,7 +101,6 @@ pub struct Options {
pub parse_only: bool, pub parse_only: bool,
pub no_trans: bool, pub no_trans: bool,
pub treat_err_as_bug: bool, pub treat_err_as_bug: bool,
pub always_build_mir: bool,
pub no_analysis: bool, pub no_analysis: bool,
pub debugging_opts: DebuggingOptions, pub debugging_opts: DebuggingOptions,
pub prints: Vec<PrintRequest>, pub prints: Vec<PrintRequest>,
@ -211,7 +210,6 @@ pub fn basic_options() -> Options {
parse_only: false, parse_only: false,
no_trans: false, no_trans: false,
treat_err_as_bug: false, treat_err_as_bug: false,
always_build_mir: false,
no_analysis: false, no_analysis: false,
debugging_opts: basic_debugging_options(), debugging_opts: basic_debugging_options(),
prints: Vec::new(), prints: Vec::new(),
@ -578,8 +576,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"Run all passes except translation; no output"), "Run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool, treat_err_as_bug: bool = (false, parse_bool,
"Treat all errors that occur as bugs"), "Treat all errors that occur as bugs"),
always_build_mir: bool = (false, parse_bool,
"Always build MIR for all fns, even without a #[rustc_mir] annotation"),
no_analysis: bool = (false, parse_bool, no_analysis: bool = (false, parse_bool,
"Parse and expand the source, but run no analysis"), "Parse and expand the source, but run no analysis"),
extra_plugins: Vec<String> = (Vec::new(), parse_list, extra_plugins: Vec<String> = (Vec::new(), parse_list,
@ -895,7 +891,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
let parse_only = debugging_opts.parse_only; let parse_only = debugging_opts.parse_only;
let no_trans = debugging_opts.no_trans; let no_trans = debugging_opts.no_trans;
let treat_err_as_bug = debugging_opts.treat_err_as_bug; let treat_err_as_bug = debugging_opts.treat_err_as_bug;
let always_build_mir = debugging_opts.always_build_mir;
let no_analysis = debugging_opts.no_analysis; let no_analysis = debugging_opts.no_analysis;
if debugging_opts.debug_llvm { if debugging_opts.debug_llvm {
@ -1049,7 +1044,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
parse_only: parse_only, parse_only: parse_only,
no_trans: no_trans, no_trans: no_trans,
treat_err_as_bug: treat_err_as_bug, treat_err_as_bug: treat_err_as_bug,
always_build_mir: always_build_mir,
no_analysis: no_analysis, no_analysis: no_analysis,
debugging_opts: debugging_opts, debugging_opts: debugging_opts,
prints: prints, prints: prints,

View file

@ -738,8 +738,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
time(time_passes, "match checking", || time(time_passes, "match checking", ||
middle::check_match::check_crate(tcx)); middle::check_match::check_crate(tcx));
let _mir_map =
time(time_passes, "MIR dump", || time(time_passes, "MIR dump", ||
mir::dump::dump_crate(tcx)); mir::mir_map::build_mir_for_crate(tcx));
time(time_passes, "liveness checking", || time(time_passes, "liveness checking", ||
middle::liveness::check_crate(tcx)); middle::liveness::check_crate(tcx));

View file

@ -8,15 +8,16 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use build::{BlockAnd, Builder};
use hair::*; use hair::*;
use repr::*; use repr::*;
use build::{BlockAnd, Builder}; use rustc_front::hir;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn ast_block(&mut self, pub fn ast_block(&mut self,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
mut block: BasicBlock, mut block: BasicBlock,
ast_block: H::Block) ast_block: &'tcx hir::Block)
-> BlockAnd<()> { -> BlockAnd<()> {
let this = self; let this = self;
let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block); let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block);

View file

@ -14,15 +14,15 @@
//! Routines for manipulating the control-flow graph. //! Routines for manipulating the control-flow graph.
use build::CFG; use build::CFG;
use hair::*;
use repr::*; use repr::*;
use syntax::codemap::Span;
impl<H:Hair> CFG<H> { impl<'tcx> CFG<'tcx> {
pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<H> { pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[blk.index()] &self.basic_blocks[blk.index()]
} }
pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<H> { pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[blk.index()] &mut self.basic_blocks[blk.index()]
} }
@ -39,21 +39,21 @@ impl<H:Hair> CFG<H> {
BasicBlock::new(node_index) BasicBlock::new(node_index)
} }
pub fn push(&mut self, block: BasicBlock, statement: Statement<H>) { pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
debug!("push({:?}, {:?})", block, statement); debug!("push({:?}, {:?})", block, statement);
self.block_data_mut(block).statements.push(statement); self.block_data_mut(block).statements.push(statement);
} }
pub fn push_assign_constant(&mut self, pub fn push_assign_constant(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
temp: &Lvalue<H>, temp: &Lvalue<'tcx>,
constant: Constant<H>) { constant: Constant<'tcx>) {
self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant))); self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
} }
pub fn push_drop(&mut self, block: BasicBlock, span: H::Span, pub fn push_drop(&mut self, block: BasicBlock, span: Span,
kind: DropKind, lvalue: &Lvalue<H>) { kind: DropKind, lvalue: &Lvalue<'tcx>) {
self.push(block, Statement { self.push(block, Statement {
span: span, span: span,
kind: StatementKind::Drop(kind, lvalue.clone()) kind: StatementKind::Drop(kind, lvalue.clone())
@ -62,9 +62,9 @@ impl<H:Hair> CFG<H> {
pub fn push_assign(&mut self, pub fn push_assign(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
lvalue: &Lvalue<H>, lvalue: &Lvalue<'tcx>,
rvalue: Rvalue<H>) { rvalue: Rvalue<'tcx>) {
self.push(block, Statement { self.push(block, Statement {
span: span, span: span,
kind: StatementKind::Assign(lvalue.clone(), rvalue) kind: StatementKind::Assign(lvalue.clone(), rvalue)
@ -73,7 +73,7 @@ impl<H:Hair> CFG<H> {
pub fn terminate(&mut self, pub fn terminate(&mut self,
block: BasicBlock, block: BasicBlock,
terminator: Terminator<H>) { terminator: Terminator<'tcx>) {
// Check whether this block has already been terminated. For // Check whether this block has already been terminated. For
// this, we rely on the fact that the initial state is to have // this, we rely on the fact that the initial state is to have
// a Diverge terminator and an empty list of targets (which // a Diverge terminator and an empty list of targets (which

View file

@ -14,17 +14,17 @@ use build::{Builder};
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that /// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant! /// `expr` is a valid compile-time constant!
pub fn as_constant<M>(&mut self, expr: M) -> Constant<H> pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
where M: Mirror<H, Output=Expr<H>> where M: Mirror<'tcx, Output=Expr<'tcx>>
{ {
let expr = self.hir.mirror(expr); let expr = self.hir.mirror(expr);
self.expr_as_constant(expr) self.expr_as_constant(expr)
} }
fn expr_as_constant(&mut self, expr: Expr<H>) -> Constant<H> { fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
let this = self; let this = self;
let Expr { ty, temp_lifetime: _, span, kind } = expr; let Expr { ty, temp_lifetime: _, span, kind } = expr;
match kind { match kind {

View file

@ -15,13 +15,13 @@ use build::expr::category::Category;
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr`, yielding an lvalue that we can move from etc. /// Compile `expr`, yielding an lvalue that we can move from etc.
pub fn as_lvalue<M>(&mut self, pub fn as_lvalue<M>(&mut self,
block: BasicBlock, block: BasicBlock,
expr: M) expr: M)
-> BlockAnd<Lvalue<H>> -> BlockAnd<Lvalue<'tcx>>
where M: Mirror<H, Output=Expr<H>> where M: Mirror<'tcx, Output=Expr<'tcx>>
{ {
let expr = self.hir.mirror(expr); let expr = self.hir.mirror(expr);
self.expr_as_lvalue(block, expr) self.expr_as_lvalue(block, expr)
@ -29,8 +29,8 @@ impl<H:Hair> Builder<H> {
fn expr_as_lvalue(&mut self, fn expr_as_lvalue(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: Expr<H>) expr: Expr<'tcx>)
-> BlockAnd<Lvalue<H>> -> BlockAnd<Lvalue<'tcx>>
{ {
debug!("expr_as_lvalue(block={:?}, expr={:?})", debug!("expr_as_lvalue(block={:?}, expr={:?})",
block, expr); block, expr);

View file

@ -15,7 +15,7 @@ use build::expr::category::Category;
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr` into a value that can be used as an operand. /// Compile `expr` into a value that can be used as an operand.
/// If `expr` is an lvalue like `x`, this will introduce a /// If `expr` is an lvalue like `x`, this will introduce a
/// temporary `tmp = x`, so that we capture the value of `x` at /// temporary `tmp = x`, so that we capture the value of `x` at
@ -23,8 +23,8 @@ impl<H:Hair> Builder<H> {
pub fn as_operand<M>(&mut self, pub fn as_operand<M>(&mut self,
block: BasicBlock, block: BasicBlock,
expr: M) expr: M)
-> BlockAnd<Operand<H>> -> BlockAnd<Operand<'tcx>>
where M: Mirror<H, Output=Expr<H>> where M: Mirror<'tcx, Output=Expr<'tcx>>
{ {
let expr = self.hir.mirror(expr); let expr = self.hir.mirror(expr);
self.expr_as_operand(block, expr) self.expr_as_operand(block, expr)
@ -32,8 +32,8 @@ impl<H:Hair> Builder<H> {
fn expr_as_operand(&mut self, fn expr_as_operand(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: Expr<H>) expr: Expr<'tcx>)
-> BlockAnd<Operand<H>> -> BlockAnd<Operand<'tcx>>
{ {
debug!("expr_as_operand(block={:?}, expr={:?})", debug!("expr_as_operand(block={:?}, expr={:?})",
block, expr); block, expr);

View file

@ -17,13 +17,13 @@ use build::expr::category::{Category, RvalueFunc};
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr`, yielding an rvalue. /// Compile `expr`, yielding an rvalue.
pub fn as_rvalue<M>(&mut self, pub fn as_rvalue<M>(&mut self,
block: BasicBlock, block: BasicBlock,
expr: M) expr: M)
-> BlockAnd<Rvalue<H>> -> BlockAnd<Rvalue<'tcx>>
where M: Mirror<H, Output=Expr<H>> where M: Mirror<'tcx, Output=Expr<'tcx>>
{ {
let expr = self.hir.mirror(expr); let expr = self.hir.mirror(expr);
self.expr_as_rvalue(block, expr) self.expr_as_rvalue(block, expr)
@ -31,8 +31,8 @@ impl<H:Hair> Builder<H> {
fn expr_as_rvalue(&mut self, fn expr_as_rvalue(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: Expr<H>) expr: Expr<'tcx>)
-> BlockAnd<Rvalue<H>> -> BlockAnd<Rvalue<'tcx>>
{ {
debug!("expr_as_rvalue(block={:?}, expr={:?})", debug!("expr_as_rvalue(block={:?}, expr={:?})",
block, expr); block, expr);

View file

@ -15,14 +15,14 @@ use build::expr::category::Category;
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr` into a fresh temporary. This is used when building /// Compile `expr` into a fresh temporary. This is used when building
/// up rvalues so as to freeze the value that will be consumed. /// up rvalues so as to freeze the value that will be consumed.
pub fn as_temp<M>(&mut self, pub fn as_temp<M>(&mut self,
block: BasicBlock, block: BasicBlock,
expr: M) expr: M)
-> BlockAnd<Lvalue<H>> -> BlockAnd<Lvalue<'tcx>>
where M: Mirror<H, Output=Expr<H>> where M: Mirror<'tcx, Output=Expr<'tcx>>
{ {
let expr = self.hir.mirror(expr); let expr = self.hir.mirror(expr);
self.expr_as_temp(block, expr) self.expr_as_temp(block, expr)
@ -30,8 +30,8 @@ impl<H:Hair> Builder<H> {
fn expr_as_temp(&mut self, fn expr_as_temp(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: Expr<H>) expr: Expr<'tcx>)
-> BlockAnd<Lvalue<H>> -> BlockAnd<Lvalue<'tcx>>
{ {
debug!("expr_as_temp(block={:?}, expr={:?})", debug!("expr_as_temp(block={:?}, expr={:?})",
block, expr); block, expr);

View file

@ -41,7 +41,7 @@ pub enum RvalueFunc {
/// Determines the category for a given expression. Note that scope /// Determines the category for a given expression. Note that scope
/// and paren expressions have no category. /// and paren expressions have no category.
impl Category { impl Category {
pub fn of<H:Hair>(ek: &ExprKind<H>) -> Option<Category> { pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option<Category> {
match *ek { match *ek {
ExprKind::Scope { .. } => None, ExprKind::Scope { .. } => None,

View file

@ -15,14 +15,16 @@ use build::expr::category::{Category, RvalueFunc};
use build::scope::LoopScope; use build::scope::LoopScope;
use hair::*; use hair::*;
use repr::*; use repr::*;
use rustc::middle::region::CodeExtent;
use syntax::codemap::Span;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Compile `expr`, storing the result into `destination`, which /// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized. /// is assumed to be uninitialized.
pub fn into_expr(&mut self, pub fn into_expr(&mut self,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
mut block: BasicBlock, mut block: BasicBlock,
expr: Expr<H>) expr: Expr<'tcx>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
debug!("into_expr(destination={:?}, block={:?}, expr={:?})", debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
@ -266,12 +268,12 @@ impl<H:Hair> Builder<H> {
} }
fn break_or_continue<F>(&mut self, fn break_or_continue<F>(&mut self,
span: H::Span, span: Span,
label: Option<H::CodeExtent>, label: Option<CodeExtent>,
block: BasicBlock, block: BasicBlock,
exit_selector: F) exit_selector: F)
-> BlockAnd<()> -> BlockAnd<()>
where F: FnOnce(&LoopScope<H>) -> BasicBlock where F: FnOnce(&LoopScope) -> BasicBlock
{ {
let loop_scope = self.find_loop_scope(span, label); let loop_scope = self.find_loop_scope(span, label);
let exit_block = exit_selector(&loop_scope); let exit_block = exit_selector(&loop_scope);

View file

@ -18,27 +18,27 @@ use build::{BlockAnd, Builder};
use hair::*; use hair::*;
use repr::*; use repr::*;
pub trait EvalInto<H:Hair> { pub trait EvalInto<'tcx> {
fn eval_into(self, builder: &mut Builder<H>, destination: &Lvalue<H>, fn eval_into<'a>(self, builder: &mut Builder<'a,'tcx>, destination: &Lvalue<'tcx>,
block: BasicBlock) -> BlockAnd<()>; block: BasicBlock) -> BlockAnd<()>;
} }
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn into<E>(&mut self, pub fn into<E>(&mut self,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
block: BasicBlock, block: BasicBlock,
expr: E) expr: E)
-> BlockAnd<()> -> BlockAnd<()>
where E: EvalInto<H> where E: EvalInto<'tcx>
{ {
expr.eval_into(self, destination, block) expr.eval_into(self, destination, block)
} }
} }
impl<H:Hair> EvalInto<H> for ExprRef<H> { impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
fn eval_into(self, fn eval_into<'a>(self,
builder: &mut Builder<H>, builder: &mut Builder<'a,'tcx>,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
block: BasicBlock) block: BasicBlock)
-> BlockAnd<()> { -> BlockAnd<()> {
let expr = builder.hir.mirror(self); let expr = builder.hir.mirror(self);
@ -46,20 +46,20 @@ impl<H:Hair> EvalInto<H> for ExprRef<H> {
} }
} }
impl<H:Hair> EvalInto<H> for Expr<H> { impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
fn eval_into(self, fn eval_into<'a>(self,
builder: &mut Builder<H>, builder: &mut Builder<'a,'tcx>,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
block: BasicBlock) block: BasicBlock)
-> BlockAnd<()> { -> BlockAnd<()> {
builder.into_expr(destination, block, self) builder.into_expr(destination, block, self)
} }
} }
impl<H:Hair> EvalInto<H> for Option<ExprRef<H>> { impl<'tcx> EvalInto<'tcx> for Option<ExprRef<'tcx>> {
fn eval_into(self, fn eval_into<'a>(self,
builder: &mut Builder<H>, builder: &mut Builder<'a,'tcx>,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
block: BasicBlock) block: BasicBlock)
-> BlockAnd<()> { -> BlockAnd<()> {
match self { match self {

View file

@ -15,20 +15,24 @@
use build::{BlockAnd, Builder}; use build::{BlockAnd, Builder};
use repr::*; use repr::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::{AdtDef, Ty};
use hair::*; use hair::*;
use syntax::ast::{Name, NodeId};
use syntax::codemap::Span;
// helper functions, broken out by category: // helper functions, broken out by category:
mod simplify; mod simplify;
mod test; mod test;
mod util; mod util;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn match_expr(&mut self, pub fn match_expr(&mut self,
destination: &Lvalue<H>, destination: &Lvalue<'tcx>,
span: H::Span, span: Span,
mut block: BasicBlock, mut block: BasicBlock,
discriminant: ExprRef<H>, discriminant: ExprRef<'tcx>,
arms: Vec<Arm<H>>) arms: Vec<Arm<'tcx>>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
let discriminant_lvalue = let discriminant_lvalue =
@ -49,7 +53,7 @@ impl<H:Hair> Builder<H> {
.collect(), .collect(),
}; };
let arm_bodies: Vec<ExprRef<H>> = let arm_bodies: Vec<ExprRef<'tcx>> =
arms.iter() arms.iter()
.map(|arm| arm.body.clone()) .map(|arm| arm.body.clone())
.collect(); .collect();
@ -60,7 +64,7 @@ impl<H:Hair> Builder<H> {
// highest priority candidate comes last in the list. This the // highest priority candidate comes last in the list. This the
// reverse of the order in which candidates are written in the // reverse of the order in which candidates are written in the
// source. // source.
let candidates: Vec<Candidate<H>> = let candidates: Vec<Candidate<'tcx>> =
arms.iter() arms.iter()
.enumerate() .enumerate()
.rev() // highest priority comes last .rev() // highest priority comes last
@ -97,9 +101,9 @@ impl<H:Hair> Builder<H> {
pub fn expr_into_pattern(&mut self, pub fn expr_into_pattern(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
var_extent: H::CodeExtent, // lifetime of vars var_extent: CodeExtent, // lifetime of vars
irrefutable_pat: PatternRef<H>, irrefutable_pat: PatternRef<'tcx>,
initializer: ExprRef<H>) initializer: ExprRef<'tcx>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
// optimize the case of `let x = ...` // optimize the case of `let x = ...`
@ -125,16 +129,16 @@ impl<H:Hair> Builder<H> {
pub fn lvalue_into_pattern(&mut self, pub fn lvalue_into_pattern(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
var_extent: H::CodeExtent, var_extent: CodeExtent,
irrefutable_pat: PatternRef<H>, irrefutable_pat: PatternRef<'tcx>,
initializer: &Lvalue<H>) initializer: &Lvalue<'tcx>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
// first, creating the bindings // first, creating the bindings
self.declare_bindings(var_extent, irrefutable_pat.clone()); self.declare_bindings(var_extent, irrefutable_pat.clone());
// create a dummy candidate // create a dummy candidate
let mut candidate = Candidate::<H> { let mut candidate = Candidate::<'tcx> {
match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())], match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())],
bindings: vec![], bindings: vec![],
guard: None, guard: None,
@ -159,8 +163,8 @@ impl<H:Hair> Builder<H> {
} }
pub fn declare_bindings(&mut self, pub fn declare_bindings(&mut self,
var_extent: H::CodeExtent, var_extent: CodeExtent,
pattern: PatternRef<H>) pattern: PatternRef<'tcx>)
{ {
let pattern = self.hir.mirror(pattern); let pattern = self.hir.mirror(pattern);
match pattern.kind { match pattern.kind {
@ -198,69 +202,69 @@ struct ArmBlocks {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Candidate<H:Hair> { struct Candidate<'tcx> {
// all of these must be satisfied... // all of these must be satisfied...
match_pairs: Vec<MatchPair<H>>, match_pairs: Vec<MatchPair<'tcx>>,
// ...these bindings established... // ...these bindings established...
bindings: Vec<Binding<H>>, bindings: Vec<Binding<'tcx>>,
// ...and the guard must be evaluated... // ...and the guard must be evaluated...
guard: Option<ExprRef<H>>, guard: Option<ExprRef<'tcx>>,
// ...and then we branch to arm with this index. // ...and then we branch to arm with this index.
arm_index: usize, arm_index: usize,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Binding<H:Hair> { struct Binding<'tcx> {
span: H::Span, span: Span,
source: Lvalue<H>, source: Lvalue<'tcx>,
name: H::Name, name: Name,
var_id: H::VarId, var_id: NodeId,
var_ty: H::Ty, var_ty: Ty<'tcx>,
mutability: Mutability, mutability: Mutability,
binding_mode: BindingMode<H>, binding_mode: BindingMode,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct MatchPair<H:Hair> { struct MatchPair<'tcx> {
// this lvalue... // this lvalue...
lvalue: Lvalue<H>, lvalue: Lvalue<'tcx>,
// ... must match this pattern. // ... must match this pattern.
pattern: Pattern<H>, pattern: Pattern<'tcx>,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
enum TestKind<H:Hair> { enum TestKind<'tcx> {
// test the branches of enum // test the branches of enum
Switch { adt_def: H::AdtDef }, Switch { adt_def: AdtDef<'tcx> },
// test for equality // test for equality
Eq { value: Literal<H>, ty: H::Ty }, Eq { value: Literal<'tcx>, ty: Ty<'tcx> },
// test whether the value falls within an inclusive range // test whether the value falls within an inclusive range
Range { lo: Literal<H>, hi: Literal<H>, ty: H::Ty }, Range { lo: Literal<'tcx>, hi: Literal<'tcx>, ty: Ty<'tcx> },
// test length of the slice is equal to len // test length of the slice is equal to len
Len { len: usize, op: BinOp }, Len { len: usize, op: BinOp },
} }
#[derive(Debug)] #[derive(Debug)]
struct Test<H:Hair> { struct Test<'tcx> {
span: H::Span, span: Span,
kind: TestKind<H>, kind: TestKind<'tcx>,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Main matching algorithm // Main matching algorithm
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
fn match_candidates(&mut self, fn match_candidates(&mut self,
span: H::Span, span: Span,
arm_blocks: &mut ArmBlocks, arm_blocks: &mut ArmBlocks,
mut candidates: Vec<Candidate<H>>, mut candidates: Vec<Candidate<'tcx>>,
mut block: BasicBlock) mut block: BasicBlock)
{ {
debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})", debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})",
@ -306,7 +310,7 @@ impl<H:Hair> Builder<H> {
let target_blocks = self.perform_test(block, &match_pair.lvalue, &test); let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
for (outcome, mut target_block) in target_blocks.into_iter().enumerate() { for (outcome, mut target_block) in target_blocks.into_iter().enumerate() {
let applicable_candidates: Vec<Candidate<H>> = let applicable_candidates: Vec<Candidate<'tcx>> =
candidates.iter() candidates.iter()
.filter_map(|candidate| { .filter_map(|candidate| {
unpack!(target_block = unpack!(target_block =
@ -336,7 +340,7 @@ impl<H:Hair> Builder<H> {
fn bind_and_guard_matched_candidate(&mut self, fn bind_and_guard_matched_candidate(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
arm_blocks: &mut ArmBlocks, arm_blocks: &mut ArmBlocks,
candidate: Candidate<H>) candidate: Candidate<'tcx>)
-> Option<BasicBlock> { -> Option<BasicBlock> {
debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})", debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
block, candidate); block, candidate);
@ -363,7 +367,7 @@ impl<H:Hair> Builder<H> {
fn bind_matched_candidate(&mut self, fn bind_matched_candidate(&mut self,
block: BasicBlock, block: BasicBlock,
bindings: Vec<Binding<H>>) { bindings: Vec<Binding<'tcx>>) {
debug!("bind_matched_candidate(block={:?}, bindings={:?})", debug!("bind_matched_candidate(block={:?}, bindings={:?})",
block, bindings); block, bindings);
@ -386,19 +390,19 @@ impl<H:Hair> Builder<H> {
} }
fn declare_binding(&mut self, fn declare_binding(&mut self,
var_extent: H::CodeExtent, var_extent: CodeExtent,
mutability: Mutability, mutability: Mutability,
name: H::Name, name: Name,
var_id: H::VarId, var_id: NodeId,
var_ty: H::Ty, var_ty: Ty<'tcx>,
span: H::Span) span: Span)
-> u32 -> u32
{ {
debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_extent={:?}, span={:?})", debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_extent={:?}, span={:?})",
var_id, name, var_ty, var_extent, span); var_id, name, var_ty, var_extent, span);
let index = self.var_decls.len(); let index = self.var_decls.len();
self.var_decls.push(VarDecl::<H> { self.var_decls.push(VarDecl::<'tcx> {
mutability: mutability, mutability: mutability,
name: name, name: name,
ty: var_ty.clone(), ty: var_ty.clone(),

View file

@ -29,10 +29,10 @@ use repr::*;
use std::mem; use std::mem;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn simplify_candidate(&mut self, pub fn simplify_candidate(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
candidate: &mut Candidate<H>) candidate: &mut Candidate<'tcx>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
// repeatedly simplify match pairs until fixed point is reached // repeatedly simplify match pairs until fixed point is reached
@ -56,13 +56,14 @@ impl<H:Hair> Builder<H> {
/// Tries to simplify `match_pair`, returning true if /// Tries to simplify `match_pair`, returning true if
/// successful. If successful, new match pairs and bindings will /// successful. If successful, new match pairs and bindings will
/// have been pushed into the candidate. On failure (if false is /// have been pushed into the candidate. If no simplification is
/// returned), no changes are made to candidate. /// possible, Err is returned and no changes are made to
/// candidate.
fn simplify_match_pair(&mut self, fn simplify_match_pair(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
match_pair: MatchPair<H>, match_pair: MatchPair<'tcx>,
candidate: &mut Candidate<H>) candidate: &mut Candidate<'tcx>)
-> Result<BasicBlock, MatchPair<H>> // returns Err() if cannot simplify -> Result<BasicBlock, MatchPair<'tcx>>
{ {
match match_pair.pattern.kind { match match_pair.pattern.kind {
PatternKind::Wild(..) => { PatternKind::Wild(..) => {

View file

@ -19,12 +19,13 @@ use build::{BlockAnd, Builder};
use build::matches::{Candidate, MatchPair, Test, TestKind}; use build::matches::{Candidate, MatchPair, Test, TestKind};
use hair::*; use hair::*;
use repr::*; use repr::*;
use syntax::codemap::Span;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Identifies what test is needed to decide if `match_pair` is applicable. /// Identifies what test is needed to decide if `match_pair` is applicable.
/// ///
/// It is a bug to call this with a simplifyable pattern. /// It is a bug to call this with a simplifyable pattern.
pub fn test(&mut self, match_pair: &MatchPair<H>) -> Test<H> { pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> {
match match_pair.pattern.kind { match match_pair.pattern.kind {
PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => { PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => {
Test { Test {
@ -72,8 +73,8 @@ impl<H:Hair> Builder<H> {
/// Generates the code to perform a test. /// Generates the code to perform a test.
pub fn perform_test(&mut self, pub fn perform_test(&mut self,
block: BasicBlock, block: BasicBlock,
lvalue: &Lvalue<H>, lvalue: &Lvalue<'tcx>,
test: &Test<H>) test: &Test<'tcx>)
-> Vec<BasicBlock> { -> Vec<BasicBlock> {
match test.kind.clone() { match test.kind.clone() {
TestKind::Switch { adt_def } => { TestKind::Switch { adt_def } => {
@ -149,10 +150,10 @@ impl<H:Hair> Builder<H> {
fn call_comparison_fn(&mut self, fn call_comparison_fn(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
item_ref: ItemRef<H>, item_ref: ItemRef<'tcx>,
lvalue1: Lvalue<H>, lvalue1: Lvalue<'tcx>,
lvalue2: Lvalue<H>) lvalue2: Lvalue<'tcx>)
-> Vec<BasicBlock> { -> Vec<BasicBlock> {
let target_blocks = vec![self.cfg.start_new_block(), let target_blocks = vec![self.cfg.start_new_block(),
self.cfg.start_new_block()]; self.cfg.start_new_block()];
@ -194,11 +195,11 @@ impl<H:Hair> Builder<H> {
/// @ 22])`. /// @ 22])`.
pub fn candidate_under_assumption(&mut self, pub fn candidate_under_assumption(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
test_lvalue: &Lvalue<H>, test_lvalue: &Lvalue<'tcx>,
test_kind: &TestKind<H>, test_kind: &TestKind<'tcx>,
test_outcome: usize, test_outcome: usize,
candidate: &Candidate<H>) candidate: &Candidate<'tcx>)
-> BlockAnd<Option<Candidate<H>>> { -> BlockAnd<Option<Candidate<'tcx>>> {
let candidate = candidate.clone(); let candidate = candidate.clone();
let match_pairs = candidate.match_pairs; let match_pairs = candidate.match_pairs;
let result = unpack!(block = self.match_pairs_under_assumption(block, let result = unpack!(block = self.match_pairs_under_assumption(block,
@ -216,11 +217,11 @@ impl<H:Hair> Builder<H> {
/// work of transforming the list of match pairs. /// work of transforming the list of match pairs.
fn match_pairs_under_assumption(&mut self, fn match_pairs_under_assumption(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
test_lvalue: &Lvalue<H>, test_lvalue: &Lvalue<'tcx>,
test_kind: &TestKind<H>, test_kind: &TestKind<'tcx>,
test_outcome: usize, test_outcome: usize,
match_pairs: Vec<MatchPair<H>>) match_pairs: Vec<MatchPair<'tcx>>)
-> BlockAnd<Option<Vec<MatchPair<H>>>> { -> BlockAnd<Option<Vec<MatchPair<'tcx>>>> {
let mut result = vec![]; let mut result = vec![];
for match_pair in match_pairs { for match_pair in match_pairs {
@ -279,9 +280,9 @@ impl<H:Hair> Builder<H> {
/// It is a bug to call this with a simplifyable pattern. /// It is a bug to call this with a simplifyable pattern.
pub fn consequent_match_pairs_under_assumption(&mut self, pub fn consequent_match_pairs_under_assumption(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
match_pair: MatchPair<H>, match_pair: MatchPair<'tcx>,
test_outcome: usize) test_outcome: usize)
-> BlockAnd<Option<Vec<MatchPair<H>>>> { -> BlockAnd<Option<Vec<MatchPair<'tcx>>>> {
match match_pair.pattern.kind { match match_pair.pattern.kind {
PatternKind::Variant { adt_def, variant_index, subpatterns } => { PatternKind::Variant { adt_def, variant_index, subpatterns } => {
if test_outcome != variant_index { if test_outcome != variant_index {
@ -339,7 +340,7 @@ impl<H:Hair> Builder<H> {
} }
} }
fn error_simplifyable(&mut self, match_pair: &MatchPair<H>) -> ! { fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! {
self.hir.span_bug( self.hir.span_bug(
match_pair.pattern.span, match_pair.pattern.span,
&format!("simplifyable pattern found: {:?}", match_pair.pattern)) &format!("simplifyable pattern found: {:?}", match_pair.pattern))

View file

@ -14,11 +14,11 @@ use hair::*;
use repr::*; use repr::*;
use std::u32; use std::u32;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn field_match_pairs(&mut self, pub fn field_match_pairs(&mut self,
lvalue: Lvalue<H>, lvalue: Lvalue<'tcx>,
subpatterns: Vec<FieldPatternRef<H>>) subpatterns: Vec<FieldPatternRef<'tcx>>)
-> Vec<MatchPair<H>> { -> Vec<MatchPair<'tcx>> {
subpatterns.into_iter() subpatterns.into_iter()
.map(|fieldpat| { .map(|fieldpat| {
let lvalue = lvalue.clone().field(fieldpat.field); let lvalue = lvalue.clone().field(fieldpat.field);
@ -27,7 +27,8 @@ impl<H:Hair> Builder<H> {
.collect() .collect()
} }
pub fn match_pair(&mut self, lvalue: Lvalue<H>, pattern: PatternRef<H>) -> MatchPair<H> { pub fn match_pair(&mut self, lvalue: Lvalue<'tcx>, pattern: PatternRef<'tcx>)
-> MatchPair<'tcx> {
let pattern = self.hir.mirror(pattern); let pattern = self.hir.mirror(pattern);
MatchPair::new(lvalue, pattern) MatchPair::new(lvalue, pattern)
} }
@ -47,12 +48,12 @@ impl<H:Hair> Builder<H> {
/// ///
/// and creates a match pair `tmp0 @ s` /// and creates a match pair `tmp0 @ s`
pub fn prefix_suffix_slice(&mut self, pub fn prefix_suffix_slice(&mut self,
match_pairs: &mut Vec<MatchPair<H>>, match_pairs: &mut Vec<MatchPair<'tcx>>,
block: BasicBlock, block: BasicBlock,
lvalue: Lvalue<H>, lvalue: Lvalue<'tcx>,
prefix: Vec<PatternRef<H>>, prefix: Vec<PatternRef<'tcx>>,
opt_slice: Option<PatternRef<H>>, opt_slice: Option<PatternRef<'tcx>>,
suffix: Vec<PatternRef<H>>) suffix: Vec<PatternRef<'tcx>>)
-> BlockAnd<()> -> BlockAnd<()>
{ {
// If there is a `..P` pattern, create a temporary `t0` for // If there is a `..P` pattern, create a temporary `t0` for
@ -76,10 +77,10 @@ impl<H:Hair> Builder<H> {
/// Helper for `prefix_suffix_slice` which just processes the prefix and suffix. /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
fn prefix_suffix(&mut self, fn prefix_suffix(&mut self,
match_pairs: &mut Vec<MatchPair<H>>, match_pairs: &mut Vec<MatchPair<'tcx>>,
lvalue: Lvalue<H>, lvalue: Lvalue<'tcx>,
prefix: Vec<PatternRef<H>>, prefix: Vec<PatternRef<'tcx>>,
suffix: Vec<PatternRef<H>>) suffix: Vec<PatternRef<'tcx>>)
{ {
let min_length = prefix.len() + suffix.len(); let min_length = prefix.len() + suffix.len();
assert!(min_length < u32::MAX as usize); assert!(min_length < u32::MAX as usize);
@ -118,8 +119,8 @@ impl<H:Hair> Builder<H> {
} }
} }
impl<H:Hair> MatchPair<H> { impl<'tcx> MatchPair<'tcx> {
pub fn new(lvalue: Lvalue<H>, pattern: Pattern<H>) -> MatchPair<H> { pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> {
MatchPair { lvalue: lvalue, pattern: pattern } MatchPair { lvalue: lvalue, pattern: pattern }
} }
} }

View file

@ -14,16 +14,17 @@
use build::Builder; use build::Builder;
use hair::*; use hair::*;
use repr::*; use repr::*;
use rustc::middle::ty::Ty;
use std::u32; use std::u32;
use syntax::codemap::Span;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Add a new temporary value of type `ty` storing the result of /// Add a new temporary value of type `ty` storing the result of
/// evaluating `expr`. /// evaluating `expr`.
/// ///
/// NB: **No cleanup is scheduled for this temporary.** You should /// NB: **No cleanup is scheduled for this temporary.** You should
/// call `schedule_drop` once the temporary is initialized. /// call `schedule_drop` once the temporary is initialized.
pub fn temp(&mut self, ty: H::Ty) -> Lvalue<H> { pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
let index = self.temp_decls.len(); let index = self.temp_decls.len();
self.temp_decls.push(TempDecl { ty: ty }); self.temp_decls.push(TempDecl { ty: ty });
assert!(index < (u32::MAX) as usize); assert!(index < (u32::MAX) as usize);
@ -35,10 +36,10 @@ impl<H:Hair> Builder<H> {
pub fn push_literal(&mut self, pub fn push_literal(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
ty: H::Ty, ty: Ty<'tcx>,
literal: Literal<H>) literal: Literal<'tcx>)
-> Lvalue<H> { -> Lvalue<'tcx> {
let temp = self.temp(ty.clone()); let temp = self.temp(ty.clone());
let constant = Constant { span: span, ty: ty, literal: literal }; let constant = Constant { span: span, ty: ty, literal: literal };
self.cfg.push_assign_constant(block, span, &temp, constant); self.cfg.push_assign_constant(block, span, &temp, constant);
@ -47,9 +48,9 @@ impl<H:Hair> Builder<H> {
pub fn push_usize(&mut self, pub fn push_usize(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
value: usize) value: usize)
-> Lvalue<H> { -> Lvalue<'tcx> {
let usize_ty = self.hir.usize_ty(); let usize_ty = self.hir.usize_ty();
let temp = self.temp(usize_ty); let temp = self.temp(usize_ty);
self.cfg.push_assign_constant( self.cfg.push_assign_constant(
@ -64,9 +65,9 @@ impl<H:Hair> Builder<H> {
pub fn push_item_ref(&mut self, pub fn push_item_ref(&mut self,
block: BasicBlock, block: BasicBlock,
span: H::Span, span: Span,
item_ref: ItemRef<H>) item_ref: ItemRef<'tcx>)
-> Lvalue<H> { -> Lvalue<'tcx> {
let literal = Literal::Item { def_id: item_ref.def_id, substs: item_ref.substs }; let literal = Literal::Item { def_id: item_ref.def_id, substs: item_ref.substs };
self.push_literal(block, span, item_ref.ty, literal) self.push_literal(block, span, item_ref.ty, literal)
} }

View file

@ -8,24 +8,30 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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_data_structures::fnv::FnvHashMap;
use rustc_front::hir;
use repr::*; use repr::*;
use syntax::ast;
use syntax::codemap::Span;
use tcx::{Cx, PatNode};
struct Builder<H:Hair> { struct Builder<'a,'tcx:'a> {
hir: H, hir: Cx<'a, 'tcx>,
extents: FnvHashMap<H::CodeExtent, Vec<GraphExtent>>, extents: FnvHashMap<CodeExtent, Vec<GraphExtent>>,
cfg: CFG<H>, cfg: CFG<'tcx>,
scopes: Vec<scope::Scope<H>>, scopes: Vec<scope::Scope<'tcx>>,
loop_scopes: Vec<scope::LoopScope<H>>, loop_scopes: Vec<scope::LoopScope>,
unit_temp: Lvalue<H>, unit_temp: Lvalue<'tcx>,
var_decls: Vec<VarDecl<H>>, var_decls: Vec<VarDecl<'tcx>>,
var_indices: FnvHashMap<H::VarId, u32>, var_indices: FnvHashMap<ast::NodeId, u32>,
temp_decls: Vec<TempDecl<H>>, temp_decls: Vec<TempDecl<'tcx>>,
} }
struct CFG<H:Hair> { struct CFG<'tcx> {
basic_blocks: Vec<BasicBlockData<H>> basic_blocks: Vec<BasicBlockData<'tcx>>
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -69,18 +75,18 @@ macro_rules! unpack {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// construct() -- the main entry point for building MIR for a function // construct() -- the main entry point for building MIR for a function
pub fn construct<H:Hair>(mut hir: H, pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
_span: H::Span, _span: Span,
implicit_arguments: Vec<H::Ty>, implicit_arguments: Vec<Ty<'tcx>>,
explicit_arguments: Vec<(H::Ty, H::Pattern)>, explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
argument_extent: H::CodeExtent, argument_extent: CodeExtent,
ast_block: H::Block) ast_block: &'tcx hir::Block)
-> Mir<H> { -> Mir<'tcx> {
let cfg = CFG { basic_blocks: vec![] }; let cfg = CFG { basic_blocks: vec![] };
// it's handy to have a temporary of type `()` sometimes, so make // it's handy to have a temporary of type `()` sometimes, so make
// one from the start and keep it available // one from the start and keep it available
let temp_decls = vec![TempDecl::<H> { ty: hir.unit_ty() }]; let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
let unit_temp = Lvalue::Temp(0); let unit_temp = Lvalue::Temp(0);
let mut builder = Builder { let mut builder = Builder {
@ -118,14 +124,14 @@ pub fn construct<H:Hair>(mut hir: H,
} }
} }
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
fn args_and_body(&mut self, fn args_and_body(&mut self,
mut block: BasicBlock, mut block: BasicBlock,
implicit_arguments: Vec<H::Ty>, implicit_arguments: Vec<Ty<'tcx>>,
explicit_arguments: Vec<(H::Ty, H::Pattern)>, explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
argument_extent: H::CodeExtent, argument_extent: CodeExtent,
ast_block: H::Block) ast_block: &'tcx hir::Block)
-> BlockAnd<Vec<ArgDecl<H>>> -> BlockAnd<Vec<ArgDecl<'tcx>>>
{ {
self.in_scope(argument_extent, block, |this| { self.in_scope(argument_extent, block, |this| {
let arg_decls = { let arg_decls = {

View file

@ -12,7 +12,7 @@
Managing the scope stack. The scopes are tied to lexical scopes, so as 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 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 contents, and then pop it off. Every scope is named by a
`H::CodeExtent`. `CodeExtent`.
### SEME Regions ### 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, from the scope. Each lexical scope thus corresponds to a single-entry,
multiple-exit (SEME) region in the control-flow graph. 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 corresponding SEME region for later reference (see caveat in next
paragraph). This is because region scopes are tied to paragraph). This is because region scopes are tied to
them. Eventually, when we shift to non-lexical lifetimes, three should them. Eventually, when we shift to non-lexical lifetimes, three should
@ -87,24 +87,26 @@ should go to.
*/ */
use build::{BlockAnd, Builder, CFG}; use build::{BlockAnd, Builder, CFG};
use hair::Hair;
use repr::*; use repr::*;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::Ty;
use syntax::codemap::Span;
pub struct Scope<H:Hair> { pub struct Scope<'tcx> {
extent: H::CodeExtent, extent: CodeExtent,
exits: Vec<ExecutionPoint>, exits: Vec<ExecutionPoint>,
drops: Vec<(DropKind, H::Span, Lvalue<H>)>, drops: Vec<(DropKind, Span, Lvalue<'tcx>)>,
cached_block: Option<BasicBlock>, cached_block: Option<BasicBlock>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LoopScope<H:Hair> { pub struct LoopScope {
pub extent: H::CodeExtent, // extent of the loop pub extent: CodeExtent, // extent of the loop
pub continue_block: BasicBlock, // where to go on a `loop` pub continue_block: BasicBlock, // where to go on a `loop`
pub break_block: BasicBlock, // where to go on a `break pub break_block: BasicBlock, // where to go on a `break
} }
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
/// Start a loop scope, which tracks where `continue` and `break` /// Start a loop scope, which tracks where `continue` and `break`
/// should branch to. See module comment for more details. /// should branch to. See module comment for more details.
pub fn in_loop_scope<F,R>(&mut self, pub fn in_loop_scope<F,R>(&mut self,
@ -112,10 +114,10 @@ impl<H:Hair> Builder<H> {
break_block: BasicBlock, break_block: BasicBlock,
f: F) f: F)
-> BlockAnd<R> -> BlockAnd<R>
where F: FnOnce(&mut Builder<H>) -> BlockAnd<R> where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd<R>
{ {
let extent = self.extent_of_innermost_scope().unwrap(); let extent = self.extent_of_innermost_scope().unwrap();
let loop_scope = LoopScope::<H> { extent: extent.clone(), let loop_scope = LoopScope { extent: extent.clone(),
continue_block: loop_block, continue_block: loop_block,
break_block: break_block }; break_block: break_block };
self.loop_scopes.push(loop_scope); self.loop_scopes.push(loop_scope);
@ -127,11 +129,11 @@ impl<H:Hair> Builder<H> {
/// Start a scope. The closure `f` should translate the contents /// Start a scope. The closure `f` should translate the contents
/// of the scope. See module comment for more details. /// of the scope. See module comment for more details.
pub fn in_scope<F,R>(&mut self, pub fn in_scope<F,R>(&mut self,
extent: H::CodeExtent, extent: CodeExtent,
block: BasicBlock, block: BasicBlock,
f: F) f: F)
-> BlockAnd<R> -> BlockAnd<R>
where F: FnOnce(&mut Builder<H>) -> BlockAnd<R> where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd<R>
{ {
debug!("in_scope(extent={:?}, block={:?})", extent, block); debug!("in_scope(extent={:?}, block={:?})", extent, block);
@ -180,9 +182,9 @@ impl<H:Hair> Builder<H> {
/// Finds the loop scope for a given label. This is used for /// Finds the loop scope for a given label. This is used for
/// resolving `break` and `continue`. /// resolving `break` and `continue`.
pub fn find_loop_scope(&mut self, pub fn find_loop_scope(&mut self,
span: H::Span, span: Span,
label: Option<H::CodeExtent>) label: Option<CodeExtent>)
-> LoopScope<H> { -> LoopScope {
let loop_scope = let loop_scope =
match label { match label {
None => { None => {
@ -211,8 +213,8 @@ impl<H:Hair> Builder<H> {
/// needed, as well as tracking this exit for the SEME region. See /// needed, as well as tracking this exit for the SEME region. See
/// module comment for details. /// module comment for details.
pub fn exit_scope(&mut self, pub fn exit_scope(&mut self,
span: H::Span, span: Span,
extent: H::CodeExtent, extent: CodeExtent,
block: BasicBlock, block: BasicBlock,
target: BasicBlock) { target: BasicBlock) {
let popped_scopes = let popped_scopes =
@ -249,11 +251,11 @@ impl<H:Hair> Builder<H> {
/// Indicates that `lvalue` should be dropped on exit from /// Indicates that `lvalue` should be dropped on exit from
/// `extent`. /// `extent`.
pub fn schedule_drop(&mut self, pub fn schedule_drop(&mut self,
span: H::Span, span: Span,
extent: H::CodeExtent, extent: CodeExtent,
kind: DropKind, kind: DropKind,
lvalue: &Lvalue<H>, lvalue: &Lvalue<'tcx>,
lvalue_ty: H::Ty) lvalue_ty: Ty<'tcx>)
{ {
if self.hir.needs_drop(lvalue_ty, span) { if self.hir.needs_drop(lvalue_ty, span) {
match self.scopes.iter_mut().rev().find(|s| s.extent == extent) { match self.scopes.iter_mut().rev().find(|s| s.extent == extent) {
@ -267,17 +269,17 @@ impl<H:Hair> Builder<H> {
} }
} }
pub fn extent_of_innermost_scope(&self) -> Option<H::CodeExtent> { pub fn extent_of_innermost_scope(&self) -> Option<CodeExtent> {
self.scopes.last().map(|scope| scope.extent) self.scopes.last().map(|scope| scope.extent)
} }
pub fn extent_of_outermost_scope(&self) -> Option<H::CodeExtent> { pub fn extent_of_outermost_scope(&self) -> Option<CodeExtent> {
self.scopes.first().map(|scope| scope.extent) self.scopes.first().map(|scope| scope.extent)
} }
} }
fn diverge_cleanup_helper<H:Hair>(cfg: &mut CFG<H>, fn diverge_cleanup_helper<'tcx>(cfg: &mut CFG<'tcx>,
scopes: &mut [Scope<H>]) scopes: &mut [Scope<'tcx>])
-> BasicBlock { -> BasicBlock {
let len = scopes.len(); let len = scopes.len();

View file

@ -12,15 +12,15 @@ use build::{BlockAnd, Builder};
use hair::*; use hair::*;
use repr::*; use repr::*;
impl<H:Hair> Builder<H> { impl<'a,'tcx> Builder<'a,'tcx> {
pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<H>>) -> BlockAnd<()> { pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<'tcx>>) -> BlockAnd<()> {
for stmt in stmts { for stmt in stmts {
unpack!(block = self.stmt(block, stmt)); unpack!(block = self.stmt(block, stmt));
} }
block.unit() block.unit()
} }
pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef<H>) -> BlockAnd<()> { pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef<'tcx>) -> BlockAnd<()> {
let this = self; let this = self;
let Stmt { span, kind } = this.hir.mirror(stmt); let Stmt { span, kind } = this.hir.mirror(stmt);
match kind { match kind {

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
use dot; use dot;
use hair::Hair;
use repr::*; use repr::*;
use std::borrow::IntoCow; use std::borrow::IntoCow;
@ -20,7 +19,7 @@ pub struct EdgeIndex {
index: usize, index: usize,
} }
impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<H> { impl<'a,'tcx> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<'tcx> {
fn graph_id(&'a self) -> dot::Id<'a> { fn graph_id(&'a self) -> dot::Id<'a> {
dot::Id::new("Mir").unwrap() dot::Id::new("Mir").unwrap()
} }
@ -62,7 +61,7 @@ impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<H> {
} }
} }
impl<'a,H:Hair> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<H> { impl<'a,'tcx> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<'tcx> {
fn nodes(&'a self) -> dot::Nodes<'a, BasicBlock> { fn nodes(&'a self) -> dot::Nodes<'a, BasicBlock> {
self.all_basic_blocks().into_cow() self.all_basic_blocks().into_cow()
} }

View file

@ -15,144 +15,78 @@
//! structures. //! structures.
use repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp}; use repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp};
use std::fmt::Debug; use rustc::middle::def_id::DefId;
use std::hash::Hash; 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 { // (*) #[derive(Clone, Debug)]
pub struct ItemRef<'tcx> {
// (*) the `Sized` and Debug` bounds are the only ones that really pub ty: Ty<'tcx>,
// make sense. The rest are just there so that we can pub def_id: DefId,
// `#[derive(Clone)]` on things that are parameterized over pub substs: &'tcx Substs<'tcx>,
// `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<Vec<u8>>
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<Self,Output=Pattern<Self>>; // e.g., &P<ast::Pat>
type Expr: Clone+Debug+Mirror<Self,Output=Expr<Self>>; // e.g., &P<ast::Expr>
type Stmt: Clone+Debug+Mirror<Self,Output=Stmt<Self>>; // e.g., &P<ast::Stmt>
type Block: Clone+Debug+Mirror<Self,Output=Block<Self>>; // e.g., &P<ast::Block>
type InlineAsm: Clone+Debug+Eq+Hash; // e.g., ast::InlineAsm
/// Normalizes `ast` into the appropriate `mirror` type.
fn mirror<M:Mirror<Self>>(&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<Self>;
/// Returns the type `bool`.
fn bool_ty(&mut self) -> Self::Ty;
/// Returns the literal for `true`
fn true_literal(&mut self) -> Literal<Self>;
/// Returns the literal for `false`
fn false_literal(&mut self) -> Literal<Self>;
/// Returns a reference to `PartialEq::<T,T>::eq`
fn partial_eq(&mut self, ty: Self::Ty) -> ItemRef<Self>;
/// Returns a reference to `PartialOrd::<T,T>::le`
fn partial_le(&mut self, ty: Self::Ty) -> ItemRef<Self>;
/// 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<Field<Self>>;
/// 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)] #[derive(Clone, Debug)]
pub struct ItemRef<H:Hair> { pub struct Block<'tcx> {
pub ty: H::Ty, pub extent: CodeExtent,
pub def_id: H::DefId, pub span: Span,
pub substs: H::Substs, pub stmts: Vec<StmtRef<'tcx>>,
pub expr: Option<ExprRef<'tcx>>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Block<H:Hair> { pub enum StmtRef<'tcx> {
pub extent: H::CodeExtent, Hair(&'tcx hir::Stmt),
pub span: H::Span, Mirror(Box<Stmt<'tcx>>),
pub stmts: Vec<StmtRef<H>>,
pub expr: Option<ExprRef<H>>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum StmtRef<H:Hair> { pub struct Stmt<'tcx> {
Hair(H::Stmt), pub span: Span,
Mirror(Box<Stmt<H>>), pub kind: StmtKind<'tcx>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Stmt<H:Hair> { pub enum StmtKind<'tcx> {
pub span: H::Span,
pub kind: StmtKind<H>,
}
#[derive(Clone, Debug)]
pub enum StmtKind<H:Hair> {
Expr { Expr {
/// scope for this statement; may be used as lifetime of temporaries /// scope for this statement; may be used as lifetime of temporaries
scope: H::CodeExtent, scope: CodeExtent,
/// expression being evaluated in this statement /// expression being evaluated in this statement
expr: ExprRef<H> expr: ExprRef<'tcx>
}, },
Let { Let {
/// scope for variables bound in this let; covers this and /// scope for variables bound in this let; covers this and
/// remaining statements in block /// remaining statements in block
remainder_scope: H::CodeExtent, remainder_scope: CodeExtent,
/// scope for the initialization itself; might be used as /// scope for the initialization itself; might be used as
/// lifetime of temporaries /// lifetime of temporaries
init_scope: H::CodeExtent, init_scope: CodeExtent,
/// let <PAT> = ... /// let <PAT> = ...
pattern: PatternRef<H>, pattern: PatternRef<'tcx>,
/// let pat = <INIT> ... /// let pat = <INIT> ...
initializer: Option<ExprRef<H>>, initializer: Option<ExprRef<'tcx>>,
/// let pat = init; <STMTS> /// let pat = init; <STMTS>
stmts: Vec<StmtRef<H>> stmts: Vec<StmtRef<'tcx>>
}, },
} }
// 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 // into instances of this `Expr` enum. This translation can be done
// basically as lazilly or as eagerly as desired: every recursive // basically as lazilly or as eagerly as desired: every recursive
// reference to an expression in this enum is an `ExprRef<H>`, 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 // 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 // shortlived. They are created by `Hair::to_expr`, analyzed and
// converted into MIR, and then discarded. // converted into MIR, and then discarded.
// //
@ -162,87 +96,88 @@ pub enum StmtKind<H:Hair> {
// example, method calls and overloaded operators are absent: they are // example, method calls and overloaded operators are absent: they are
// expected to be converted into `Expr::Call` instances. // expected to be converted into `Expr::Call` instances.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Expr<H:Hair> { pub struct Expr<'tcx> {
// type of this expression // type of this expression
pub ty: H::Ty, pub ty: Ty<'tcx>,
// lifetime of this expression if it should be spilled into a // lifetime of this expression if it should be spilled into a
// temporary; should be None only if in a constant context // temporary; should be None only if in a constant context
pub temp_lifetime: Option<H::CodeExtent>, pub temp_lifetime: Option<CodeExtent>,
// span of the expression in the source // span of the expression in the source
pub span: H::Span, pub span: Span,
// kind of expression // kind of expression
pub kind: ExprKind<H>, pub kind: ExprKind<'tcx>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ExprKind<H:Hair> { pub enum ExprKind<'tcx> {
Scope { extent: H::CodeExtent, value: ExprRef<H> }, Scope { extent: CodeExtent, value: ExprRef<'tcx> },
Box { value: ExprRef<H> }, Box { value: ExprRef<'tcx> },
Call { fun: ExprRef<H>, args: Vec<ExprRef<H>> }, Call { fun: ExprRef<'tcx>, args: Vec<ExprRef<'tcx>> },
Deref { arg: ExprRef<H> }, // NOT overloaded! Deref { arg: ExprRef<'tcx> }, // NOT overloaded!
Binary { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> }, // NOT overloaded! Binary { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, // NOT overloaded!
LogicalOp { op: LogicalOp, lhs: ExprRef<H>, rhs: ExprRef<H> }, LogicalOp { op: LogicalOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
Unary { op: UnOp, arg: ExprRef<H> }, // NOT overloaded! Unary { op: UnOp, arg: ExprRef<'tcx> }, // NOT overloaded!
Cast { source: ExprRef<H> }, Cast { source: ExprRef<'tcx> },
ReifyFnPointer { source: ExprRef<H> }, ReifyFnPointer { source: ExprRef<'tcx> },
UnsafeFnPointer { source: ExprRef<H> }, UnsafeFnPointer { source: ExprRef<'tcx> },
Unsize { source: ExprRef<H> }, Unsize { source: ExprRef<'tcx> },
If { condition: ExprRef<H>, then: ExprRef<H>, otherwise: Option<ExprRef<H>> }, If { condition: ExprRef<'tcx>, then: ExprRef<'tcx>, otherwise: Option<ExprRef<'tcx>> },
Loop { condition: Option<ExprRef<H>>, body: ExprRef<H>, }, Loop { condition: Option<ExprRef<'tcx>>, body: ExprRef<'tcx>, },
Match { discriminant: ExprRef<H>, arms: Vec<Arm<H>> }, Match { discriminant: ExprRef<'tcx>, arms: Vec<Arm<'tcx>> },
Block { body: H::Block }, Block { body: &'tcx hir::Block },
Assign { lhs: ExprRef<H>, rhs: ExprRef<H> }, Assign { lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
AssignOp { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> }, AssignOp { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
Field { lhs: ExprRef<H>, name: Field<H> }, Field { lhs: ExprRef<'tcx>, name: Field },
Index { lhs: ExprRef<H>, index: ExprRef<H> }, Index { lhs: ExprRef<'tcx>, index: ExprRef<'tcx> },
VarRef { id: H::VarId }, VarRef { id: ast::NodeId },
SelfRef, // first argument, used for self in a closure SelfRef, // first argument, used for self in a closure
StaticRef { id: H::DefId }, StaticRef { id: DefId },
Borrow { region: H::Region, borrow_kind: BorrowKind, arg: ExprRef<H> }, Borrow { region: Region, borrow_kind: BorrowKind, arg: ExprRef<'tcx> },
Break { label: Option<H::CodeExtent> }, Break { label: Option<CodeExtent> },
Continue { label: Option<H::CodeExtent> }, Continue { label: Option<CodeExtent> },
Return { value: Option<ExprRef<H>> }, Return { value: Option<ExprRef<'tcx>> },
Repeat { value: ExprRef<H>, count: ExprRef<H> }, Repeat { value: ExprRef<'tcx>, count: ExprRef<'tcx> },
Vec { fields: Vec<ExprRef<H>> }, Vec { fields: Vec<ExprRef<'tcx>> },
Tuple { fields: Vec<ExprRef<H>> }, Tuple { fields: Vec<ExprRef<'tcx>> },
Adt { adt_def: H::AdtDef, Adt { adt_def: AdtDef<'tcx>,
variant_index: usize, variant_index: usize,
substs: H::Substs, substs: &'tcx Substs<'tcx>,
fields: Vec<FieldExprRef<H>>, fields: Vec<FieldExprRef<'tcx>>,
base: Option<ExprRef<H>> }, base: Option<ExprRef<'tcx>> },
Closure { closure_id: H::DefId, substs: H::ClosureSubsts, Closure { closure_id: DefId,
upvars: Vec<ExprRef<H>> }, substs: &'tcx ClosureSubsts<'tcx>,
Literal { literal: Literal<H> }, upvars: Vec<ExprRef<'tcx>> },
InlineAsm { asm: H::InlineAsm }, Literal { literal: Literal<'tcx> },
InlineAsm { asm: &'tcx hir::InlineAsm },
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ExprRef<H:Hair> { pub enum ExprRef<'tcx> {
Hair(H::Expr), Hair(&'tcx hir::Expr),
Mirror(Box<Expr<H>>), Mirror(Box<Expr<'tcx>>),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FieldExprRef<H:Hair> { pub struct FieldExprRef<'tcx> {
pub name: Field<H>, pub name: Field,
pub expr: ExprRef<H>, pub expr: ExprRef<'tcx>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Arm<H:Hair> { pub struct Arm<'tcx> {
pub patterns: Vec<PatternRef<H>>, pub patterns: Vec<PatternRef<'tcx>>,
pub guard: Option<ExprRef<H>>, pub guard: Option<ExprRef<'tcx>>,
pub body: ExprRef<H>, pub body: ExprRef<'tcx>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Pattern<H:Hair> { pub struct Pattern<'tcx> {
pub ty: H::Ty, pub ty: Ty<'tcx>,
pub span: H::Span, pub span: Span,
pub kind: PatternKind<H>, pub kind: PatternKind<'tcx>,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -252,89 +187,93 @@ pub enum LogicalOp {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PatternKind<H:Hair> { pub enum PatternKind<'tcx> {
Wild, Wild,
// x, ref x, x @ P, etc // x, ref x, x @ P, etc
Binding { mutability: Mutability, Binding { mutability: Mutability,
name: H::Name, name: ast::Name,
mode: BindingMode<H>, mode: BindingMode,
var: H::VarId, var: ast::NodeId,
ty: H::Ty, ty: Ty<'tcx>,
subpattern: Option<PatternRef<H>> }, subpattern: Option<PatternRef<'tcx>> },
// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants // 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<FieldPatternRef<H>> }, Variant { adt_def: AdtDef<'tcx>,
variant_index: usize,
subpatterns: Vec<FieldPatternRef<'tcx>> },
// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
Leaf { subpatterns: Vec<FieldPatternRef<H>> }, Leaf { subpatterns: Vec<FieldPatternRef<'tcx>> },
Deref { subpattern: PatternRef<H> }, // box P, &P, &mut P, etc Deref { subpattern: PatternRef<'tcx> }, // box P, &P, &mut P, etc
Constant { value: Literal<H> }, Constant { value: Literal<'tcx> },
Range { lo: Literal<H>, hi: Literal<H> }, Range { lo: Literal<'tcx>, hi: Literal<'tcx> },
// matches against a slice, checking the length and extracting elements // matches against a slice, checking the length and extracting elements
Slice { prefix: Vec<PatternRef<H>>, Slice { prefix: Vec<PatternRef<'tcx>>,
slice: Option<PatternRef<H>>, slice: Option<PatternRef<'tcx>>,
suffix: Vec<PatternRef<H>> }, suffix: Vec<PatternRef<'tcx>> },
// fixed match against an array, irrefutable // fixed match against an array, irrefutable
Array { prefix: Vec<PatternRef<H>>, Array { prefix: Vec<PatternRef<'tcx>>,
slice: Option<PatternRef<H>>, slice: Option<PatternRef<'tcx>>,
suffix: Vec<PatternRef<H>> }, suffix: Vec<PatternRef<'tcx>> },
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum BindingMode<H:Hair> { pub enum BindingMode {
ByValue, ByValue,
ByRef(H::Region, BorrowKind), ByRef(Region, BorrowKind),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PatternRef<H:Hair> { pub enum PatternRef<'tcx> {
Hair(H::Pattern), Hair(PatNode<'tcx>),
Mirror(Box<Pattern<H>>), Mirror(Box<Pattern<'tcx>>),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FieldPatternRef<H:Hair> { pub struct FieldPatternRef<'tcx> {
pub field: Field<H>, pub field: Field,
pub pattern: PatternRef<H>, pub pattern: PatternRef<'tcx>,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// The Mirror trait // The Mirror trait
/// "Mirroring" is the process of converting from a Hair type into one /// "Mirroring" is the process of converting from a HIR type into one
/// of the types in this file. For example, the mirror of a `H::Expr` /// of the HAIR types defined in this file. This is basically a "on
/// is an `Expr<H>`. Mirroring is the point at which the actual IR is /// the fly" desugaring step that hides a lot of the messiness in the
/// converting into the more idealized representation described in /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
/// this file. Mirroring is gradual: when you mirror an outer /// `Expr<'tcx>`.
/// expression like `e1 + e2`, the references to the inner expressions ///
/// `e1` and `e2` are `ExprRef<H>` instances, and they may or may not /// Mirroring is gradual: when you mirror an outer expression like `e1
/// be eagerly mirrored. This allows a single AST node from the /// + e2`, the references to the inner expressions `e1` and `e2` are
/// compiler to expand into one or more Hair nodes, which lets the Hair /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
/// nodes be simpler. /// mirrored. This allows a single AST node from the compiler to
pub trait Mirror<H:Hair> { /// expand into one or more Hair nodes, which lets the Hair nodes be
/// simpler.
pub trait Mirror<'tcx> {
type Output; type Output;
fn make_mirror(self, hir: &mut H) -> Self::Output; fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Self::Output;
} }
impl<H:Hair> Mirror<H> for Expr<H> { impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
type Output = Expr<H>; type Output = Expr<'tcx>;
fn make_mirror(self, _: &mut H) -> Expr<H> { fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
self self
} }
} }
impl<H:Hair> Mirror<H> for ExprRef<H> { impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
type Output = Expr<H>; type Output = Expr<'tcx>;
fn make_mirror(self, hir: &mut H) -> Expr<H> { fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
match self { match self {
ExprRef::Hair(h) => h.make_mirror(hir), ExprRef::Hair(h) => h.make_mirror(hir),
ExprRef::Mirror(m) => *m, ExprRef::Mirror(m) => *m,
@ -342,18 +281,18 @@ impl<H:Hair> Mirror<H> for ExprRef<H> {
} }
} }
impl<H:Hair> Mirror<H> for Stmt<H> { impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
type Output = Stmt<H>; type Output = Stmt<'tcx>;
fn make_mirror(self, _: &mut H) -> Stmt<H> { fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
self self
} }
} }
impl<H:Hair> Mirror<H> for StmtRef<H> { impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
type Output = Stmt<H>; type Output = Stmt<'tcx>;
fn make_mirror(self, hir: &mut H) -> Stmt<H> { fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
match self { match self {
StmtRef::Hair(h) => h.make_mirror(hir), StmtRef::Hair(h) => h.make_mirror(hir),
StmtRef::Mirror(m) => *m, StmtRef::Mirror(m) => *m,
@ -361,18 +300,18 @@ impl<H:Hair> Mirror<H> for StmtRef<H> {
} }
} }
impl<H:Hair> Mirror<H> for Pattern<H> { impl<'tcx> Mirror<'tcx> for Pattern<'tcx> {
type Output = Pattern<H>; type Output = Pattern<'tcx>;
fn make_mirror(self, _: &mut H) -> Pattern<H> { fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
self self
} }
} }
impl<H:Hair> Mirror<H> for PatternRef<H> { impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> {
type Output = Pattern<H>; type Output = Pattern<'tcx>;
fn make_mirror(self, hir: &mut H) -> Pattern<H> { fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
match self { match self {
PatternRef::Hair(h) => h.make_mirror(hir), PatternRef::Hair(h) => h.make_mirror(hir),
PatternRef::Mirror(m) => *m, PatternRef::Mirror(m) => *m,
@ -380,10 +319,10 @@ impl<H:Hair> Mirror<H> for PatternRef<H> {
} }
} }
impl<H:Hair> Mirror<H> for Block<H> { impl<'tcx> Mirror<'tcx> for Block<'tcx> {
type Output = Block<H>; type Output = Block<'tcx>;
fn make_mirror(self, _: &mut H) -> Block<H> { fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Block<'tcx> {
self self
} }
} }

View file

@ -24,10 +24,13 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
#[macro_use] extern crate log; #[macro_use] extern crate log;
extern crate graphviz as dot; extern crate graphviz as dot;
extern crate rustc;
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate rustc_front;
extern crate syntax;
pub mod build; pub mod build;
pub mod dump; pub mod mir_map;
pub mod hair; pub mod hair;
pub mod repr; pub mod repr;
mod graphviz; mod graphviz;

View file

@ -30,43 +30,43 @@ use self::rustc::middle::infer;
use self::rustc::middle::region::CodeExtentData; use self::rustc::middle::region::CodeExtentData;
use self::rustc::middle::ty::{self, Ty}; use self::rustc::middle::ty::{self, Ty};
use self::rustc::util::common::ErrorReported; use self::rustc::util::common::ErrorReported;
use self::rustc::util::nodemap::NodeMap;
use self::rustc_front::hir; use self::rustc_front::hir;
use self::rustc_front::visit; use self::rustc_front::visit;
use self::syntax::ast; use self::syntax::ast;
use self::syntax::attr::AttrMetaMethods; use self::syntax::attr::AttrMetaMethods;
use self::syntax::codemap::Span; use self::syntax::codemap::Span;
pub fn dump_crate(tcx: &ty::ctxt) { pub type MirMap<'tcx> = NodeMap<Mir<'tcx>>;
let mut dump = OuterDump { tcx: tcx };
pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'tcx>{
let mut map = NodeMap();
{
let mut dump = OuterDump { tcx: tcx, map: &mut map };
visit::walk_crate(&mut dump, tcx.map.krate()); visit::walk_crate(&mut dump, tcx.map.krate());
} }
map
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// OuterDump -- walks a crate, looking for fn items and methods to build MIR from // OuterDump -- walks a crate, looking for fn items and methods to build MIR from
struct OuterDump<'a,'tcx:'a> { struct OuterDump<'a,'tcx:'a> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
map: &'a mut MirMap<'tcx>,
} }
impl<'a, 'tcx> OuterDump<'a, 'tcx> { impl<'a, 'tcx> OuterDump<'a, 'tcx> {
fn visit_mir<OP>(&self, attributes: &'tcx [ast::Attribute], mut walk_op: OP) fn visit_mir<OP>(&mut self, attributes: &'a [ast::Attribute], mut walk_op: OP)
where OP: FnMut(&mut InnerDump<'a,'tcx>) where OP: for<'m> FnMut(&mut InnerDump<'a,'m,'tcx>)
{ {
let mut built_mir = false; let mut closure_dump = InnerDump { tcx: self.tcx, attr: None, map: &mut *self.map };
for attr in attributes { for attr in attributes {
if attr.check_name("rustc_mir") { if attr.check_name("rustc_mir") {
let mut closure_dump = InnerDump { tcx: self.tcx, attr: Some(attr) }; closure_dump.attr = Some(attr);
}
}
walk_op(&mut closure_dump); walk_op(&mut closure_dump);
built_mir = true;
}
}
let always_build_mir = true;
if !built_mir && always_build_mir {
let mut closure_dump = InnerDump { tcx: self.tcx, attr: None };
walk_op(&mut closure_dump);
}
} }
} }
@ -82,25 +82,47 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
hir::MethodTraitItem(_, Some(_)) => { hir::MethodTraitItem(_, Some(_)) => {
self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item)); self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item));
} }
_ => { } hir::MethodTraitItem(_, None) |
hir::ConstTraitItem(..) |
hir::TypeTraitItem(..) => {
}
} }
visit::walk_trait_item(self, trait_item); visit::walk_trait_item(self, trait_item);
} }
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
match impl_item.node {
hir::MethodImplItem(..) => {
self.visit_mir(&impl_item.attrs, |c| visit::walk_impl_item(c, impl_item));
}
hir::ConstImplItem(..) | hir::TypeImplItem(..) => { }
}
visit::walk_impl_item(self, impl_item);
}
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// InnerDump -- dumps MIR for a single fn and its contained closures // InnerDump -- dumps MIR for a single fn and its contained closures
struct InnerDump<'a,'tcx:'a> { struct InnerDump<'a,'m,'tcx:'a+'m> {
tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
map: &'m mut MirMap<'tcx>,
attr: Option<&'a ast::Attribute>, attr: Option<&'a ast::Attribute>,
} }
impl<'a, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'tcx> { impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
fn visit_item(&mut self, _: &'tcx hir::Item) { fn visit_item(&mut self, _: &'tcx hir::Item) {
// ignore nested items; they need their own graphviz annotation // ignore nested items; they need their own graphviz annotation
} }
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {
// ignore nested items; they need their own graphviz annotation
}
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {
// ignore nested items; they need their own graphviz annotation
}
fn visit_fn(&mut self, fn visit_fn(&mut self,
fk: visit::FnKind<'tcx>, fk: visit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
@ -155,6 +177,9 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'tcx> {
} }
} }
} }
let previous = self.map.insert(id, mir);
assert!(previous.is_none());
} }
Err(ErrorReported) => { } Err(ErrorReported) => { }
} }
@ -169,18 +194,18 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
span: Span, span: Span,
decl: &'tcx hir::FnDecl, decl: &'tcx hir::FnDecl,
body: &'tcx hir::Block) body: &'tcx hir::Block)
-> Result<Mir<Cx<'a,'tcx>>, ErrorReported> { -> Result<Mir<'tcx>, ErrorReported> {
let arguments = let arguments =
decl.inputs decl.inputs
.iter() .iter()
.map(|arg| { .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)) (ty, PatNode::irrefutable(&arg.pat))
}) })
.collect(); .collect();
let parameter_scope = 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 }); CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
Ok(build::construct(cx, Ok(build::construct(cx,
span, span,

View file

@ -8,22 +8,29 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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_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::fmt::{Debug, Formatter, Error};
use std::slice; use std::slice;
use std::u32; use std::u32;
/// Lowered representation of a single function. /// Lowered representation of a single function.
pub struct Mir<H:Hair> { pub struct Mir<'tcx> {
pub basic_blocks: Vec<BasicBlockData<H>>, pub basic_blocks: Vec<BasicBlockData<'tcx>>,
// for every node id // for every node id
pub extents: FnvHashMap<H::CodeExtent, Vec<GraphExtent>>, pub extents: FnvHashMap<CodeExtent, Vec<GraphExtent>>,
pub var_decls: Vec<VarDecl<H>>, pub var_decls: Vec<VarDecl<'tcx>>,
pub arg_decls: Vec<ArgDecl<H>>, pub arg_decls: Vec<ArgDecl<'tcx>>,
pub temp_decls: Vec<TempDecl<H>>, pub temp_decls: Vec<TempDecl<'tcx>>,
} }
/// where execution begins /// where execution begins
@ -35,18 +42,18 @@ pub const END_BLOCK: BasicBlock = BasicBlock(1);
/// where execution ends, on panic /// where execution ends, on panic
pub const DIVERGE_BLOCK: BasicBlock = BasicBlock(2); pub const DIVERGE_BLOCK: BasicBlock = BasicBlock(2);
impl<H:Hair> Mir<H> { impl<'tcx> Mir<'tcx> {
pub fn all_basic_blocks(&self) -> Vec<BasicBlock> { pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
(0..self.basic_blocks.len()) (0..self.basic_blocks.len())
.map(|i| BasicBlock::new(i)) .map(|i| BasicBlock::new(i))
.collect() .collect()
} }
pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<H> { pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[bb.index()] &self.basic_blocks[bb.index()]
} }
pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<H> { pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> {
&mut self.basic_blocks[bb.index()] &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 // A "variable" is a binding declared by the user as part of the fn
// decl, a let, etc. // decl, a let, etc.
pub struct VarDecl<H:Hair> { pub struct VarDecl<'tcx> {
pub mutability: Mutability, pub mutability: Mutability,
pub name: H::Name, pub name: Name,
pub ty: H::Ty, pub ty: Ty<'tcx>,
} }
// A "temp" is a temporary that we place on the stack. They are // A "temp" is a temporary that we place on the stack. They are
// anonymous, always mutable, and have only a type. // anonymous, always mutable, and have only a type.
pub struct TempDecl<H:Hair> { pub struct TempDecl<'tcx> {
pub ty: H::Ty, pub ty: Ty<'tcx>,
} }
// A "arg" is one of the function's formal arguments. These are // A "arg" is one of the function's formal arguments. These are
@ -134,8 +141,8 @@ pub struct TempDecl<H:Hair> {
// //
// there is only one argument, of type `(i32, u32)`, but two bindings // there is only one argument, of type `(i32, u32)`, but two bindings
// (`x` and `y`). // (`x` and `y`).
pub struct ArgDecl<H:Hair> { pub struct ArgDecl<'tcx> {
pub ty: H::Ty, pub ty: Ty<'tcx>,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -212,12 +219,12 @@ impl Debug for BasicBlock {
// BasicBlock and Terminator // BasicBlock and Terminator
#[derive(Debug)] #[derive(Debug)]
pub struct BasicBlockData<H:Hair> { pub struct BasicBlockData<'tcx> {
pub statements: Vec<Statement<H>>, pub statements: Vec<Statement<'tcx>>,
pub terminator: Terminator<H>, pub terminator: Terminator<'tcx>,
} }
pub enum Terminator<H:Hair> { pub enum Terminator<'tcx> {
/// block should have one successor in the graph; we jump there /// block should have one successor in the graph; we jump there
Goto { target: BasicBlock }, Goto { target: BasicBlock },
@ -226,10 +233,10 @@ pub enum Terminator<H:Hair> {
Panic { target: BasicBlock }, Panic { target: BasicBlock },
/// jump to branch 0 if this lvalue evaluates to true /// jump to branch 0 if this lvalue evaluates to true
If { cond: Operand<H>, targets: [BasicBlock; 2] }, If { cond: Operand<'tcx>, targets: [BasicBlock; 2] },
/// lvalue evaluates to some enum; jump depending on the branch /// lvalue evaluates to some enum; jump depending on the branch
Switch { discr: Lvalue<H>, targets: Vec<BasicBlock> }, Switch { discr: Lvalue<'tcx>, targets: Vec<BasicBlock> },
/// Indicates that the last statement in the block panics, aborts, /// Indicates that the last statement in the block panics, aborts,
/// etc. No successors. This terminator appears on exactly one /// etc. No successors. This terminator appears on exactly one
@ -247,10 +254,10 @@ pub enum Terminator<H:Hair> {
/// block ends with a call; it should have two successors. The /// block ends with a call; it should have two successors. The
/// first successor indicates normal return. The second indicates /// first successor indicates normal return. The second indicates
/// unwinding. /// unwinding.
Call { data: CallData<H>, targets: [BasicBlock; 2] }, Call { data: CallData<'tcx>, targets: [BasicBlock; 2] },
} }
impl<H:Hair> Terminator<H> { impl<'tcx> Terminator<'tcx> {
pub fn successors(&self) -> &[BasicBlock] { pub fn successors(&self) -> &[BasicBlock] {
use self::Terminator::*; use self::Terminator::*;
match *self { match *self {
@ -266,19 +273,19 @@ impl<H:Hair> Terminator<H> {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct CallData<H:Hair> { pub struct CallData<'tcx> {
/// where the return value is written to /// where the return value is written to
pub destination: Lvalue<H>, pub destination: Lvalue<'tcx>,
/// the fn being called /// the fn being called
pub func: Lvalue<H>, pub func: Lvalue<'tcx>,
/// the arguments /// the arguments
pub args: Vec<Lvalue<H>>, pub args: Vec<Lvalue<'tcx>>,
} }
impl<H:Hair> BasicBlockData<H> { impl<'tcx> BasicBlockData<'tcx> {
pub fn new(terminator: Terminator<H>) -> BasicBlockData<H> { pub fn new(terminator: Terminator<'tcx>) -> BasicBlockData<'tcx> {
BasicBlockData { BasicBlockData {
statements: vec![], statements: vec![],
terminator: terminator, terminator: terminator,
@ -286,7 +293,7 @@ impl<H:Hair> BasicBlockData<H> {
} }
} }
impl<H:Hair> Debug for Terminator<H> { impl<'tcx> Debug for Terminator<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::Terminator::*; use self::Terminator::*;
match *self { match *self {
@ -318,15 +325,15 @@ impl<H:Hair> Debug for Terminator<H> {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Statements // Statements
pub struct Statement<H:Hair> { pub struct Statement<'tcx> {
pub span: H::Span, pub span: Span,
pub kind: StatementKind<H>, pub kind: StatementKind<'tcx>,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum StatementKind<H:Hair> { pub enum StatementKind<'tcx> {
Assign(Lvalue<H>, Rvalue<H>), Assign(Lvalue<'tcx>, Rvalue<'tcx>),
Drop(DropKind, Lvalue<H>), Drop(DropKind, Lvalue<'tcx>),
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -335,7 +342,7 @@ pub enum DropKind {
Deep Deep
} }
impl<H:Hair> Debug for Statement<H> { impl<'tcx> Debug for Statement<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::StatementKind::*; use self::StatementKind::*;
match self.kind { match self.kind {
@ -351,7 +358,7 @@ impl<H:Hair> Debug for Statement<H> {
/// A path to a value; something that can be evaluated without /// A path to a value; something that can be evaluated without
/// changing or disturbing program state. /// changing or disturbing program state.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum Lvalue<H:Hair> { pub enum Lvalue<'tcx> {
/// local variable declared by the user /// local variable declared by the user
Var(u32), Var(u32),
@ -363,13 +370,13 @@ pub enum Lvalue<H:Hair> {
Arg(u32), Arg(u32),
/// static or static mut variable /// static or static mut variable
Static(H::DefId), Static(DefId),
/// the return pointer of the fn /// the return pointer of the fn
ReturnPointer, ReturnPointer,
/// projection out of an lvalue (access a field, deref a pointer, etc) /// projection out of an lvalue (access a field, deref a pointer, etc)
Projection(Box<LvalueProjection<H>>) Projection(Box<LvalueProjection<'tcx>>)
} }
/// The `Projection` data structure defines things of the form `B.x` /// The `Projection` data structure defines things of the form `B.x`
@ -377,15 +384,15 @@ pub enum Lvalue<H:Hair> {
/// shared between `Constant` and `Lvalue`. See the aliases /// shared between `Constant` and `Lvalue`. See the aliases
/// `LvalueProjection` etc below. /// `LvalueProjection` etc below.
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Projection<H:Hair,B,V> { pub struct Projection<'tcx,B,V> {
pub base: B, pub base: B,
pub elem: ProjectionElem<H,V>, pub elem: ProjectionElem<'tcx,V>,
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum ProjectionElem<H:Hair,V> { pub enum ProjectionElem<'tcx,V> {
Deref, Deref,
Field(Field<H>), Field(Field),
Index(V), Index(V),
// These indices are generated by slice patterns. Easiest to explain // These indices are generated by slice patterns. Easiest to explain
@ -406,44 +413,44 @@ pub enum ProjectionElem<H:Hair,V> {
// "Downcast" to a variant of an ADT. Currently, we only introduce // "Downcast" to a variant of an ADT. Currently, we only introduce
// this for ADTs with more than one variant. It may be better to // this for ADTs with more than one variant. It may be better to
// just introduce it always, or always for enums. // 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 /// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is an operand. /// and the index is an operand.
pub type LvalueProjection<H> = pub type LvalueProjection<'tcx> =
Projection<H,Lvalue<H>,Operand<H>>; Projection<'tcx,Lvalue<'tcx>,Operand<'tcx>>;
/// Alias for projections as they appear in lvalues, where the base is an lvalue /// Alias for projections as they appear in lvalues, where the base is an lvalue
/// and the index is an operand. /// and the index is an operand.
pub type LvalueElem<H> = pub type LvalueElem<'tcx> =
ProjectionElem<H,Operand<H>>; ProjectionElem<'tcx,Operand<'tcx>>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Field<H:Hair> { pub enum Field {
Named(H::Name), Named(Name),
Indexed(usize), Indexed(usize),
} }
impl<H:Hair> Lvalue<H> { impl<'tcx> Lvalue<'tcx> {
pub fn field(self, f: Field<H>) -> Lvalue<H> { pub fn field(self, f: Field) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Field(f)) self.elem(ProjectionElem::Field(f))
} }
pub fn deref(self) -> Lvalue<H> { pub fn deref(self) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Deref) self.elem(ProjectionElem::Deref)
} }
pub fn index(self, index: Operand<H>) -> Lvalue<H> { pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> {
self.elem(ProjectionElem::Index(index)) self.elem(ProjectionElem::Index(index))
} }
pub fn elem(self, elem: LvalueElem<H>) -> Lvalue<H> { pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> {
Lvalue::Projection(Box::new(LvalueProjection { base: self, elem: elem })) Lvalue::Projection(Box::new(LvalueProjection { base: self, elem: elem }))
} }
} }
impl<H:Hair> Debug for Lvalue<H> { impl<'tcx> Debug for Lvalue<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::Lvalue::*; use self::Lvalue::*;
@ -487,12 +494,12 @@ impl<H:Hair> Debug for Lvalue<H> {
// being nested in one another. // being nested in one another.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum Operand<H:Hair> { pub enum Operand<'tcx> {
Consume(Lvalue<H>), Consume(Lvalue<'tcx>),
Constant(Constant<H>), Constant(Constant<'tcx>),
} }
impl<H:Hair> Debug for Operand<H> { impl<'tcx> Debug for Operand<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::Operand::*; use self::Operand::*;
match *self { match *self {
@ -506,34 +513,34 @@ impl<H:Hair> Debug for Operand<H> {
// Rvalues // Rvalues
#[derive(Clone)] #[derive(Clone)]
pub enum Rvalue<H:Hair> { pub enum Rvalue<'tcx> {
// x (either a move or copy, depending on type of x) // x (either a move or copy, depending on type of x)
Use(Operand<H>), Use(Operand<'tcx>),
// [x; 32] // [x; 32]
Repeat(Operand<H>, Operand<H>), Repeat(Operand<'tcx>, Operand<'tcx>),
// &x or &mut x // &x or &mut x
Ref(H::Region, BorrowKind, Lvalue<H>), Ref(Region, BorrowKind, Lvalue<'tcx>),
// length of a [X] or [X;n] value // length of a [X] or [X;n] value
Len(Lvalue<H>), Len(Lvalue<'tcx>),
Cast(CastKind, Operand<H>, H::Ty), Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
BinaryOp(BinOp, Operand<H>, Operand<H>), BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
UnaryOp(UnOp, Operand<H>), UnaryOp(UnOp, Operand<'tcx>),
// Creates an *uninitialized* Box // Creates an *uninitialized* Box
Box(H::Ty), Box(Ty<'tcx>),
// Create an aggregate value, like a tuple or struct. This is // Create an aggregate value, like a tuple or struct. This is
// only needed because we want to distinguish `dest = Foo { x: // only needed because we want to distinguish `dest = Foo { x:
// ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case // ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
// that `Foo` has a destructor. These rvalues can be optimized // that `Foo` has a destructor. These rvalues can be optimized
// away after type-checking and before lowering. // away after type-checking and before lowering.
Aggregate(AggregateKind<H>, Vec<Operand<H>>), Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
// Generates a slice of the form `&input[from_start..L-from_end]` // 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 // where `L` is the length of the slice. This is only created by
@ -541,12 +548,12 @@ pub enum Rvalue<H:Hair> {
// .., z]` might create a slice with `from_start=2` and // .., z]` might create a slice with `from_start=2` and
// `from_end=1`. // `from_end=1`.
Slice { Slice {
input: Lvalue<H>, input: Lvalue<'tcx>,
from_start: usize, from_start: usize,
from_end: usize, from_end: usize,
}, },
InlineAsm(H::InlineAsm), InlineAsm(&'tcx InlineAsm),
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
@ -568,11 +575,11 @@ pub enum CastKind {
} }
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum AggregateKind<H:Hair> { pub enum AggregateKind<'tcx> {
Vec, Vec,
Tuple, Tuple,
Adt(H::AdtDef, usize, H::Substs), Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>),
Closure(H::DefId, H::ClosureSubsts), Closure(DefId, &'tcx ClosureSubsts<'tcx>),
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -619,7 +626,7 @@ pub enum UnOp {
Neg Neg
} }
impl<H:Hair> Debug for Rvalue<H> { impl<'tcx> Debug for Rvalue<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
use self::Rvalue::*; use self::Rvalue::*;
@ -648,15 +655,15 @@ impl<H:Hair> Debug for Rvalue<H> {
// particular one must be wary of `NaN`! // particular one must be wary of `NaN`!
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Constant<H:Hair> { pub struct Constant<'tcx> {
pub span: H::Span, pub span: Span,
pub ty: H::Ty, pub ty: Ty<'tcx>,
pub literal: Literal<H> pub literal: Literal<'tcx>
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Literal<H:Hair> { pub enum Literal<'tcx> {
Item { def_id: H::DefId, substs: H::Substs }, Item { def_id: DefId, substs: &'tcx Substs<'tcx> },
Value { value: H::ConstVal }, Value { value: ConstVal },
} }

View file

@ -12,16 +12,16 @@ use hair::*;
use tcx::Cx; use tcx::Cx;
use tcx::pattern::PatNode; 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 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<Cx<'a,'tcx>> for &'tcx hir::Block { impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
type Output = Block<Cx<'a,'tcx>>; type Output = Block<'tcx>;
fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Block<Cx<'a,'tcx>> { fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Block<'tcx> {
// We have to eagerly translate the "spine" of the statements // We have to eagerly translate the "spine" of the statements
// in order to get the lexical scoping correctly. // in order to get the lexical scoping correctly.
let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate()); let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate());
@ -34,10 +34,10 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Block {
} }
} }
impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Stmt { impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt {
type Output = Stmt<Cx<'a,'tcx>>; type Output = Stmt<'tcx>;
fn make_mirror(self, _cx: &mut Cx<'a,'tcx>) -> Stmt<Cx<'a,'tcx>> { fn make_mirror<'a>(self, _cx: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
// In order to get the scoping correct, we eagerly mirror // In order to get the scoping correct, we eagerly mirror
// statements when we translate the enclosing block, so we // statements when we translate the enclosing block, so we
// should in fact never get to this point. // should in fact never get to this point.
@ -48,7 +48,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Stmt {
fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>, fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
block_id: ast::NodeId, block_id: ast::NodeId,
mut stmts: STMTS) mut stmts: STMTS)
-> Vec<StmtRef<Cx<'a,'tcx>>> -> Vec<StmtRef<'tcx>>
where STMTS: Iterator<Item=(usize, &'tcx P<hir::Stmt>)> where STMTS: Iterator<Item=(usize, &'tcx P<hir::Stmt>)>
{ {
let mut result = vec![]; 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>, pub fn to_expr_ref<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
block: &'tcx hir::Block) block: &'tcx hir::Block)
-> ExprRef<Cx<'a, 'tcx>> { -> ExprRef<'tcx> {
let block_ty = cx.tcx.node_id_to_type(block.id); let block_ty = cx.tcx.node_id_to_type(block.id);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
let expr = Expr { let expr = Expr {

View file

@ -15,22 +15,22 @@ use std::rc::Rc;
use tcx::Cx; use tcx::Cx;
use tcx::block; use tcx::block;
use tcx::pattern::PatNode; 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 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<Cx<'a,'tcx>> for &'tcx hir::Expr { impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
type Output = Expr<Cx<'a,'tcx>>; type Output = Expr<'tcx>;
fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> { fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)! let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)!
@ -427,7 +427,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &hir::Expr, expr: &hir::Expr,
method_call: ty::MethodCall) method_call: ty::MethodCall)
-> Expr<Cx<'a,'tcx>> { -> Expr<'tcx> {
let tables = cx.tcx.tables.borrow(); let tables = cx.tcx.tables.borrow();
let callee = &tables.method_map[&method_call]; let callee = &tables.method_map[&method_call];
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); 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<Cx<'a,'tcx>> { fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
let map = if arm.pats.len() == 1 { let map = if arm.pats.len() == 1 {
None None
} else { } else {
@ -469,7 +469,7 @@ fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<Cx<'a,'
fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>, fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &'tcx hir::Expr) expr: &'tcx hir::Expr)
-> ExprKind<Cx<'a,'tcx>> -> ExprKind<'tcx>
{ {
let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs); 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() { 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>, fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &'tcx hir::Expr, expr: &'tcx hir::Expr,
def: def::Def) def: def::Def)
-> ExprKind<Cx<'a,'tcx>> -> ExprKind<'tcx>
{ {
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); 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, expr: &'tcx hir::Expr,
method_call: ty::MethodCall, method_call: ty::MethodCall,
pass_args: PassArgs, pass_args: PassArgs,
receiver: ExprRef<Cx<'a,'tcx>>, receiver: ExprRef<'tcx>,
args: Vec<&'tcx P<hir::Expr>>) args: Vec<&'tcx P<hir::Expr>>)
-> ExprKind<Cx<'a,'tcx>> -> ExprKind<'tcx>
{ {
// the receiver has all the adjustments that are needed, so we can // the receiver has all the adjustments that are needed, so we can
// just push a reference to it // 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, expr: &'tcx hir::Expr,
method_call: ty::MethodCall, method_call: ty::MethodCall,
pass_args: PassArgs, pass_args: PassArgs,
receiver: ExprRef<Cx<'a,'tcx>>, receiver: ExprRef<'tcx>,
args: Vec<&'tcx P<hir::Expr>>) args: Vec<&'tcx P<hir::Expr>>)
-> ExprKind<Cx<'a,'tcx>> -> ExprKind<'tcx>
{ {
// For an overloaded *x or x[y] expression of type T, the method // 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 // 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, closure_expr: &'tcx hir::Expr,
freevar: &ty::Freevar, freevar: &ty::Freevar,
freevar_ty: Ty<'tcx>) freevar_ty: Ty<'tcx>)
-> ExprRef<Cx<'a,'tcx>> { -> ExprRef<'tcx> {
let id_var = freevar.def.var_id(); let id_var = freevar.def.var_id();
let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.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(); let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap();

View file

@ -8,31 +8,28 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // 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 hair::*;
use repr::*; 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 rustc::middle::const_eval::ConstVal;
use self::rustc::middle::def_id::DefId; use rustc::middle::def_id::DefId;
use self::rustc::middle::infer::InferCtxt; use rustc::middle::infer::InferCtxt;
use self::rustc::middle::region::CodeExtent; use rustc::middle::subst::{Subst, Substs};
use self::rustc::middle::subst::{self, Subst, Substs}; use rustc::middle::ty::{self, Ty};
use self::rustc::middle::ty::{self, Ty}; use syntax::codemap::Span;
use self::rustc_front::hir; use syntax::parse::token::{self, special_idents};
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;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Cx<'a,'tcx:'a> { pub struct Cx<'a,'tcx:'a> {
pub tcx: &'a ty::ctxt<'tcx>, tcx: &'a ty::ctxt<'tcx>,
pub infcx: &'a InferCtxt<'a,'tcx>, infcx: &'a InferCtxt<'a,'tcx>,
} }
impl<'a,'tcx> Cx<'a,'tcx> { impl<'a,'tcx> Cx<'a,'tcx> {
@ -43,66 +40,51 @@ impl<'a,'tcx> Cx<'a,'tcx> {
pub use self::pattern::PatNode; pub use self::pattern::PatNode;
impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> { impl<'a,'tcx:'a> Cx<'a, 'tcx> {
type VarId = ast::NodeId; /// Normalizes `ast` into the appropriate `mirror` type.
type DefId = DefId; pub fn mirror<M:Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
type AdtDef = ty::AdtDef<'tcx>; ast.make_mirror(self)
type Name = ast::Name; }
type InternedString = InternedString;
type Bytes = Rc<Vec<u8>>;
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;
fn unit_ty(&mut self) -> Ty<'tcx> { pub fn unit_ty(&mut self) -> Ty<'tcx> {
self.tcx.mk_nil() self.tcx.mk_nil()
} }
fn usize_ty(&mut self) -> Ty<'tcx> { pub fn usize_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.usize self.tcx.types.usize
} }
fn usize_literal(&mut self, value: usize) -> Literal<Self> { pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Uint(value as u64) } 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 self.tcx.types.bool
} }
fn true_literal(&mut self) -> Literal<Self> { pub fn true_literal(&mut self) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Bool(true) } Literal::Value { value: ConstVal::Bool(true) }
} }
fn false_literal(&mut self) -> Literal<Self> { pub fn false_literal(&mut self) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Bool(false) } Literal::Value { value: ConstVal::Bool(false) }
} }
fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<Self> { pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
let eq_def_id = self.tcx.lang_items.eq_trait().unwrap(); let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
self.cmp_method_ref(eq_def_id, "eq", ty) self.cmp_method_ref(eq_def_id, "eq", ty)
} }
fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<Self> { pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
let ord_def_id = self.tcx.lang_items.ord_trait().unwrap(); let ord_def_id = self.tcx.lang_items.ord_trait().unwrap();
self.cmp_method_ref(ord_def_id, "le", ty) 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() adt_def.variants.len()
} }
fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field<Self>> { pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> {
adt_def.variants[variant_index] adt_def.variants[variant_index]
.fields .fields
.iter() .iter()
@ -117,7 +99,7 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
.collect() .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) { if self.infcx.type_moves_by_default(ty, span) {
// FIXME(#21859) we should do an add'l check here to determine if // FIXME(#21859) we should do an add'l check here to determine if
// any dtor will execute, but the relevant fn // any dtor will execute, but the relevant fn
@ -130,17 +112,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) self.tcx.sess.span_bug(span, message)
} }
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
self.tcx
} }
impl<'a,'tcx:'a> Cx<'a,'tcx> {
fn cmp_method_ref(&mut self, fn cmp_method_ref(&mut self,
trait_def_id: DefId, trait_def_id: DefId,
method_name: &str, method_name: &str,
arg_ty: Ty<'tcx>) arg_ty: Ty<'tcx>)
-> ItemRef<Cx<'a,'tcx>> { -> ItemRef<'tcx> {
let method_name = token::intern(method_name); let method_name = token::intern(method_name);
let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty); let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
for trait_item in self.tcx.trait_items(trait_def_id).iter() { for trait_item in self.tcx.trait_items(trait_def_id).iter() {
@ -167,29 +151,6 @@ impl<'a,'tcx:'a> Cx<'a,'tcx> {
} }
} }
// We only need this impl so that we do deriving for things that are
// defined relative to the `Hair` trait. See `Hair` trait for more
// details.
impl<'a,'tcx> PartialEq for Cx<'a,'tcx> {
fn eq(&self, _: &Cx<'a,'tcx>) -> bool {
panic!("Cx should never ACTUALLY be compared for equality")
}
}
impl<'a,'tcx> Eq for Cx<'a,'tcx> { }
impl<'a,'tcx> Hash for Cx<'a,'tcx> {
fn hash<H: Hasher>(&self, _: &mut H) {
panic!("Cx should never ACTUALLY be hashed")
}
}
impl<'a,'tcx> Debug for Cx<'a,'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "Tcx")
}
}
mod block; mod block;
mod expr; mod expr;
mod pattern; mod pattern;

View file

@ -14,15 +14,15 @@ use repr::*;
use rustc_data_structures::fnv::FnvHashMap; use rustc_data_structures::fnv::FnvHashMap;
use std::rc::Rc; use std::rc::Rc;
use tcx::Cx; 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 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 /// When there are multiple patterns in a single arm, each one has its
/// own node-ids for the bindings. References to the variables always /// own node-ids for the bindings. References to the variables always
@ -58,15 +58,15 @@ impl<'tcx> PatNode<'tcx> {
PatNode::new(pat, None) PatNode::new(pat, None)
} }
fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<Cx<'a,'tcx>> { fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> {
PatNode::new(pat, self.binding_map.clone()).to_ref() PatNode::new(pat, self.binding_map.clone()).to_ref()
} }
fn pat_refs<'a>(&self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<PatternRef<Cx<'a,'tcx>>> { fn pat_refs<'a>(&self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<PatternRef<'tcx>> {
pats.iter().map(|p| self.pat_ref(p)).collect() pats.iter().map(|p| self.pat_ref(p)).collect()
} }
fn opt_pat_ref<'a>(&self, pat: &'tcx Option<P<hir::Pat>>) -> Option<PatternRef<Cx<'a,'tcx>>> { fn opt_pat_ref<'a>(&self, pat: &'tcx Option<P<hir::Pat>>) -> Option<PatternRef<'tcx>> {
pat.as_ref().map(|p| self.pat_ref(p)) pat.as_ref().map(|p| self.pat_ref(p))
} }
@ -76,7 +76,7 @@ impl<'tcx> PatNode<'tcx> {
prefix: &'tcx Vec<P<hir::Pat>>, prefix: &'tcx Vec<P<hir::Pat>>,
slice: &'tcx Option<P<hir::Pat>>, slice: &'tcx Option<P<hir::Pat>>,
suffix: &'tcx Vec<P<hir::Pat>>) suffix: &'tcx Vec<P<hir::Pat>>)
-> PatternKind<Cx<'a,'tcx>> -> PatternKind<'tcx>
{ {
match ty.sty { match ty.sty {
ty::TySlice(..) => ty::TySlice(..) =>
@ -107,8 +107,8 @@ impl<'tcx> PatNode<'tcx> {
fn variant_or_leaf<'a>(&self, fn variant_or_leaf<'a>(&self,
cx: &mut Cx<'a, 'tcx>, cx: &mut Cx<'a, 'tcx>,
subpatterns: Vec<FieldPatternRef<Cx<'a,'tcx>>>) subpatterns: Vec<FieldPatternRef<'tcx>>)
-> PatternKind<Cx<'a,'tcx>> -> PatternKind<'tcx>
{ {
let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def(); let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
match def { match def {
@ -138,10 +138,10 @@ impl<'tcx> PatNode<'tcx> {
} }
} }
impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> { impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
type Output = Pattern<Cx<'a,'tcx>>; type Output = Pattern<'tcx>;
fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Pattern<Cx<'a,'tcx>> { fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
let kind = match self.pat.node { let kind = match self.pat.node {
hir::PatWild(..) => hir::PatWild(..) =>
PatternKind::Wild, PatternKind::Wild,

View file

@ -11,58 +11,57 @@
use hair::*; use hair::*;
use repr::*; use repr::*;
use tcx::Cx;
use tcx::pattern::PatNode; use tcx::pattern::PatNode;
use tcx::rustc_front::hir; use rustc_front::hir;
use tcx::syntax::ptr::P; use syntax::ptr::P;
pub trait ToRef<H> { pub trait ToRef {
type Output; type Output;
fn to_ref(self) -> Self::Output; fn to_ref(self) -> Self::Output;
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx hir::Expr { impl<'a,'tcx:'a> ToRef for &'tcx hir::Expr {
type Output = ExprRef<Cx<'a,'tcx>>; type Output = ExprRef<'tcx>;
fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> { fn to_ref(self) -> ExprRef<'tcx> {
ExprRef::Hair(self) ExprRef::Hair(self)
} }
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx P<hir::Expr> { impl<'a,'tcx:'a> ToRef for &'tcx P<hir::Expr> {
type Output = ExprRef<Cx<'a,'tcx>>; type Output = ExprRef<'tcx>;
fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> { fn to_ref(self) -> ExprRef<'tcx> {
ExprRef::Hair(&**self) ExprRef::Hair(&**self)
} }
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for Expr<Cx<'a,'tcx>> { impl<'a,'tcx:'a> ToRef for Expr<'tcx> {
type Output = ExprRef<Cx<'a,'tcx>>; type Output = ExprRef<'tcx>;
fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> { fn to_ref(self) -> ExprRef<'tcx> {
ExprRef::Mirror(Box::new(self)) ExprRef::Mirror(Box::new(self))
} }
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for PatNode<'tcx> { impl<'a,'tcx:'a> ToRef for PatNode<'tcx> {
type Output = PatternRef<Cx<'a,'tcx>>; type Output = PatternRef<'tcx>;
fn to_ref(self) -> PatternRef<Cx<'a,'tcx>> { fn to_ref(self) -> PatternRef<'tcx> {
PatternRef::Hair(self) PatternRef::Hair(self)
} }
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for Pattern<Cx<'a,'tcx>> { impl<'a,'tcx:'a> ToRef for Pattern<'tcx> {
type Output = PatternRef<Cx<'a,'tcx>>; type Output = PatternRef<'tcx>;
fn to_ref(self) -> PatternRef<Cx<'a,'tcx>> { fn to_ref(self) -> PatternRef<'tcx> {
PatternRef::Mirror(Box::new(self)) PatternRef::Mirror(Box::new(self))
} }
} }
impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Option<T> impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option<T>
where &'tcx T: ToRef<Cx<'a,'tcx>, Output=U> where &'tcx T: ToRef<Output=U>
{ {
type Output = Option<U>; type Output = Option<U>;
@ -71,8 +70,8 @@ impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Option<T>
} }
} }
impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Vec<T> impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec<T>
where &'tcx T: ToRef<Cx<'a,'tcx>, Output=U> where &'tcx T: ToRef<Output=U>
{ {
type Output = Vec<U>; type Output = Vec<U>;
@ -81,10 +80,10 @@ impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Vec<T>
} }
} }
impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx hir::Field { impl<'a,'tcx:'a> ToRef for &'tcx hir::Field {
type Output = FieldExprRef<Cx<'a,'tcx>>; type Output = FieldExprRef<'tcx>;
fn to_ref(self) -> FieldExprRef<Cx<'a,'tcx>> { fn to_ref(self) -> FieldExprRef<'tcx> {
FieldExprRef { FieldExprRef {
name: Field::Named(self.name.node), name: Field::Named(self.name.node),
expr: self.expr.to_ref() expr: self.expr.to_ref()