Auto merge of #28884 - Ms2ger:fmt-mir, r=nikomatsakis
This commit contains some of the changes proposed by a rustfmt invocation, chosen based on the fairly non-deterministic metric of how much I liked the change. I expect we will run rustfmt on this crate again later, probably accepting more of its changes. For now, this is already an improvement over the status-quo.
This commit is contained in:
commit
e50298f7b5
@ -29,7 +29,7 @@ impl<'tcx> CFG<'tcx> {
|
||||
pub fn end_point(&self, block: BasicBlock) -> ExecutionPoint {
|
||||
ExecutionPoint {
|
||||
block: block,
|
||||
statement: self.block_data(block).statements.len() as u32
|
||||
statement: self.block_data(block).statements.len() as u32,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
//! See docs in build/expr/mod.rs
|
||||
|
||||
use build::{Builder};
|
||||
use build::Builder;
|
||||
use hair::*;
|
||||
use repr::*;
|
||||
|
||||
|
@ -30,18 +30,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
fn expr_as_lvalue(&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: Expr<'tcx>)
|
||||
-> BlockAnd<Lvalue<'tcx>>
|
||||
{
|
||||
debug!("expr_as_lvalue(block={:?}, expr={:?})",
|
||||
block, expr);
|
||||
-> BlockAnd<Lvalue<'tcx>> {
|
||||
debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr);
|
||||
|
||||
let this = self;
|
||||
let expr_span = expr.span;
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| {
|
||||
this.as_lvalue(block, value)
|
||||
})
|
||||
this.in_scope(extent, block, |this| this.as_lvalue(block, value))
|
||||
}
|
||||
ExprKind::Field { lhs, name } => {
|
||||
let lvalue = unpack!(block = this.as_lvalue(block, lhs));
|
||||
@ -69,12 +65,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
idx.clone(),
|
||||
Operand::Consume(len)));
|
||||
|
||||
let (success, failure) = (this.cfg.start_new_block(),
|
||||
this.cfg.start_new_block());
|
||||
let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
|
||||
this.cfg.terminate(block,
|
||||
Terminator::If {
|
||||
cond: Operand::Consume(lt),
|
||||
targets: [success, failure]
|
||||
targets: [success, failure],
|
||||
});
|
||||
this.panic(failure);
|
||||
success.and(slice.index(idx))
|
||||
|
@ -20,11 +20,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// If `expr` is an lvalue like `x`, this will introduce a
|
||||
/// temporary `tmp = x`, so that we capture the value of `x` at
|
||||
/// this time.
|
||||
pub fn as_operand<M>(&mut self,
|
||||
block: BasicBlock,
|
||||
expr: M)
|
||||
-> BlockAnd<Operand<'tcx>>
|
||||
where M: Mirror<'tcx, Output=Expr<'tcx>>
|
||||
pub fn as_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
|
||||
where M: Mirror<'tcx, Output = Expr<'tcx>>
|
||||
{
|
||||
let expr = self.hir.mirror(expr);
|
||||
self.expr_as_operand(block, expr)
|
||||
@ -33,16 +30,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
fn expr_as_operand(&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: Expr<'tcx>)
|
||||
-> BlockAnd<Operand<'tcx>>
|
||||
{
|
||||
debug!("expr_as_operand(block={:?}, expr={:?})",
|
||||
block, expr);
|
||||
-> BlockAnd<Operand<'tcx>> {
|
||||
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
|
||||
let this = self;
|
||||
|
||||
if let ExprKind::Scope { extent, value } = expr.kind {
|
||||
return this.in_scope(extent, block, |this| {
|
||||
this.as_operand(block, value)
|
||||
});
|
||||
return this.in_scope(extent, block, |this| this.as_operand(block, value));
|
||||
}
|
||||
|
||||
let category = Category::of(&expr.kind).unwrap();
|
||||
|
@ -19,11 +19,8 @@ use repr::*;
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// Compile `expr`, yielding an rvalue.
|
||||
pub fn as_rvalue<M>(&mut self,
|
||||
block: BasicBlock,
|
||||
expr: M)
|
||||
-> BlockAnd<Rvalue<'tcx>>
|
||||
where M: Mirror<'tcx, Output=Expr<'tcx>>
|
||||
pub fn as_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
|
||||
where M: Mirror<'tcx, Output = Expr<'tcx>>
|
||||
{
|
||||
let expr = self.hir.mirror(expr);
|
||||
self.expr_as_rvalue(block, expr)
|
||||
@ -32,19 +29,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
fn expr_as_rvalue(&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: Expr<'tcx>)
|
||||
-> BlockAnd<Rvalue<'tcx>>
|
||||
{
|
||||
debug!("expr_as_rvalue(block={:?}, expr={:?})",
|
||||
block, expr);
|
||||
-> BlockAnd<Rvalue<'tcx>> {
|
||||
debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
|
||||
|
||||
let this = self;
|
||||
let expr_span = expr.span;
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| {
|
||||
this.as_rvalue(block, value)
|
||||
})
|
||||
this.in_scope(extent, block, |this| this.as_rvalue(block, value))
|
||||
}
|
||||
ExprKind::InlineAsm { asm } => {
|
||||
block.and(Rvalue::InlineAsm(asm))
|
||||
@ -162,11 +155,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
|
||||
.collect();
|
||||
|
||||
let field_names =
|
||||
this.hir.fields(adt_def, variant_index);
|
||||
let field_names = this.hir.fields(adt_def, variant_index);
|
||||
|
||||
let base =
|
||||
base.map(|base| unpack!(block = this.as_lvalue(block, base)));
|
||||
let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));
|
||||
|
||||
// for the actual values we use, take either the
|
||||
// expr the user specified or, if they didn't
|
||||
|
@ -18,29 +18,19 @@ use repr::*;
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// Compile `expr` into a fresh temporary. This is used when building
|
||||
/// up rvalues so as to freeze the value that will be consumed.
|
||||
pub fn as_temp<M>(&mut self,
|
||||
block: BasicBlock,
|
||||
expr: M)
|
||||
-> BlockAnd<Lvalue<'tcx>>
|
||||
where M: Mirror<'tcx, Output=Expr<'tcx>>
|
||||
pub fn as_temp<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Lvalue<'tcx>>
|
||||
where M: Mirror<'tcx, Output = Expr<'tcx>>
|
||||
{
|
||||
let expr = self.hir.mirror(expr);
|
||||
self.expr_as_temp(block, expr)
|
||||
}
|
||||
|
||||
fn expr_as_temp(&mut self,
|
||||
mut block: BasicBlock,
|
||||
expr: Expr<'tcx>)
|
||||
-> BlockAnd<Lvalue<'tcx>>
|
||||
{
|
||||
debug!("expr_as_temp(block={:?}, expr={:?})",
|
||||
block, expr);
|
||||
fn expr_as_temp(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<Lvalue<'tcx>> {
|
||||
debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
|
||||
let this = self;
|
||||
|
||||
if let ExprKind::Scope { extent, value } = expr.kind {
|
||||
return this.in_scope(extent, block, |this| {
|
||||
this.as_temp(block, value)
|
||||
});
|
||||
return this.in_scope(extent, block, |this| this.as_temp(block, value));
|
||||
}
|
||||
|
||||
let expr_ty = expr.ty.clone();
|
||||
@ -48,9 +38,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let temp_lifetime = match expr.temp_lifetime {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
this.hir.span_bug(
|
||||
expr.span,
|
||||
&format!("no temp_lifetime for expr"));
|
||||
this.hir.span_bug(expr.span, &format!("no temp_lifetime for expr"));
|
||||
}
|
||||
};
|
||||
this.schedule_drop(expr.span, temp_lifetime, DropKind::Deep, &temp, expr_ty);
|
||||
|
@ -38,9 +38,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
match expr.kind {
|
||||
ExprKind::Scope { extent, value } => {
|
||||
this.in_scope(extent, block, |this| {
|
||||
this.into(destination, block, value)
|
||||
})
|
||||
this.in_scope(extent, block, |this| this.into(destination, block, value))
|
||||
}
|
||||
ExprKind::Block { body: ast_block } => {
|
||||
this.ast_block(destination, block, ast_block)
|
||||
@ -204,8 +202,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|loop_scope| loop_scope.continue_block)
|
||||
}
|
||||
ExprKind::Break { label } => {
|
||||
this.break_or_continue(expr_span, label, block,
|
||||
|loop_scope| loop_scope.break_block)
|
||||
this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
|
||||
}
|
||||
ExprKind::Return { value } => {
|
||||
unpack!(block = this.into(&Lvalue::ReturnPointer, block, value));
|
||||
@ -226,9 +223,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
data: CallData {
|
||||
destination: destination.clone(),
|
||||
func: fun,
|
||||
args: args
|
||||
args: args,
|
||||
},
|
||||
targets: [success, panic]
|
||||
targets: [success, panic],
|
||||
});
|
||||
success.unit()
|
||||
}
|
||||
|
@ -19,8 +19,11 @@ use hair::*;
|
||||
use repr::*;
|
||||
|
||||
pub trait EvalInto<'tcx> {
|
||||
fn eval_into<'a>(self, builder: &mut Builder<'a,'tcx>, destination: &Lvalue<'tcx>,
|
||||
block: BasicBlock) -> BlockAnd<()>;
|
||||
fn eval_into<'a>(self,
|
||||
builder: &mut Builder<'a, 'tcx>,
|
||||
destination: &Lvalue<'tcx>,
|
||||
block: BasicBlock)
|
||||
-> BlockAnd<()>;
|
||||
}
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
@ -37,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
|
||||
fn eval_into<'a>(self,
|
||||
builder: &mut Builder<'a,'tcx>,
|
||||
builder: &mut Builder<'a, 'tcx>,
|
||||
destination: &Lvalue<'tcx>,
|
||||
block: BasicBlock)
|
||||
-> BlockAnd<()> {
|
||||
@ -48,7 +51,7 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
|
||||
|
||||
impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
|
||||
fn eval_into<'a>(self,
|
||||
builder: &mut Builder<'a,'tcx>,
|
||||
builder: &mut Builder<'a, 'tcx>,
|
||||
destination: &Lvalue<'tcx>,
|
||||
block: BasicBlock)
|
||||
-> BlockAnd<()> {
|
||||
@ -58,13 +61,13 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
|
||||
|
||||
impl<'tcx> EvalInto<'tcx> for Option<ExprRef<'tcx>> {
|
||||
fn eval_into<'a>(self,
|
||||
builder: &mut Builder<'a,'tcx>,
|
||||
builder: &mut Builder<'a, 'tcx>,
|
||||
destination: &Lvalue<'tcx>,
|
||||
block: BasicBlock)
|
||||
-> BlockAnd<()> {
|
||||
match self {
|
||||
Some(expr) => builder.into(destination, block, expr),
|
||||
None => block.unit()
|
||||
None => block.unit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,10 +33,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
mut block: BasicBlock,
|
||||
discriminant: ExprRef<'tcx>,
|
||||
arms: Vec<Arm<'tcx>>)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
let discriminant_lvalue =
|
||||
unpack!(block = self.as_lvalue(block, discriminant));
|
||||
-> BlockAnd<()> {
|
||||
let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
|
||||
|
||||
// Before we do anything, create uninitialized variables with
|
||||
// suitable extent for all of the bindings in this match. It's
|
||||
@ -101,11 +99,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
pub fn expr_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
var_extent: CodeExtent, // lifetime of vars
|
||||
var_extent: CodeExtent, // lifetime of vars
|
||||
irrefutable_pat: PatternRef<'tcx>,
|
||||
initializer: ExprRef<'tcx>)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
-> BlockAnd<()> {
|
||||
// optimize the case of `let x = ...`
|
||||
let irrefutable_pat = self.hir.mirror(irrefutable_pat);
|
||||
match irrefutable_pat.kind {
|
||||
@ -115,16 +112,22 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
var,
|
||||
ty,
|
||||
subpattern: None } => {
|
||||
let index = self.declare_binding(var_extent, mutability, name,
|
||||
var, ty, irrefutable_pat.span);
|
||||
let index = self.declare_binding(var_extent,
|
||||
mutability,
|
||||
name,
|
||||
var,
|
||||
ty,
|
||||
irrefutable_pat.span);
|
||||
let lvalue = Lvalue::Var(index);
|
||||
return self.into(&lvalue, block, initializer);
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
let lvalue = unpack!(block = self.as_lvalue(block, initializer));
|
||||
self.lvalue_into_pattern(block, var_extent,
|
||||
PatternRef::Mirror(Box::new(irrefutable_pat)), &lvalue)
|
||||
self.lvalue_into_pattern(block,
|
||||
var_extent,
|
||||
PatternRef::Mirror(Box::new(irrefutable_pat)),
|
||||
&lvalue)
|
||||
}
|
||||
|
||||
pub fn lvalue_into_pattern(&mut self,
|
||||
@ -132,8 +135,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
var_extent: CodeExtent,
|
||||
irrefutable_pat: PatternRef<'tcx>,
|
||||
initializer: &Lvalue<'tcx>)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
-> BlockAnd<()> {
|
||||
// first, creating the bindings
|
||||
self.declare_bindings(var_extent, irrefutable_pat.clone());
|
||||
|
||||
@ -150,10 +152,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
unpack!(block = self.simplify_candidate(block, &mut candidate));
|
||||
|
||||
if !candidate.match_pairs.is_empty() {
|
||||
self.hir.span_bug(
|
||||
candidate.match_pairs[0].pattern.span,
|
||||
&format!("match pairs {:?} remaining after simplifying irrefutable pattern",
|
||||
candidate.match_pairs));
|
||||
self.hir.span_bug(candidate.match_pairs[0].pattern.span,
|
||||
&format!("match pairs {:?} remaining after simplifying \
|
||||
irrefutable pattern",
|
||||
candidate.match_pairs));
|
||||
}
|
||||
|
||||
// now apply the bindings, which will also declare the variables
|
||||
@ -162,10 +164,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
block.unit()
|
||||
}
|
||||
|
||||
pub fn declare_bindings(&mut self,
|
||||
var_extent: CodeExtent,
|
||||
pattern: PatternRef<'tcx>)
|
||||
{
|
||||
pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: PatternRef<'tcx>) {
|
||||
let pattern = self.hir.mirror(pattern);
|
||||
match pattern.kind {
|
||||
PatternKind::Binding { mutability, name, mode: _, var, ty, subpattern } => {
|
||||
@ -180,8 +179,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
|
||||
PatternKind::Deref { subpattern } => {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
}
|
||||
@ -239,16 +237,28 @@ struct MatchPair<'tcx> {
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum TestKind<'tcx> {
|
||||
// test the branches of enum
|
||||
Switch { adt_def: AdtDef<'tcx> },
|
||||
Switch {
|
||||
adt_def: AdtDef<'tcx>,
|
||||
},
|
||||
|
||||
// test for equality
|
||||
Eq { value: Literal<'tcx>, ty: Ty<'tcx> },
|
||||
Eq {
|
||||
value: Literal<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
// test whether the value falls within an inclusive range
|
||||
Range { lo: Literal<'tcx>, hi: Literal<'tcx>, ty: Ty<'tcx> },
|
||||
Range {
|
||||
lo: Literal<'tcx>,
|
||||
hi: Literal<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
// test length of the slice is equal to len
|
||||
Len { len: usize, op: BinOp },
|
||||
Len {
|
||||
len: usize,
|
||||
op: BinOp,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -416,4 +426,3 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
index
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,15 +33,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
pub fn simplify_candidate(&mut self,
|
||||
mut block: BasicBlock,
|
||||
candidate: &mut Candidate<'tcx>)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
-> BlockAnd<()> {
|
||||
// repeatedly simplify match pairs until fixed point is reached
|
||||
loop {
|
||||
let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
|
||||
let mut progress = match_pairs.len(); // count how many were simplified
|
||||
for match_pair in match_pairs {
|
||||
match self.simplify_match_pair(block, match_pair, candidate) {
|
||||
Ok(b) => { block = b; }
|
||||
Ok(b) => {
|
||||
block = b;
|
||||
}
|
||||
Err(match_pair) => {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
progress -= 1; // this one was not simplified
|
||||
@ -63,8 +64,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
mut block: BasicBlock,
|
||||
match_pair: MatchPair<'tcx>,
|
||||
candidate: &mut Candidate<'tcx>)
|
||||
-> Result<BasicBlock, MatchPair<'tcx>>
|
||||
{
|
||||
-> Result<BasicBlock, MatchPair<'tcx>> {
|
||||
match match_pair.pattern.kind {
|
||||
PatternKind::Wild(..) => {
|
||||
// nothing left to do
|
||||
@ -115,8 +115,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
PatternKind::Leaf { subpatterns } => {
|
||||
// tuple struct, match subpats (if any)
|
||||
candidate.match_pairs.extend(
|
||||
self.field_match_pairs(match_pair.lvalue, subpatterns));
|
||||
candidate.match_pairs
|
||||
.extend(self.field_match_pairs(match_pair.lvalue, subpatterns));
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
@ -129,4 +129,3 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,23 +37,31 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
PatternKind::Constant { ref value } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Eq { value: value.clone(),
|
||||
ty: match_pair.pattern.ty.clone() },
|
||||
kind: TestKind::Eq {
|
||||
value: value.clone(),
|
||||
ty: match_pair.pattern.ty.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Range { ref lo, ref hi } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Range { lo: lo.clone(),
|
||||
hi: hi.clone(),
|
||||
ty: match_pair.pattern.ty.clone() },
|
||||
kind: TestKind::Range {
|
||||
lo: lo.clone(),
|
||||
hi: hi.clone(),
|
||||
ty: match_pair.pattern.ty.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
let len = prefix.len() + suffix.len();
|
||||
let op = if slice.is_some() {BinOp::Ge} else {BinOp::Eq};
|
||||
let op = if slice.is_some() {
|
||||
BinOp::Ge
|
||||
} else {
|
||||
BinOp::Eq
|
||||
};
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Len { len: len, op: op },
|
||||
@ -102,11 +110,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let hi = self.push_literal(block, test.span, ty.clone(), hi);
|
||||
let item_ref = self.hir.partial_le(ty);
|
||||
|
||||
let lo_blocks =
|
||||
self.call_comparison_fn(block, test.span, item_ref.clone(), lo, lvalue.clone());
|
||||
let lo_blocks = self.call_comparison_fn(block,
|
||||
test.span,
|
||||
item_ref.clone(),
|
||||
lo,
|
||||
lvalue.clone());
|
||||
|
||||
let hi_blocks =
|
||||
self.call_comparison_fn(lo_blocks[0], test.span, item_ref, lvalue.clone(), hi);
|
||||
let hi_blocks = self.call_comparison_fn(lo_blocks[0],
|
||||
test.span,
|
||||
item_ref,
|
||||
lvalue.clone(),
|
||||
hi);
|
||||
|
||||
let failure = self.cfg.start_new_block();
|
||||
self.cfg.terminate(lo_blocks[1], Terminator::Goto { target: failure });
|
||||
@ -120,20 +134,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
let (actual, result) = (self.temp(usize_ty), self.temp(bool_ty));
|
||||
|
||||
// actual = len(lvalue)
|
||||
self.cfg.push_assign(
|
||||
block, test.span,
|
||||
&actual, Rvalue::Len(lvalue.clone()));
|
||||
self.cfg.push_assign(block, test.span, &actual, Rvalue::Len(lvalue.clone()));
|
||||
|
||||
// expected = <N>
|
||||
let expected =
|
||||
self.push_usize(block, test.span, len);
|
||||
let expected = self.push_usize(block, test.span, len);
|
||||
|
||||
// result = actual == expected OR result = actual < expected
|
||||
self.cfg.push_assign(
|
||||
block, test.span,
|
||||
&result, Rvalue::BinaryOp(op,
|
||||
Operand::Consume(actual),
|
||||
Operand::Consume(expected)));
|
||||
self.cfg.push_assign(block,
|
||||
test.span,
|
||||
&result,
|
||||
Rvalue::BinaryOp(op,
|
||||
Operand::Consume(actual),
|
||||
Operand::Consume(expected)));
|
||||
|
||||
// branch based on result
|
||||
let target_blocks: Vec<_> = vec![self.cfg.start_new_block(),
|
||||
@ -155,8 +167,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
lvalue1: Lvalue<'tcx>,
|
||||
lvalue2: Lvalue<'tcx>)
|
||||
-> Vec<BasicBlock> {
|
||||
let target_blocks = vec![self.cfg.start_new_block(),
|
||||
self.cfg.start_new_block()];
|
||||
let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()];
|
||||
|
||||
let bool_ty = self.hir.bool_ty();
|
||||
let eq_result = self.temp(bool_ty);
|
||||
@ -176,7 +187,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
self.cfg.terminate(call_blocks[0],
|
||||
Terminator::If {
|
||||
cond: Operand::Consume(eq_result),
|
||||
targets: [target_blocks[0], target_blocks[1]]
|
||||
targets: [target_blocks[0], target_blocks[1]],
|
||||
});
|
||||
|
||||
target_blocks
|
||||
@ -209,7 +220,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
match_pairs));
|
||||
block.and(match result {
|
||||
Some(match_pairs) => Some(Candidate { match_pairs: match_pairs, ..candidate }),
|
||||
None => None
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
@ -341,8 +352,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
|
||||
fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! {
|
||||
self.hir.span_bug(
|
||||
match_pair.pattern.span,
|
||||
&format!("simplifyable pattern found: {:?}", match_pair.pattern))
|
||||
self.hir.span_bug(match_pair.pattern.span,
|
||||
&format!("simplifyable pattern found: {:?}", match_pair.pattern))
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn match_pair(&mut self, lvalue: Lvalue<'tcx>, pattern: PatternRef<'tcx>)
|
||||
pub fn match_pair(&mut self,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
pattern: PatternRef<'tcx>)
|
||||
-> MatchPair<'tcx> {
|
||||
let pattern = self.hir.mirror(pattern);
|
||||
MatchPair::new(lvalue, pattern)
|
||||
@ -54,17 +56,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
opt_slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>)
|
||||
-> BlockAnd<()>
|
||||
{
|
||||
-> BlockAnd<()> {
|
||||
// If there is a `..P` pattern, create a temporary `t0` for
|
||||
// the slice and then a match pair `t0 @ P`:
|
||||
if let Some(slice) = opt_slice {
|
||||
let slice = self.hir.mirror(slice);
|
||||
let prefix_len = prefix.len();
|
||||
let suffix_len = suffix.len();
|
||||
let rvalue = Rvalue::Slice { input: lvalue.clone(),
|
||||
from_start: prefix_len,
|
||||
from_end: suffix_len };
|
||||
let rvalue = Rvalue::Slice {
|
||||
input: lvalue.clone(),
|
||||
from_start: prefix_len,
|
||||
from_end: suffix_len,
|
||||
};
|
||||
let temp = self.temp(slice.ty.clone()); // no need to schedule drop, temp is always copy
|
||||
self.cfg.push_assign(block, slice.span, &temp, rvalue);
|
||||
match_pairs.push(MatchPair::new(temp, slice));
|
||||
@ -80,8 +83,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
match_pairs: &mut Vec<MatchPair<'tcx>>,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>)
|
||||
{
|
||||
suffix: Vec<PatternRef<'tcx>>) {
|
||||
let min_length = prefix.len() + suffix.len();
|
||||
assert!(min_length < u32::MAX as usize);
|
||||
let min_length = min_length as u32;
|
||||
@ -121,6 +123,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
impl<'tcx> MatchPair<'tcx> {
|
||||
pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> {
|
||||
MatchPair { lvalue: lvalue, pattern: pattern }
|
||||
MatchPair {
|
||||
lvalue: lvalue,
|
||||
pattern: pattern,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,16 +41,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
literal: Literal<'tcx>)
|
||||
-> Lvalue<'tcx> {
|
||||
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);
|
||||
temp
|
||||
}
|
||||
|
||||
pub fn push_usize(&mut self,
|
||||
block: BasicBlock,
|
||||
span: Span,
|
||||
value: usize)
|
||||
-> Lvalue<'tcx> {
|
||||
pub fn push_usize(&mut self, block: BasicBlock, span: Span, value: usize) -> Lvalue<'tcx> {
|
||||
let usize_ty = self.hir.usize_ty();
|
||||
let temp = self.temp(usize_ty);
|
||||
self.cfg.push_assign_constant(
|
||||
@ -68,7 +68,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
span: Span,
|
||||
item_ref: ItemRef<'tcx>)
|
||||
-> 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)
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use tcx::{Cx, PatNode};
|
||||
|
||||
struct Builder<'a,'tcx:'a> {
|
||||
struct Builder<'a, 'tcx: 'a> {
|
||||
hir: Cx<'a, 'tcx>,
|
||||
extents: FnvHashMap<CodeExtent, Vec<GraphExtent>>,
|
||||
cfg: CFG<'tcx>,
|
||||
@ -31,7 +31,7 @@ struct Builder<'a,'tcx:'a> {
|
||||
}
|
||||
|
||||
struct CFG<'tcx> {
|
||||
basic_blocks: Vec<BasicBlockData<'tcx>>
|
||||
basic_blocks: Vec<BasicBlockData<'tcx>>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -75,13 +75,13 @@ macro_rules! unpack {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// construct() -- the main entry point for building MIR for a function
|
||||
|
||||
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
|
||||
_span: Span,
|
||||
implicit_arguments: Vec<Ty<'tcx>>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> Mir<'tcx> {
|
||||
pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
|
||||
_span: Span,
|
||||
implicit_arguments: Vec<Ty<'tcx>>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> Mir<'tcx> {
|
||||
let cfg = CFG { basic_blocks: vec![] };
|
||||
|
||||
// it's handy to have a temporary of type `()` sometimes, so make
|
||||
@ -115,7 +115,7 @@ pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
|
||||
builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
|
||||
builder.cfg.terminate(END_BLOCK, Terminator::Return);
|
||||
|
||||
Mir {
|
||||
Mir {
|
||||
basic_blocks: builder.cfg.basic_blocks,
|
||||
extents: builder.extents,
|
||||
var_decls: builder.var_decls,
|
||||
@ -177,4 +177,3 @@ mod matches;
|
||||
mod misc;
|
||||
mod scope;
|
||||
mod stmt;
|
||||
|
||||
|
@ -101,25 +101,27 @@ pub struct Scope<'tcx> {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LoopScope {
|
||||
pub extent: CodeExtent, // extent of the loop
|
||||
pub extent: CodeExtent, // extent of the loop
|
||||
pub continue_block: BasicBlock, // where to go on a `loop`
|
||||
pub break_block: BasicBlock, // where to go on a `break
|
||||
pub break_block: BasicBlock, // where to go on a `break
|
||||
}
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// Start a loop scope, which tracks where `continue` and `break`
|
||||
/// should branch to. See module comment for more details.
|
||||
pub fn in_loop_scope<F,R>(&mut self,
|
||||
loop_block: BasicBlock,
|
||||
break_block: BasicBlock,
|
||||
f: F)
|
||||
-> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd<R>
|
||||
pub fn in_loop_scope<F, R>(&mut self,
|
||||
loop_block: BasicBlock,
|
||||
break_block: BasicBlock,
|
||||
f: F)
|
||||
-> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
|
||||
{
|
||||
let extent = self.extent_of_innermost_scope().unwrap();
|
||||
let loop_scope = LoopScope { extent: extent.clone(),
|
||||
continue_block: loop_block,
|
||||
break_block: break_block };
|
||||
let loop_scope = LoopScope {
|
||||
extent: extent.clone(),
|
||||
continue_block: loop_block,
|
||||
break_block: break_block,
|
||||
};
|
||||
self.loop_scopes.push(loop_scope);
|
||||
let r = f(self);
|
||||
assert!(self.loop_scopes.pop().unwrap().extent == extent);
|
||||
@ -128,12 +130,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
/// Start a scope. The closure `f` should translate the contents
|
||||
/// of the scope. See module comment for more details.
|
||||
pub fn in_scope<F,R>(&mut self,
|
||||
extent: CodeExtent,
|
||||
block: BasicBlock,
|
||||
f: F)
|
||||
-> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a,'tcx>) -> BlockAnd<R>
|
||||
pub fn in_scope<F, R>(&mut self, extent: CodeExtent, block: BasicBlock, f: F) -> BlockAnd<R>
|
||||
where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
|
||||
{
|
||||
debug!("in_scope(extent={:?}, block={:?})", extent, block);
|
||||
|
||||
@ -173,9 +171,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
/// exit points.
|
||||
fn graph_extent(&self, entry: ExecutionPoint, exits: Vec<ExecutionPoint>) -> GraphExtent {
|
||||
if exits.len() == 1 && entry.block == exits[0].block {
|
||||
GraphExtent { entry: entry, exit: GraphExtentExit::Statement(exits[0].statement) }
|
||||
GraphExtent {
|
||||
entry: entry,
|
||||
exit: GraphExtentExit::Statement(exits[0].statement),
|
||||
}
|
||||
} else {
|
||||
GraphExtent { entry: entry, exit: GraphExtentExit::Points(exits) }
|
||||
GraphExtent {
|
||||
entry: entry,
|
||||
exit: GraphExtentExit::Points(exits),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,7 +208,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
|
||||
match loop_scope {
|
||||
Some(loop_scope) => loop_scope.clone(),
|
||||
None => self.hir.span_bug(span, "no enclosing loop scope found?")
|
||||
None => self.hir.span_bug(span, "no enclosing loop scope found?"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,8 +259,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
extent: CodeExtent,
|
||||
kind: DropKind,
|
||||
lvalue: &Lvalue<'tcx>,
|
||||
lvalue_ty: Ty<'tcx>)
|
||||
{
|
||||
lvalue_ty: Ty<'tcx>) {
|
||||
if self.hir.needs_drop(lvalue_ty, span) {
|
||||
match self.scopes.iter_mut().rev().find(|s| s.extent == extent) {
|
||||
Some(scope) => {
|
||||
@ -278,9 +281,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn diverge_cleanup_helper<'tcx>(cfg: &mut CFG<'tcx>,
|
||||
scopes: &mut [Scope<'tcx>])
|
||||
-> BasicBlock {
|
||||
fn diverge_cleanup_helper<'tcx>(cfg: &mut CFG<'tcx>, scopes: &mut [Scope<'tcx>]) -> BasicBlock {
|
||||
let len = scopes.len();
|
||||
|
||||
if len == 0 {
|
||||
|
@ -70,15 +70,18 @@ impl<'a,'tcx> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<'tcx> {
|
||||
self.all_basic_blocks()
|
||||
.into_iter()
|
||||
.flat_map(|source| {
|
||||
self.basic_block_data(source).terminator
|
||||
.successors()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(move |(index, &target)| {
|
||||
EdgeIndex { source: source,
|
||||
target: target,
|
||||
index: index }
|
||||
})
|
||||
self.basic_block_data(source)
|
||||
.terminator
|
||||
.successors()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(move |(index, &target)| {
|
||||
EdgeIndex {
|
||||
source: source,
|
||||
target: target,
|
||||
index: index,
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into_cow()
|
||||
@ -118,7 +121,10 @@ fn all_to_subscript(header: &str, mut text: String) -> String {
|
||||
/// Returns an updated string if changes were made, else None.
|
||||
fn to_subscript1(header: &str, text: &str, offset: &mut usize) -> Option<String> {
|
||||
let a = match text[*offset..].find(header) {
|
||||
None => { *offset = text.len(); return None; }
|
||||
None => {
|
||||
*offset = text.len();
|
||||
return None;
|
||||
}
|
||||
Some(a) => a + *offset,
|
||||
};
|
||||
|
||||
@ -141,8 +147,12 @@ fn all_to_subscript(header: &str, mut text: String) -> String {
|
||||
result.push_str(&text[..b]);
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
if c == ')' { break; }
|
||||
if !c.is_digit(10) { return None; }
|
||||
if c == ')' {
|
||||
break;
|
||||
}
|
||||
if !c.is_digit(10) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// 0x208 is _0 in unicode, 0x209 is _1, etc
|
||||
const SUBSCRIPTS: &'static str = "₀₁₂₃₄₅₆₇₈₉";
|
||||
|
@ -58,7 +58,7 @@ pub enum StmtKind<'tcx> {
|
||||
scope: CodeExtent,
|
||||
|
||||
/// expression being evaluated in this statement
|
||||
expr: ExprRef<'tcx>
|
||||
expr: ExprRef<'tcx>,
|
||||
},
|
||||
|
||||
Let {
|
||||
@ -77,7 +77,7 @@ pub enum StmtKind<'tcx> {
|
||||
initializer: Option<ExprRef<'tcx>>,
|
||||
|
||||
/// let pat = init; <STMTS>
|
||||
stmts: Vec<StmtRef<'tcx>>
|
||||
stmts: Vec<StmtRef<'tcx>>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -113,45 +113,128 @@ pub struct Expr<'tcx> {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ExprKind<'tcx> {
|
||||
Scope { extent: CodeExtent, value: ExprRef<'tcx> },
|
||||
Box { value: ExprRef<'tcx> },
|
||||
Call { fun: ExprRef<'tcx>, args: Vec<ExprRef<'tcx>> },
|
||||
Deref { arg: ExprRef<'tcx> }, // NOT overloaded!
|
||||
Binary { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> }, // NOT overloaded!
|
||||
LogicalOp { op: LogicalOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
|
||||
Unary { op: UnOp, arg: ExprRef<'tcx> }, // NOT overloaded!
|
||||
Cast { source: ExprRef<'tcx> },
|
||||
ReifyFnPointer { source: ExprRef<'tcx> },
|
||||
UnsafeFnPointer { source: ExprRef<'tcx> },
|
||||
Unsize { source: ExprRef<'tcx> },
|
||||
If { condition: ExprRef<'tcx>, then: ExprRef<'tcx>, otherwise: Option<ExprRef<'tcx>> },
|
||||
Loop { condition: Option<ExprRef<'tcx>>, body: ExprRef<'tcx>, },
|
||||
Match { discriminant: ExprRef<'tcx>, arms: Vec<Arm<'tcx>> },
|
||||
Block { body: &'tcx hir::Block },
|
||||
Assign { lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
|
||||
AssignOp { op: BinOp, lhs: ExprRef<'tcx>, rhs: ExprRef<'tcx> },
|
||||
Field { lhs: ExprRef<'tcx>, name: Field },
|
||||
Index { lhs: ExprRef<'tcx>, index: ExprRef<'tcx> },
|
||||
VarRef { id: ast::NodeId },
|
||||
Scope {
|
||||
extent: CodeExtent,
|
||||
value: ExprRef<'tcx>,
|
||||
},
|
||||
Box {
|
||||
value: ExprRef<'tcx>,
|
||||
},
|
||||
Call {
|
||||
fun: ExprRef<'tcx>,
|
||||
args: Vec<ExprRef<'tcx>>,
|
||||
},
|
||||
Deref {
|
||||
arg: ExprRef<'tcx>,
|
||||
}, // NOT overloaded!
|
||||
Binary {
|
||||
op: BinOp,
|
||||
lhs: ExprRef<'tcx>,
|
||||
rhs: ExprRef<'tcx>,
|
||||
}, // NOT overloaded!
|
||||
LogicalOp {
|
||||
op: LogicalOp,
|
||||
lhs: ExprRef<'tcx>,
|
||||
rhs: ExprRef<'tcx>,
|
||||
},
|
||||
Unary {
|
||||
op: UnOp,
|
||||
arg: ExprRef<'tcx>,
|
||||
}, // NOT overloaded!
|
||||
Cast {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
ReifyFnPointer {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
UnsafeFnPointer {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
Unsize {
|
||||
source: ExprRef<'tcx>,
|
||||
},
|
||||
If {
|
||||
condition: ExprRef<'tcx>,
|
||||
then: ExprRef<'tcx>,
|
||||
otherwise: Option<ExprRef<'tcx>>,
|
||||
},
|
||||
Loop {
|
||||
condition: Option<ExprRef<'tcx>>,
|
||||
body: ExprRef<'tcx>,
|
||||
},
|
||||
Match {
|
||||
discriminant: ExprRef<'tcx>,
|
||||
arms: Vec<Arm<'tcx>>,
|
||||
},
|
||||
Block {
|
||||
body: &'tcx hir::Block,
|
||||
},
|
||||
Assign {
|
||||
lhs: ExprRef<'tcx>,
|
||||
rhs: ExprRef<'tcx>,
|
||||
},
|
||||
AssignOp {
|
||||
op: BinOp,
|
||||
lhs: ExprRef<'tcx>,
|
||||
rhs: ExprRef<'tcx>,
|
||||
},
|
||||
Field {
|
||||
lhs: ExprRef<'tcx>,
|
||||
name: Field,
|
||||
},
|
||||
Index {
|
||||
lhs: ExprRef<'tcx>,
|
||||
index: ExprRef<'tcx>,
|
||||
},
|
||||
VarRef {
|
||||
id: ast::NodeId,
|
||||
},
|
||||
SelfRef, // first argument, used for self in a closure
|
||||
StaticRef { id: DefId },
|
||||
Borrow { region: Region, borrow_kind: BorrowKind, arg: ExprRef<'tcx> },
|
||||
Break { label: Option<CodeExtent> },
|
||||
Continue { label: Option<CodeExtent> },
|
||||
Return { value: Option<ExprRef<'tcx>> },
|
||||
Repeat { value: ExprRef<'tcx>, count: ExprRef<'tcx> },
|
||||
Vec { fields: Vec<ExprRef<'tcx>> },
|
||||
Tuple { fields: Vec<ExprRef<'tcx>> },
|
||||
Adt { adt_def: AdtDef<'tcx>,
|
||||
variant_index: usize,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
fields: Vec<FieldExprRef<'tcx>>,
|
||||
base: Option<ExprRef<'tcx>> },
|
||||
Closure { closure_id: DefId,
|
||||
substs: &'tcx ClosureSubsts<'tcx>,
|
||||
upvars: Vec<ExprRef<'tcx>> },
|
||||
Literal { literal: Literal<'tcx> },
|
||||
InlineAsm { asm: &'tcx hir::InlineAsm },
|
||||
StaticRef {
|
||||
id: DefId,
|
||||
},
|
||||
Borrow {
|
||||
region: Region,
|
||||
borrow_kind: BorrowKind,
|
||||
arg: ExprRef<'tcx>,
|
||||
},
|
||||
Break {
|
||||
label: Option<CodeExtent>,
|
||||
},
|
||||
Continue {
|
||||
label: Option<CodeExtent>,
|
||||
},
|
||||
Return {
|
||||
value: Option<ExprRef<'tcx>>,
|
||||
},
|
||||
Repeat {
|
||||
value: ExprRef<'tcx>,
|
||||
count: ExprRef<'tcx>,
|
||||
},
|
||||
Vec {
|
||||
fields: Vec<ExprRef<'tcx>>,
|
||||
},
|
||||
Tuple {
|
||||
fields: Vec<ExprRef<'tcx>>,
|
||||
},
|
||||
Adt {
|
||||
adt_def: AdtDef<'tcx>,
|
||||
variant_index: usize,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
fields: Vec<FieldExprRef<'tcx>>,
|
||||
base: Option<ExprRef<'tcx>>,
|
||||
},
|
||||
Closure {
|
||||
closure_id: DefId,
|
||||
substs: &'tcx ClosureSubsts<'tcx>,
|
||||
upvars: Vec<ExprRef<'tcx>>,
|
||||
},
|
||||
Literal {
|
||||
literal: Literal<'tcx>,
|
||||
},
|
||||
InlineAsm {
|
||||
asm: &'tcx hir::InlineAsm,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -183,7 +266,7 @@ pub struct Pattern<'tcx> {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum LogicalOp {
|
||||
And,
|
||||
Or
|
||||
Or,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -191,36 +274,53 @@ pub enum PatternKind<'tcx> {
|
||||
Wild,
|
||||
|
||||
// x, ref x, x @ P, etc
|
||||
Binding { mutability: Mutability,
|
||||
name: ast::Name,
|
||||
mode: BindingMode,
|
||||
var: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
subpattern: Option<PatternRef<'tcx>> },
|
||||
Binding {
|
||||
mutability: Mutability,
|
||||
name: ast::Name,
|
||||
mode: BindingMode,
|
||||
var: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
subpattern: Option<PatternRef<'tcx>>,
|
||||
},
|
||||
|
||||
// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
|
||||
Variant { adt_def: AdtDef<'tcx>,
|
||||
variant_index: usize,
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>> },
|
||||
Variant {
|
||||
adt_def: AdtDef<'tcx>,
|
||||
variant_index: usize,
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>,
|
||||
},
|
||||
|
||||
// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
|
||||
Leaf { subpatterns: Vec<FieldPatternRef<'tcx>> },
|
||||
Leaf {
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>,
|
||||
},
|
||||
|
||||
Deref { subpattern: PatternRef<'tcx> }, // box P, &P, &mut P, etc
|
||||
Deref {
|
||||
subpattern: PatternRef<'tcx>,
|
||||
}, // box P, &P, &mut P, etc
|
||||
|
||||
Constant { value: Literal<'tcx> },
|
||||
Constant {
|
||||
value: Literal<'tcx>,
|
||||
},
|
||||
|
||||
Range { lo: Literal<'tcx>, hi: Literal<'tcx> },
|
||||
Range {
|
||||
lo: Literal<'tcx>,
|
||||
hi: Literal<'tcx>,
|
||||
},
|
||||
|
||||
// matches against a slice, checking the length and extracting elements
|
||||
Slice { prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>> },
|
||||
Slice {
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>,
|
||||
},
|
||||
|
||||
// fixed match against an array, irrefutable
|
||||
Array { prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>> },
|
||||
Array {
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -259,13 +359,13 @@ pub struct FieldPatternRef<'tcx> {
|
||||
pub trait Mirror<'tcx> {
|
||||
type Output;
|
||||
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Self::Output;
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
|
||||
type Output = Expr<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -273,7 +373,7 @@ impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
|
||||
type Output = Expr<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
|
||||
match self {
|
||||
ExprRef::Hair(h) => h.make_mirror(hir),
|
||||
ExprRef::Mirror(m) => *m,
|
||||
@ -284,7 +384,7 @@ impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
|
||||
type Output = Stmt<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -292,7 +392,7 @@ impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
|
||||
type Output = Stmt<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
|
||||
match self {
|
||||
StmtRef::Hair(h) => h.make_mirror(hir),
|
||||
StmtRef::Mirror(m) => *m,
|
||||
@ -303,7 +403,7 @@ impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for Pattern<'tcx> {
|
||||
type Output = Pattern<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -311,7 +411,7 @@ impl<'tcx> Mirror<'tcx> for Pattern<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> {
|
||||
type Output = Pattern<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
|
||||
fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
|
||||
match self {
|
||||
PatternRef::Hair(h) => h.make_mirror(hir),
|
||||
PatternRef::Mirror(m) => *m,
|
||||
@ -322,8 +422,7 @@ impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for Block<'tcx> {
|
||||
type Output = Block<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Block<'tcx> {
|
||||
fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,13 @@ use self::syntax::codemap::Span;
|
||||
|
||||
pub type MirMap<'tcx> = NodeMap<Mir<'tcx>>;
|
||||
|
||||
pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'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 };
|
||||
let mut dump = OuterDump {
|
||||
tcx: tcx,
|
||||
map: &mut map,
|
||||
};
|
||||
visit::walk_crate(&mut dump, tcx.map.krate());
|
||||
}
|
||||
map
|
||||
@ -51,16 +54,20 @@ pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'tcx>{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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>,
|
||||
map: &'a mut MirMap<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> OuterDump<'a, 'tcx> {
|
||||
fn visit_mir<OP>(&mut self, attributes: &'a [ast::Attribute], mut walk_op: OP)
|
||||
where OP: for<'m> FnMut(&mut InnerDump<'a,'m,'tcx>)
|
||||
where OP: for<'m> FnMut(&mut InnerDump<'a, 'm, 'tcx>)
|
||||
{
|
||||
let mut closure_dump = InnerDump { tcx: self.tcx, attr: None, map: &mut *self.map };
|
||||
let mut closure_dump = InnerDump {
|
||||
tcx: self.tcx,
|
||||
attr: None,
|
||||
map: &mut *self.map,
|
||||
};
|
||||
for attr in attributes {
|
||||
if attr.check_name("rustc_mir") {
|
||||
closure_dump.attr = Some(attr);
|
||||
@ -84,8 +91,7 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
|
||||
}
|
||||
hir::MethodTraitItem(_, None) |
|
||||
hir::ConstTraitItem(..) |
|
||||
hir::TypeTraitItem(..) => {
|
||||
}
|
||||
hir::TypeTraitItem(..) => {}
|
||||
}
|
||||
visit::walk_trait_item(self, trait_item);
|
||||
}
|
||||
@ -95,7 +101,7 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
|
||||
hir::MethodImplItem(..) => {
|
||||
self.visit_mir(&impl_item.attrs, |c| visit::walk_impl_item(c, impl_item));
|
||||
}
|
||||
hir::ConstImplItem(..) | hir::TypeImplItem(..) => { }
|
||||
hir::ConstImplItem(..) | hir::TypeImplItem(..) => {}
|
||||
}
|
||||
visit::walk_impl_item(self, impl_item);
|
||||
}
|
||||
@ -104,7 +110,7 @@ impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InnerDump -- dumps MIR for a single fn and its contained closures
|
||||
|
||||
struct InnerDump<'a,'m,'tcx:'a+'m> {
|
||||
struct InnerDump<'a, 'm, 'tcx: 'a + 'm> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
map: &'m mut MirMap<'tcx>,
|
||||
attr: Option<&'a ast::Attribute>,
|
||||
@ -136,21 +142,16 @@ impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
|
||||
(format!(""), vec![]),
|
||||
};
|
||||
|
||||
let param_env =
|
||||
ty::ParameterEnvironment::for_item(self.tcx, id);
|
||||
let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
|
||||
|
||||
let infcx =
|
||||
infer::new_infer_ctxt(self.tcx,
|
||||
&self.tcx.tables,
|
||||
Some(param_env),
|
||||
true);
|
||||
let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), true);
|
||||
|
||||
match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
|
||||
Ok(mir) => {
|
||||
let meta_item_list =
|
||||
self.attr.iter()
|
||||
.flat_map(|a| a.meta_item_list())
|
||||
.flat_map(|l| l.iter());
|
||||
let meta_item_list = self.attr
|
||||
.iter()
|
||||
.flat_map(|a| a.meta_item_list())
|
||||
.flat_map(|l| l.iter());
|
||||
for item in meta_item_list {
|
||||
if item.check_name("graphviz") {
|
||||
match item.value_str() {
|
||||
@ -181,58 +182,49 @@ impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
|
||||
let previous = self.map.insert(id, mir);
|
||||
assert!(previous.is_none());
|
||||
}
|
||||
Err(ErrorReported) => { }
|
||||
Err(ErrorReported) => {}
|
||||
}
|
||||
|
||||
visit::walk_fn(self, fk, decl, body, span);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
|
||||
implicit_arg_tys: Vec<Ty<'tcx>>,
|
||||
fn_id: ast::NodeId,
|
||||
span: Span,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block)
|
||||
-> Result<Mir<'tcx>, ErrorReported> {
|
||||
let arguments =
|
||||
decl.inputs
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
let ty = cx.tcx().node_id_to_type(arg.id);
|
||||
(ty, PatNode::irrefutable(&arg.pat))
|
||||
})
|
||||
.collect();
|
||||
fn build_mir<'a, 'tcx: 'a>(cx: Cx<'a, 'tcx>,
|
||||
implicit_arg_tys: Vec<Ty<'tcx>>,
|
||||
fn_id: ast::NodeId,
|
||||
span: Span,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block)
|
||||
-> Result<Mir<'tcx>, ErrorReported> {
|
||||
let arguments = decl.inputs
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
let ty = cx.tcx().node_id_to_type(arg.id);
|
||||
(ty, PatNode::irrefutable(&arg.pat))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let parameter_scope =
|
||||
cx.tcx().region_maps.lookup_code_extent(
|
||||
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
|
||||
Ok(build::construct(cx,
|
||||
span,
|
||||
implicit_arg_tys,
|
||||
arguments,
|
||||
parameter_scope,
|
||||
body))
|
||||
let parameter_scope = cx.tcx().region_maps.lookup_code_extent(CodeExtentData::ParameterScope {
|
||||
fn_id: fn_id,
|
||||
body_id: body.id,
|
||||
});
|
||||
Ok(build::construct(cx, span, implicit_arg_tys, arguments, parameter_scope, body))
|
||||
}
|
||||
|
||||
fn closure_self_ty<'a,'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
closure_expr_id: ast::NodeId,
|
||||
body_id: ast::NodeId)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
fn closure_self_ty<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
closure_expr_id: ast::NodeId,
|
||||
body_id: ast::NodeId)
|
||||
-> Ty<'tcx> {
|
||||
let closure_ty = tcx.node_id_to_type(closure_expr_id);
|
||||
|
||||
// We're just hard-coding the idea that the signature will be
|
||||
// &self or &mut self and hence will have a bound region with
|
||||
// number 0, hokey.
|
||||
let region =
|
||||
ty::Region::ReFree(
|
||||
ty::FreeRegion {
|
||||
scope: tcx.region_maps.item_extent(body_id),
|
||||
bound_region: ty::BoundRegion::BrAnon(0)
|
||||
});
|
||||
let region =
|
||||
tcx.mk_region(region);
|
||||
let region = ty::Region::ReFree(ty::FreeRegion {
|
||||
scope: tcx.region_maps.item_extent(body_id),
|
||||
bound_region: ty::BoundRegion::BrAnon(0),
|
||||
});
|
||||
let region = tcx.mk_region(region);
|
||||
|
||||
match tcx.closure_kind(tcx.map.local_def_id(closure_expr_id)) {
|
||||
ty::ClosureKind::FnClosureKind =>
|
||||
|
@ -110,7 +110,7 @@ pub enum BorrowKind {
|
||||
Unique,
|
||||
|
||||
/// Data is mutable and not aliasable.
|
||||
Mut
|
||||
Mut,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -226,17 +226,27 @@ pub struct BasicBlockData<'tcx> {
|
||||
|
||||
pub enum Terminator<'tcx> {
|
||||
/// block should have one successor in the graph; we jump there
|
||||
Goto { target: BasicBlock },
|
||||
Goto {
|
||||
target: BasicBlock,
|
||||
},
|
||||
|
||||
/// block should initiate unwinding; should be one successor
|
||||
/// that does cleanup and branches to DIVERGE_BLOCK
|
||||
Panic { target: BasicBlock },
|
||||
Panic {
|
||||
target: BasicBlock,
|
||||
},
|
||||
|
||||
/// jump to branch 0 if this lvalue evaluates to true
|
||||
If { cond: Operand<'tcx>, targets: [BasicBlock; 2] },
|
||||
If {
|
||||
cond: Operand<'tcx>,
|
||||
targets: [BasicBlock; 2],
|
||||
},
|
||||
|
||||
/// lvalue evaluates to some enum; jump depending on the branch
|
||||
Switch { discr: Lvalue<'tcx>, targets: Vec<BasicBlock> },
|
||||
Switch {
|
||||
discr: Lvalue<'tcx>,
|
||||
targets: Vec<BasicBlock>,
|
||||
},
|
||||
|
||||
/// Indicates that the last statement in the block panics, aborts,
|
||||
/// etc. No successors. This terminator appears on exactly one
|
||||
@ -254,7 +264,10 @@ pub enum Terminator<'tcx> {
|
||||
/// block ends with a call; it should have two successors. The
|
||||
/// first successor indicates normal return. The second indicates
|
||||
/// unwinding.
|
||||
Call { data: CallData<'tcx>, targets: [BasicBlock; 2] },
|
||||
Call {
|
||||
data: CallData<'tcx>,
|
||||
targets: [BasicBlock; 2],
|
||||
},
|
||||
}
|
||||
|
||||
impl<'tcx> Terminator<'tcx> {
|
||||
@ -312,7 +325,9 @@ impl<'tcx> Debug for Terminator<'tcx> {
|
||||
Call { data: ref c, targets } => {
|
||||
try!(write!(fmt, "{:?} = {:?}(", c.destination, c.func));
|
||||
for (index, arg) in c.args.iter().enumerate() {
|
||||
if index > 0 { try!(write!(fmt, ", ")); }
|
||||
if index > 0 {
|
||||
try!(write!(fmt, ", "));
|
||||
}
|
||||
try!(write!(fmt, "{:?}", arg));
|
||||
}
|
||||
write!(fmt, ") -> {:?}", targets)
|
||||
@ -339,7 +354,7 @@ pub enum StatementKind<'tcx> {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum DropKind {
|
||||
Shallow,
|
||||
Deep
|
||||
Deep,
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for Statement<'tcx> {
|
||||
@ -376,7 +391,7 @@ pub enum Lvalue<'tcx> {
|
||||
ReturnPointer,
|
||||
|
||||
/// projection out of an lvalue (access a field, deref a pointer, etc)
|
||||
Projection(Box<LvalueProjection<'tcx>>)
|
||||
Projection(Box<LvalueProjection<'tcx>>),
|
||||
}
|
||||
|
||||
/// The `Projection` data structure defines things of the form `B.x`
|
||||
@ -384,13 +399,13 @@ pub enum Lvalue<'tcx> {
|
||||
/// shared between `Constant` and `Lvalue`. See the aliases
|
||||
/// `LvalueProjection` etc below.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Projection<'tcx,B,V> {
|
||||
pub struct Projection<'tcx, B, V> {
|
||||
pub base: B,
|
||||
pub elem: ProjectionElem<'tcx,V>,
|
||||
pub elem: ProjectionElem<'tcx, V>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ProjectionElem<'tcx,V> {
|
||||
pub enum ProjectionElem<'tcx, V> {
|
||||
Deref,
|
||||
Field(Field),
|
||||
Index(V),
|
||||
@ -446,7 +461,10 @@ impl<'tcx> Lvalue<'tcx> {
|
||||
}
|
||||
|
||||
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,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -623,7 +641,7 @@ pub enum UnOp {
|
||||
/// The `!` operator for logical inversion
|
||||
Not,
|
||||
/// The `-` operator for negation
|
||||
Neg
|
||||
Neg,
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
@ -641,8 +659,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
Box(ref t) => write!(fmt, "Box {:?}", t),
|
||||
Aggregate(ref kind, ref lvs) => write!(fmt, "Aggregate<{:?}>({:?})", kind, lvs),
|
||||
InlineAsm(ref asm) => write!(fmt, "InlineAsm({:?})", asm),
|
||||
Slice { ref input, from_start, from_end } => write!(fmt, "{:?}[{:?}..-{:?}]",
|
||||
input, from_start, from_end),
|
||||
Slice { ref input, from_start, from_end } =>
|
||||
write!(fmt, "{:?}[{:?}..-{:?}]", input, from_start, from_end),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -658,12 +676,16 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
pub struct Constant<'tcx> {
|
||||
pub span: Span,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub literal: Literal<'tcx>
|
||||
pub literal: Literal<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Literal<'tcx> {
|
||||
Item { def_id: DefId, substs: &'tcx Substs<'tcx> },
|
||||
Value { value: ConstVal },
|
||||
Item {
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
},
|
||||
Value {
|
||||
value: ConstVal,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ use syntax::ptr::P;
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
||||
type Output = Block<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Block<'tcx> {
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
|
||||
// We have to eagerly translate the "spine" of the statements
|
||||
// in order to get the lexical scoping correctly.
|
||||
let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate());
|
||||
@ -29,7 +29,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
||||
extent: cx.tcx.region_maps.node_extent(self.id),
|
||||
span: self.span,
|
||||
stmts: stmts,
|
||||
expr: self.expr.to_ref()
|
||||
expr: self.expr.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt {
|
||||
type Output = Stmt<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, _cx: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
|
||||
fn make_mirror<'a>(self, _cx: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
|
||||
// In order to get the scoping correct, we eagerly mirror
|
||||
// statements when we translate the enclosing block, so we
|
||||
// should in fact never get to this point.
|
||||
@ -45,11 +45,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt {
|
||||
}
|
||||
}
|
||||
|
||||
fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
|
||||
block_id: ast::NodeId,
|
||||
mut stmts: STMTS)
|
||||
-> Vec<StmtRef<'tcx>>
|
||||
where STMTS: Iterator<Item=(usize, &'tcx P<hir::Stmt>)>
|
||||
fn mirror_stmts<'a, 'tcx: 'a, STMTS>(cx: &mut Cx<'a, 'tcx>,
|
||||
block_id: ast::NodeId,
|
||||
mut stmts: STMTS)
|
||||
-> Vec<StmtRef<'tcx>>
|
||||
where STMTS: Iterator<Item = (usize, &'tcx P<hir::Stmt>)>
|
||||
{
|
||||
let mut result = vec![];
|
||||
while let Some((index, stmt)) = stmts.next() {
|
||||
@ -68,7 +68,7 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
|
||||
hir::DeclLocal(ref local) => {
|
||||
let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
|
||||
block: block_id,
|
||||
first_statement_index: index as u32
|
||||
first_statement_index: index as u32,
|
||||
});
|
||||
let remainder_extent =
|
||||
cx.tcx.region_maps.lookup_code_extent(remainder_extent);
|
||||
@ -77,18 +77,16 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
|
||||
// they are within the scope of this let:
|
||||
let following_stmts = mirror_stmts(cx, block_id, stmts);
|
||||
|
||||
result.push(
|
||||
StmtRef::Mirror(
|
||||
Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_extent,
|
||||
init_scope: cx.tcx.region_maps.node_extent(id),
|
||||
pattern: PatNode::irrefutable(&local.pat).to_ref(),
|
||||
initializer: local.init.to_ref(),
|
||||
stmts: following_stmts
|
||||
}
|
||||
})));
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
span: stmt.span,
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_extent,
|
||||
init_scope: cx.tcx.region_maps.node_extent(id),
|
||||
pattern: PatNode::irrefutable(&local.pat).to_ref(),
|
||||
initializer: local.init.to_ref(),
|
||||
stmts: following_stmts,
|
||||
},
|
||||
})));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -99,16 +97,14 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn to_expr_ref<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
block: &'tcx hir::Block)
|
||||
-> ExprRef<'tcx> {
|
||||
pub fn to_expr_ref<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> {
|
||||
let block_ty = cx.tcx.node_id_to_type(block.id);
|
||||
let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
|
||||
let expr = Expr {
|
||||
ty: block_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: block.span,
|
||||
kind: ExprKind::Block { body: block }
|
||||
kind: ExprKind::Block { body: block },
|
||||
};
|
||||
expr.to_ref()
|
||||
}
|
||||
|
@ -30,14 +30,13 @@ use syntax::ptr::P;
|
||||
impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
type Output = Expr<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Expr<'tcx> {
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
|
||||
debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
|
||||
|
||||
let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)!
|
||||
|
||||
let kind = match self.node {
|
||||
// Here comes the interesting stuff:
|
||||
|
||||
hir::ExprMethodCall(_, _, ref args) => {
|
||||
// Rewrite a.b(c) into UFCS form like Trait::b(a, c)
|
||||
let expr = method_callee(cx, self, ty::MethodCall::expr(self.id));
|
||||
@ -46,24 +45,24 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
.collect();
|
||||
ExprKind::Call {
|
||||
fun: expr.to_ref(),
|
||||
args: args
|
||||
args: args,
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprAddrOf(mutbl, ref expr) => {
|
||||
let region = match expr_ty.sty {
|
||||
ty::TyRef(r, _) => r,
|
||||
_ => cx.tcx.sess.span_bug(expr.span, "type of & not region")
|
||||
_ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
|
||||
};
|
||||
ExprKind::Borrow { region: *region,
|
||||
borrow_kind: to_borrow_kind(mutbl),
|
||||
arg: expr.to_ref() }
|
||||
ExprKind::Borrow {
|
||||
region: *region,
|
||||
borrow_kind: to_borrow_kind(mutbl),
|
||||
arg: expr.to_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprBlock(ref blk) => {
|
||||
ExprKind::Block {
|
||||
body: &**blk
|
||||
}
|
||||
ExprKind::Block { body: &**blk }
|
||||
}
|
||||
|
||||
hir::ExprAssign(ref lhs, ref rhs) => {
|
||||
@ -100,20 +99,26 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
// FIXME overflow
|
||||
match op.node {
|
||||
hir::BinOp_::BiAnd => {
|
||||
ExprKind::LogicalOp { op: LogicalOp::And,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref() }
|
||||
ExprKind::LogicalOp {
|
||||
op: LogicalOp::And,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref(),
|
||||
}
|
||||
}
|
||||
hir::BinOp_::BiOr => {
|
||||
ExprKind::LogicalOp { op: LogicalOp::Or,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref() }
|
||||
ExprKind::LogicalOp {
|
||||
op: LogicalOp::Or,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let op = bin_op(op.node);
|
||||
ExprKind::Binary { op: op,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref() }
|
||||
ExprKind::Binary {
|
||||
op: op,
|
||||
lhs: lhs.to_ref(),
|
||||
rhs: rhs.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,8 +129,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
overloaded_lvalue(cx, self, ty::MethodCall::expr(self.id),
|
||||
PassArgs::ByValue, lhs.to_ref(), vec![index])
|
||||
} else {
|
||||
ExprKind::Index { lhs: lhs.to_ref(),
|
||||
index: index.to_ref() }
|
||||
ExprKind::Index {
|
||||
lhs: lhs.to_ref(),
|
||||
index: index.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +160,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
"UnDeref should have been handled elsewhere");
|
||||
}
|
||||
};
|
||||
ExprKind::Unary { op: op, arg: arg.to_ref() }
|
||||
ExprKind::Unary {
|
||||
op: op,
|
||||
arg: arg.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -202,8 +212,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
ty::TyClosure(def_id, ref substs) => (def_id, substs),
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(self.span,
|
||||
&format!("closure expr w/o closure type: {:?}",
|
||||
closure_ty));
|
||||
&format!("closure expr w/o closure type: {:?}",
|
||||
closure_ty));
|
||||
}
|
||||
};
|
||||
let upvars = cx.tcx.with_freevars(self.id, |freevars| {
|
||||
@ -224,15 +234,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
let (adt_def, substs) = match range_ty.sty {
|
||||
ty::TyStruct(adt_def, substs) => (adt_def, substs),
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.span,
|
||||
&format!("unexpanded ast"));
|
||||
cx.tcx.sess.span_bug(self.span, &format!("unexpanded ast"));
|
||||
}
|
||||
};
|
||||
|
||||
let field_expr_ref = |s: &'tcx P<hir::Expr>, nm: &str| {
|
||||
FieldExprRef { name: Field::Named(token::intern(nm)),
|
||||
expr: s.to_ref() }
|
||||
FieldExprRef {
|
||||
name: Field::Named(token::intern(nm)),
|
||||
expr: s.to_ref(),
|
||||
}
|
||||
};
|
||||
|
||||
let start_field = start.as_ref()
|
||||
@ -243,11 +253,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
.into_iter()
|
||||
.map(|e| field_expr_ref(e, "end"));
|
||||
|
||||
ExprKind::Adt { adt_def: adt_def,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: start_field.chain(end_field).collect(),
|
||||
base: None }
|
||||
ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: start_field.chain(end_field).collect(),
|
||||
base: None,
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprPath(..) => {
|
||||
@ -311,7 +323,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
|
||||
// Now apply adjustments, if any.
|
||||
match cx.tcx.tables.borrow().adjustments.get(&self.id) {
|
||||
None => { }
|
||||
None => {}
|
||||
Some(&ty::adjustment::AdjustReifyFnPointer) => {
|
||||
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
|
||||
expr = Expr {
|
||||
@ -350,7 +362,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: adjusted_ty,
|
||||
span: self.span,
|
||||
kind: kind
|
||||
kind: kind,
|
||||
};
|
||||
}
|
||||
|
||||
@ -359,7 +371,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: target,
|
||||
span: self.span,
|
||||
kind: ExprKind::Unsize { source: expr.to_ref() }
|
||||
kind: ExprKind::Unsize { source: expr.to_ref() },
|
||||
};
|
||||
} else if let Some(autoref) = adj.autoref {
|
||||
let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
|
||||
@ -369,9 +381,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: adjusted_ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Borrow { region: *r,
|
||||
borrow_kind: to_borrow_kind(m),
|
||||
arg: expr.to_ref() }
|
||||
kind: ExprKind::Borrow {
|
||||
region: *r,
|
||||
borrow_kind: to_borrow_kind(m),
|
||||
arg: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
}
|
||||
ty::adjustment::AutoUnsafe(m) => {
|
||||
@ -384,15 +398,17 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: cx.tcx.mk_ref(region, ty::TypeAndMut { ty: expr.ty, mutbl: m }),
|
||||
span: self.span,
|
||||
kind: ExprKind::Borrow { region: *region,
|
||||
borrow_kind: to_borrow_kind(m),
|
||||
arg: expr.to_ref() }
|
||||
kind: ExprKind::Borrow {
|
||||
region: *region,
|
||||
borrow_kind: to_borrow_kind(m),
|
||||
arg: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
expr = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: adjusted_ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Cast { source: expr.to_ref() }
|
||||
kind: ExprKind::Cast { source: expr.to_ref() },
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -405,8 +421,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: expr.ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Scope { extent: expr_extent,
|
||||
value: expr.to_ref() }
|
||||
kind: ExprKind::Scope {
|
||||
extent: expr_extent,
|
||||
value: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
|
||||
// Finally, create a destruction scope, if any.
|
||||
@ -415,7 +433,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: expr.ty,
|
||||
span: self.span,
|
||||
kind: ExprKind::Scope { extent: extent, value: expr.to_ref() }
|
||||
kind: ExprKind::Scope {
|
||||
extent: extent,
|
||||
value: expr.to_ref(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -424,10 +445,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
}
|
||||
}
|
||||
|
||||
fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &hir::Expr,
|
||||
method_call: ty::MethodCall)
|
||||
-> Expr<'tcx> {
|
||||
fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
expr: &hir::Expr,
|
||||
method_call: ty::MethodCall)
|
||||
-> Expr<'tcx> {
|
||||
let tables = cx.tcx.tables.borrow();
|
||||
let callee = &tables.method_map[&method_call];
|
||||
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
|
||||
@ -439,8 +460,8 @@ fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
literal: Literal::Item {
|
||||
def_id: callee.def_id,
|
||||
substs: callee.substs,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +472,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
let map = if arm.pats.len() == 1 {
|
||||
None
|
||||
} else {
|
||||
@ -462,15 +483,14 @@ fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
Some(Rc::new(map))
|
||||
};
|
||||
|
||||
Arm { patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref() }
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &'tcx hir::Expr)
|
||||
-> ExprKind<'tcx>
|
||||
{
|
||||
fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> {
|
||||
let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
|
||||
match cx.tcx.def_map.borrow()[&expr.id].full_def() {
|
||||
def::DefVariant(_, def_id, false) |
|
||||
@ -499,11 +519,10 @@ fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
def: def::Def)
|
||||
-> ExprKind<'tcx>
|
||||
{
|
||||
fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
def: def::Def)
|
||||
-> ExprKind<'tcx> {
|
||||
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
|
||||
|
||||
match def {
|
||||
@ -534,20 +553,16 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
};
|
||||
|
||||
// FIXME free regions in closures are not right
|
||||
let closure_ty =
|
||||
cx.tcx.node_id_to_type(closure_expr_id);
|
||||
let closure_ty = cx.tcx.node_id_to_type(closure_expr_id);
|
||||
|
||||
// FIXME we're just hard-coding the idea that the
|
||||
// signature will be &self or &mut self and hence will
|
||||
// have a bound region with number 0
|
||||
let region =
|
||||
ty::Region::ReFree(
|
||||
ty::FreeRegion {
|
||||
scope: cx.tcx.region_maps.node_extent(body_id),
|
||||
bound_region: ty::BoundRegion::BrAnon(0)
|
||||
});
|
||||
let region =
|
||||
cx.tcx.mk_region(region);
|
||||
let region = ty::Region::ReFree(ty::FreeRegion {
|
||||
scope: cx.tcx.region_maps.node_extent(body_id),
|
||||
bound_region: ty::BoundRegion::BrAnon(0),
|
||||
});
|
||||
let region = cx.tcx.mk_region(region);
|
||||
|
||||
let self_expr = match cx.tcx.closure_kind(cx.tcx.map.local_def_id(closure_expr_id)) {
|
||||
ty::ClosureKind::FnClosureKind => {
|
||||
@ -593,19 +608,23 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
ty: closure_ty,
|
||||
temp_lifetime: temp_lifetime,
|
||||
span: expr.span,
|
||||
kind: ExprKind::SelfRef
|
||||
kind: ExprKind::SelfRef,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// at this point we have `self.n`, which loads up the upvar
|
||||
let field_kind =
|
||||
ExprKind::Field { lhs: self_expr.to_ref(),
|
||||
name: Field::Indexed(index) };
|
||||
let field_kind = ExprKind::Field {
|
||||
lhs: self_expr.to_ref(),
|
||||
name: Field::Indexed(index),
|
||||
};
|
||||
|
||||
// ...but the upvar might be an `&T` or `&mut T` capture, at which
|
||||
// point we need an implicit deref
|
||||
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 = match cx.tcx.upvar_capture(upvar_id) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
@ -629,7 +648,7 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
_ => cx.tcx.sess.span_bug(expr.span, "type of & not region")
|
||||
_ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,23 +671,22 @@ fn bin_op(op: hir::BinOp_) -> BinOp {
|
||||
hir::BinOp_::BiNe => BinOp::Ne,
|
||||
hir::BinOp_::BiGe => BinOp::Ge,
|
||||
hir::BinOp_::BiGt => BinOp::Gt,
|
||||
_ => panic!("no equivalent for ast binop {:?}", op)
|
||||
_ => panic!("no equivalent for ast binop {:?}", op),
|
||||
}
|
||||
}
|
||||
|
||||
enum PassArgs {
|
||||
ByValue,
|
||||
ByRef
|
||||
ByRef,
|
||||
}
|
||||
|
||||
fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
method_call: ty::MethodCall,
|
||||
pass_args: PassArgs,
|
||||
receiver: ExprRef<'tcx>,
|
||||
args: Vec<&'tcx P<hir::Expr>>)
|
||||
-> ExprKind<'tcx>
|
||||
{
|
||||
fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
method_call: ty::MethodCall,
|
||||
pass_args: PassArgs,
|
||||
receiver: ExprRef<'tcx>,
|
||||
args: Vec<&'tcx P<hir::Expr>>)
|
||||
-> ExprKind<'tcx> {
|
||||
// the receiver has all the adjustments that are needed, so we can
|
||||
// just push a reference to it
|
||||
let mut argrefs = vec![receiver];
|
||||
@ -677,9 +695,7 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
// operator, we have to gin up the autorefs (but by value is easy)
|
||||
match pass_args {
|
||||
PassArgs::ByValue => {
|
||||
argrefs.extend(
|
||||
args.iter()
|
||||
.map(|arg| arg.to_ref()))
|
||||
argrefs.extend(args.iter().map(|arg| arg.to_ref()))
|
||||
}
|
||||
|
||||
PassArgs::ByRef => {
|
||||
@ -714,14 +730,13 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
method_call: ty::MethodCall,
|
||||
pass_args: PassArgs,
|
||||
receiver: ExprRef<'tcx>,
|
||||
args: Vec<&'tcx P<hir::Expr>>)
|
||||
-> ExprKind<'tcx>
|
||||
{
|
||||
fn overloaded_lvalue<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
expr: &'tcx hir::Expr,
|
||||
method_call: ty::MethodCall,
|
||||
pass_args: PassArgs,
|
||||
receiver: ExprRef<'tcx>,
|
||||
args: Vec<&'tcx P<hir::Expr>>)
|
||||
-> ExprKind<'tcx> {
|
||||
// For an overloaded *x or x[y] expression of type T, the method
|
||||
// call returns an &T and we must add the deref so that the types
|
||||
// line up (this is because `*x` and `x[y]` represent lvalues):
|
||||
@ -750,20 +765,25 @@ fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
ExprKind::Deref { arg: ref_expr.to_ref() }
|
||||
}
|
||||
|
||||
fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
closure_expr: &'tcx hir::Expr,
|
||||
freevar: &ty::Freevar,
|
||||
freevar_ty: Ty<'tcx>)
|
||||
-> ExprRef<'tcx> {
|
||||
fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
closure_expr: &'tcx hir::Expr,
|
||||
freevar: &ty::Freevar,
|
||||
freevar_ty: Ty<'tcx>)
|
||||
-> ExprRef<'tcx> {
|
||||
let id_var = freevar.def.var_id();
|
||||
let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id };
|
||||
let upvar_id = ty::UpvarId {
|
||||
var_id: id_var,
|
||||
closure_expr_id: closure_expr.id,
|
||||
};
|
||||
let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap();
|
||||
let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id);
|
||||
let var_ty = cx.tcx.node_id_to_type(id_var);
|
||||
let captured_var = Expr { temp_lifetime: temp_lifetime,
|
||||
ty: var_ty,
|
||||
span: closure_expr.span,
|
||||
kind: convert_var(cx, closure_expr, freevar.def) };
|
||||
let captured_var = Expr {
|
||||
temp_lifetime: temp_lifetime,
|
||||
ty: var_ty,
|
||||
span: closure_expr.span,
|
||||
kind: convert_var(cx, closure_expr, freevar.def),
|
||||
};
|
||||
match upvar_capture {
|
||||
ty::UpvarCapture::ByValue => {
|
||||
captured_var.to_ref()
|
||||
@ -786,16 +806,11 @@ fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn loop_label<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
|
||||
expr: &'tcx hir::Expr)
|
||||
-> CodeExtent
|
||||
{
|
||||
fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> CodeExtent {
|
||||
match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
|
||||
Some(def::DefLabel(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
|
||||
d => {
|
||||
cx.tcx.sess.span_bug(
|
||||
expr.span,
|
||||
&format!("loop scope resolved to {:?}", d));
|
||||
cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +27,17 @@ use syntax::codemap::Span;
|
||||
use syntax::parse::token::{self, special_idents};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Cx<'a,'tcx:'a> {
|
||||
pub struct Cx<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
infcx: &'a InferCtxt<'a,'tcx>,
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a,'tcx> Cx<'a,'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'a,'tcx>) -> Cx<'a,'tcx> {
|
||||
Cx { tcx: infcx.tcx, infcx: infcx }
|
||||
pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Cx<'a, 'tcx> {
|
||||
Cx {
|
||||
tcx: infcx.tcx,
|
||||
infcx: infcx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +45,7 @@ pub use self::pattern::PatNode;
|
||||
|
||||
impl<'a,'tcx:'a> Cx<'a, 'tcx> {
|
||||
/// Normalizes `ast` into the appropriate `mirror` type.
|
||||
pub fn mirror<M:Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
|
||||
pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
|
||||
ast.make_mirror(self)
|
||||
}
|
||||
|
||||
@ -141,13 +144,11 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
ty::ImplOrTraitItem::ConstTraitItem(..) |
|
||||
ty::ImplOrTraitItem::TypeTraitItem(..) => {
|
||||
}
|
||||
ty::ImplOrTraitItem::TypeTraitItem(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx.sess.bug(
|
||||
&format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
|
||||
self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,4 +156,3 @@ mod block;
|
||||
mod expr;
|
||||
mod pattern;
|
||||
mod to_ref;
|
||||
|
||||
|
@ -40,7 +40,7 @@ use syntax::ptr::P;
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PatNode<'tcx> {
|
||||
pat: &'tcx hir::Pat,
|
||||
binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>
|
||||
binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> PatNode<'tcx> {
|
||||
@ -53,8 +53,7 @@ impl<'tcx> PatNode<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn irrefutable(pat: &'tcx hir::Pat)
|
||||
-> PatNode<'tcx> {
|
||||
pub fn irrefutable(pat: &'tcx hir::Pat) -> PatNode<'tcx> {
|
||||
PatNode::new(pat, None)
|
||||
}
|
||||
|
||||
@ -76,8 +75,7 @@ impl<'tcx> PatNode<'tcx> {
|
||||
prefix: &'tcx Vec<P<hir::Pat>>,
|
||||
slice: &'tcx Option<P<hir::Pat>>,
|
||||
suffix: &'tcx Vec<P<hir::Pat>>)
|
||||
-> PatternKind<'tcx>
|
||||
{
|
||||
-> PatternKind<'tcx> {
|
||||
match ty.sty {
|
||||
ty::TySlice(..) =>
|
||||
// matching a slice or fixed-length array
|
||||
@ -98,9 +96,7 @@ impl<'tcx> PatNode<'tcx> {
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
"unexpanded macro or bad constant etc");
|
||||
cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,16 +104,17 @@ impl<'tcx> PatNode<'tcx> {
|
||||
fn variant_or_leaf<'a>(&self,
|
||||
cx: &mut Cx<'a, 'tcx>,
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>)
|
||||
-> PatternKind<'tcx>
|
||||
{
|
||||
-> PatternKind<'tcx> {
|
||||
let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefVariant(enum_id, variant_id, _) => {
|
||||
let adt_def = cx.tcx.lookup_adt_def(enum_id);
|
||||
if adt_def.variants.len() > 1 {
|
||||
PatternKind::Variant { adt_def: adt_def,
|
||||
variant_index: adt_def.variant_index_with_id(variant_id),
|
||||
subpatterns: subpatterns }
|
||||
PatternKind::Variant {
|
||||
adt_def: adt_def,
|
||||
variant_index: adt_def.variant_index_with_id(variant_id),
|
||||
subpatterns: subpatterns,
|
||||
}
|
||||
} else {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
@ -130,9 +127,8 @@ impl<'tcx> PatNode<'tcx> {
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
&format!("inappropriate def for pattern: {:?}", def));
|
||||
cx.tcx.sess.span_bug(self.pat.span,
|
||||
&format!("inappropriate def for pattern: {:?}", def));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,16 +137,15 @@ impl<'tcx> PatNode<'tcx> {
|
||||
impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
||||
type Output = Pattern<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a,'tcx>) -> Pattern<'tcx> {
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
|
||||
let kind = match self.pat.node {
|
||||
hir::PatWild(..) =>
|
||||
PatternKind::Wild,
|
||||
hir::PatWild(..) => PatternKind::Wild,
|
||||
|
||||
hir::PatLit(ref value) => {
|
||||
let value = const_eval::eval_const_expr(cx.tcx, value);
|
||||
let value = Literal::Value { value: value };
|
||||
PatternKind::Constant { value: value }
|
||||
},
|
||||
}
|
||||
|
||||
hir::PatRange(ref lo, ref hi) => {
|
||||
let lo = const_eval::eval_const_expr(cx.tcx, lo);
|
||||
@ -296,16 +291,16 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
||||
}
|
||||
|
||||
hir::PatQPath(..) => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
"unexpanded macro or bad constant etc");
|
||||
cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
};
|
||||
|
||||
let ty = cx.tcx.node_id_to_type(self.pat.id);
|
||||
|
||||
Pattern { span: self.pat.span,
|
||||
ty: ty,
|
||||
kind: kind }
|
||||
Pattern {
|
||||
span: self.pat.span,
|
||||
ty: ty,
|
||||
kind: kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ impl<'a,'tcx:'a> ToRef for &'tcx hir::Field {
|
||||
fn to_ref(self) -> FieldExprRef<'tcx> {
|
||||
FieldExprRef {
|
||||
name: Field::Named(self.name.node),
|
||||
expr: self.expr.to_ref()
|
||||
expr: self.expr.to_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user