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:
commit
a63b0f045d
31 changed files with 671 additions and 736 deletions
12
mk/main.mk
12
mk/main.mk
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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(..) => {
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
|
@ -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 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue