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
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
include $(CFG_SRC_DIR)mk/platform.mk

View File

@ -101,7 +101,6 @@ pub struct Options {
pub parse_only: bool,
pub no_trans: bool,
pub treat_err_as_bug: bool,
pub always_build_mir: bool,
pub no_analysis: bool,
pub debugging_opts: DebuggingOptions,
pub prints: Vec<PrintRequest>,
@ -211,7 +210,6 @@ pub fn basic_options() -> Options {
parse_only: false,
no_trans: false,
treat_err_as_bug: false,
always_build_mir: false,
no_analysis: false,
debugging_opts: basic_debugging_options(),
prints: Vec::new(),
@ -578,8 +576,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"Run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool,
"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,
"Parse and expand the source, but run no analysis"),
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 no_trans = debugging_opts.no_trans;
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;
if debugging_opts.debug_llvm {
@ -1049,7 +1044,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
parse_only: parse_only,
no_trans: no_trans,
treat_err_as_bug: treat_err_as_bug,
always_build_mir: always_build_mir,
no_analysis: no_analysis,
debugging_opts: debugging_opts,
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", ||
middle::check_match::check_crate(tcx));
let _mir_map =
time(time_passes, "MIR dump", ||
mir::dump::dump_crate(tcx));
mir::mir_map::build_mir_for_crate(tcx));
time(time_passes, "liveness checking", ||
middle::liveness::check_crate(tcx));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,11 +14,11 @@ use hair::*;
use repr::*;
use std::u32;
impl<H:Hair> Builder<H> {
impl<'a,'tcx> Builder<'a,'tcx> {
pub fn field_match_pairs(&mut self,
lvalue: Lvalue<H>,
subpatterns: Vec<FieldPatternRef<H>>)
-> Vec<MatchPair<H>> {
lvalue: Lvalue<'tcx>,
subpatterns: Vec<FieldPatternRef<'tcx>>)
-> Vec<MatchPair<'tcx>> {
subpatterns.into_iter()
.map(|fieldpat| {
let lvalue = lvalue.clone().field(fieldpat.field);
@ -27,7 +27,8 @@ impl<H:Hair> Builder<H> {
.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);
MatchPair::new(lvalue, pattern)
}
@ -47,12 +48,12 @@ impl<H:Hair> Builder<H> {
///
/// and creates a match pair `tmp0 @ s`
pub fn prefix_suffix_slice(&mut self,
match_pairs: &mut Vec<MatchPair<H>>,
match_pairs: &mut Vec<MatchPair<'tcx>>,
block: BasicBlock,
lvalue: Lvalue<H>,
prefix: Vec<PatternRef<H>>,
opt_slice: Option<PatternRef<H>>,
suffix: Vec<PatternRef<H>>)
lvalue: Lvalue<'tcx>,
prefix: Vec<PatternRef<'tcx>>,
opt_slice: Option<PatternRef<'tcx>>,
suffix: Vec<PatternRef<'tcx>>)
-> BlockAnd<()>
{
// 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.
fn prefix_suffix(&mut self,
match_pairs: &mut Vec<MatchPair<H>>,
lvalue: Lvalue<H>,
prefix: Vec<PatternRef<H>>,
suffix: Vec<PatternRef<H>>)
match_pairs: &mut Vec<MatchPair<'tcx>>,
lvalue: Lvalue<'tcx>,
prefix: Vec<PatternRef<'tcx>>,
suffix: Vec<PatternRef<'tcx>>)
{
let min_length = prefix.len() + suffix.len();
assert!(min_length < u32::MAX as usize);
@ -118,8 +119,8 @@ impl<H:Hair> Builder<H> {
}
}
impl<H:Hair> MatchPair<H> {
pub fn new(lvalue: Lvalue<H>, pattern: Pattern<H>) -> MatchPair<H> {
impl<'tcx> MatchPair<'tcx> {
pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> {
MatchPair { lvalue: lvalue, pattern: pattern }
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,43 +30,43 @@ use self::rustc::middle::infer;
use self::rustc::middle::region::CodeExtentData;
use self::rustc::middle::ty::{self, Ty};
use self::rustc::util::common::ErrorReported;
use self::rustc::util::nodemap::NodeMap;
use self::rustc_front::hir;
use self::rustc_front::visit;
use self::syntax::ast;
use self::syntax::attr::AttrMetaMethods;
use self::syntax::codemap::Span;
pub fn dump_crate(tcx: &ty::ctxt) {
let mut dump = OuterDump { tcx: tcx };
pub type MirMap<'tcx> = NodeMap<Mir<'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());
}
map
}
///////////////////////////////////////////////////////////////////////////
// OuterDump -- walks a crate, looking for fn items and methods to build MIR from
struct OuterDump<'a,'tcx:'a> {
tcx: &'a ty::ctxt<'tcx>,
map: &'a mut MirMap<'tcx>,
}
impl<'a, 'tcx> OuterDump<'a, 'tcx> {
fn visit_mir<OP>(&self, attributes: &'tcx [ast::Attribute], mut walk_op: OP)
where OP: FnMut(&mut InnerDump<'a,'tcx>)
fn visit_mir<OP>(&mut self, attributes: &'a [ast::Attribute], mut walk_op: OP)
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 {
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);
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(_)) => {
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);
}
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
struct InnerDump<'a,'tcx:'a> {
struct InnerDump<'a,'m,'tcx:'a+'m> {
tcx: &'a ty::ctxt<'tcx>,
map: &'m mut MirMap<'tcx>,
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) {
// 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,
fk: visit::FnKind<'tcx>,
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) => { }
}
@ -169,18 +194,18 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
span: Span,
decl: &'tcx hir::FnDecl,
body: &'tcx hir::Block)
-> Result<Mir<Cx<'a,'tcx>>, ErrorReported> {
-> Result<Mir<'tcx>, ErrorReported> {
let arguments =
decl.inputs
.iter()
.map(|arg| {
let ty = cx.tcx.node_id_to_type(arg.id);
let ty = cx.tcx().node_id_to_type(arg.id);
(ty, PatNode::irrefutable(&arg.pat))
})
.collect();
let parameter_scope =
cx.tcx.region_maps.lookup_code_extent(
cx.tcx().region_maps.lookup_code_extent(
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
Ok(build::construct(cx,
span,

View File

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

View File

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

View File

@ -15,22 +15,22 @@ use std::rc::Rc;
use tcx::Cx;
use tcx::block;
use tcx::pattern::PatNode;
use tcx::rustc::front::map;
use tcx::rustc::middle::const_eval;
use tcx::rustc::middle::def;
use tcx::rustc::middle::region::CodeExtent;
use tcx::rustc::middle::pat_util;
use tcx::rustc::middle::ty::{self, Ty};
use tcx::rustc_front::hir;
use tcx::rustc_front::util as hir_util;
use tcx::syntax::parse::token;
use tcx::syntax::ptr::P;
use tcx::to_ref::ToRef;
use rustc::front::map;
use rustc::middle::const_eval;
use rustc::middle::def;
use rustc::middle::region::CodeExtent;
use rustc::middle::pat_util;
use rustc::middle::ty::{self, Ty};
use rustc_front::hir;
use rustc_front::util as hir_util;
use syntax::parse::token;
use syntax::ptr::P;
impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
type Output = Expr<Cx<'a,'tcx>>;
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
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);
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>,
expr: &hir::Expr,
method_call: ty::MethodCall)
-> Expr<Cx<'a,'tcx>> {
-> Expr<'tcx> {
let tables = cx.tcx.tables.borrow();
let callee = &tables.method_map[&method_call];
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
@ -451,7 +451,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
}
}
fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<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 {
None
} 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>,
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);
match cx.tcx.def_map.borrow()[&expr.id].full_def() {
@ -502,7 +502,7 @@ fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &'tcx hir::Expr,
def: def::Def)
-> ExprKind<Cx<'a,'tcx>>
-> ExprKind<'tcx>
{
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
@ -665,9 +665,9 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &'tcx hir::Expr,
method_call: ty::MethodCall,
pass_args: PassArgs,
receiver: ExprRef<Cx<'a,'tcx>>,
receiver: ExprRef<'tcx>,
args: Vec<&'tcx P<hir::Expr>>)
-> ExprKind<Cx<'a,'tcx>>
-> ExprKind<'tcx>
{
// the receiver has all the adjustments that are needed, so we can
// just push a reference to it
@ -718,9 +718,9 @@ fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
expr: &'tcx hir::Expr,
method_call: ty::MethodCall,
pass_args: PassArgs,
receiver: ExprRef<Cx<'a,'tcx>>,
receiver: ExprRef<'tcx>,
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
// call returns an &T and we must add the deref so that the types
@ -754,7 +754,7 @@ fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
closure_expr: &'tcx hir::Expr,
freevar: &ty::Freevar,
freevar_ty: Ty<'tcx>)
-> ExprRef<Cx<'a,'tcx>> {
-> ExprRef<'tcx> {
let id_var = freevar.def.var_id();
let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id };
let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap();

View File

@ -8,31 +8,28 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
* This module contains the code to convert from the wacky tcx data
* structures into the hair. The `builder` is generally ignorant of
* the tcx etc, and instead goes through the `Cx` for most of its
* work.
*/
use hair::*;
use repr::*;
use std::fmt::{Debug, Formatter, Error};
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use self::rustc::middle::const_eval::ConstVal;
use self::rustc::middle::def_id::DefId;
use self::rustc::middle::infer::InferCtxt;
use self::rustc::middle::region::CodeExtent;
use self::rustc::middle::subst::{self, Subst, Substs};
use self::rustc::middle::ty::{self, Ty};
use self::rustc_front::hir;
use self::syntax::ast;
use self::syntax::codemap::Span;
use self::syntax::parse::token::{self, special_idents, InternedString};
extern crate rustc;
extern crate rustc_front;
extern crate syntax;
use rustc::middle::const_eval::ConstVal;
use rustc::middle::def_id::DefId;
use rustc::middle::infer::InferCtxt;
use rustc::middle::subst::{Subst, Substs};
use rustc::middle::ty::{self, Ty};
use syntax::codemap::Span;
use syntax::parse::token::{self, special_idents};
#[derive(Copy, Clone)]
pub struct Cx<'a,'tcx:'a> {
pub tcx: &'a ty::ctxt<'tcx>,
pub infcx: &'a InferCtxt<'a,'tcx>,
tcx: &'a ty::ctxt<'tcx>,
infcx: &'a InferCtxt<'a,'tcx>,
}
impl<'a,'tcx> Cx<'a,'tcx> {
@ -43,66 +40,51 @@ impl<'a,'tcx> Cx<'a,'tcx> {
pub use self::pattern::PatNode;
impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
type VarId = ast::NodeId;
type DefId = DefId;
type AdtDef = ty::AdtDef<'tcx>;
type Name = ast::Name;
type InternedString = InternedString;
type Bytes = Rc<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;
impl<'a,'tcx:'a> Cx<'a, 'tcx> {
/// Normalizes `ast` into the appropriate `mirror` type.
pub fn mirror<M:Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
ast.make_mirror(self)
}
fn unit_ty(&mut self) -> Ty<'tcx> {
pub fn unit_ty(&mut self) -> Ty<'tcx> {
self.tcx.mk_nil()
}
fn usize_ty(&mut self) -> Ty<'tcx> {
pub fn usize_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.usize
}
fn usize_literal(&mut self, value: usize) -> Literal<Self> {
pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> {
Literal::Value { value: ConstVal::Uint(value as u64) }
}
fn bool_ty(&mut self) -> Ty<'tcx> {
pub fn bool_ty(&mut self) -> Ty<'tcx> {
self.tcx.types.bool
}
fn true_literal(&mut self) -> Literal<Self> {
pub fn true_literal(&mut self) -> Literal<'tcx> {
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) }
}
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();
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();
self.cmp_method_ref(ord_def_id, "le", ty)
}
fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
adt_def.variants.len()
}
fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field<Self>> {
pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> {
adt_def.variants[variant_index]
.fields
.iter()
@ -117,7 +99,7 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
.collect()
}
fn needs_drop(&mut self, ty: Ty<'tcx>, span: Self::Span) -> bool {
pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool {
if self.infcx.type_moves_by_default(ty, span) {
// FIXME(#21859) we should do an add'l check here to determine if
// any dtor will execute, but the relevant fn
@ -130,17 +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)
}
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
self.tcx
}
impl<'a,'tcx:'a> Cx<'a,'tcx> {
fn cmp_method_ref(&mut self,
trait_def_id: DefId,
method_name: &str,
arg_ty: Ty<'tcx>)
-> ItemRef<Cx<'a,'tcx>> {
-> ItemRef<'tcx> {
let method_name = token::intern(method_name);
let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
for trait_item in self.tcx.trait_items(trait_def_id).iter() {
@ -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 expr;
mod pattern;

View File

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

View File

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