enable slice patterns and enable building rustdoc
This commit is contained in:
parent
99f3bfc20c
commit
c8a661838e
|
@ -182,7 +182,7 @@ 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,syntax,$(eval $(call ADD_MIR_FLAG,$(crate))))
|
||||
$(foreach crate,$(HOST_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
|
||||
|
||||
# platform-specific auto-configuration
|
||||
include $(CFG_SRC_DIR)mk/platform.mk
|
||||
|
|
|
@ -116,7 +116,7 @@ impl<H:Hair> Builder<H> {
|
|||
}
|
||||
|
||||
pub fn lvalue_into_pattern(&mut self,
|
||||
block: BasicBlock,
|
||||
mut block: BasicBlock,
|
||||
var_extent: H::CodeExtent,
|
||||
irrefutable_pat: PatternRef<H>,
|
||||
initializer: &Lvalue<H>)
|
||||
|
@ -132,7 +132,7 @@ impl<H:Hair> Builder<H> {
|
|||
|
||||
// Simplify the candidate. Since the pattern is irrefutable, this should
|
||||
// always convert all match-pairs into bindings.
|
||||
self.simplify_candidate(&mut candidate);
|
||||
unpack!(block = self.simplify_candidate(block, &mut candidate));
|
||||
|
||||
if !candidate.match_pairs.is_empty() {
|
||||
self.hir.span_bug(
|
||||
|
@ -233,15 +233,7 @@ enum TestKind<H:Hair> {
|
|||
#[derive(Debug)]
|
||||
struct Test<H:Hair> {
|
||||
span: H::Span,
|
||||
|
||||
// the kind of test to be performed,
|
||||
kind: TestKind<H>,
|
||||
|
||||
// the outcome we expect,
|
||||
outcome: usize,
|
||||
|
||||
// and the match pairs that will result
|
||||
match_pairs: Vec<MatchPair<H>>
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -261,7 +253,7 @@ impl<H:Hair> Builder<H> {
|
|||
// complete, all the match pairs which remain require some
|
||||
// form of test, whether it be a switch or pattern comparison.
|
||||
for candidate in &mut candidates {
|
||||
self.simplify_candidate(candidate);
|
||||
unpack!(block = self.simplify_candidate(block, candidate));
|
||||
}
|
||||
|
||||
// The candidates are inversely sorted by priority. Check to
|
||||
|
@ -293,14 +285,16 @@ impl<H:Hair> Builder<H> {
|
|||
debug!("match_candidates: test={:?} match_pair={:?}", test, match_pair);
|
||||
let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
|
||||
|
||||
for (outcome, 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>> =
|
||||
candidates.iter()
|
||||
.filter_map(|candidate| {
|
||||
self.candidate_under_assumption(&match_pair.lvalue,
|
||||
&test.kind,
|
||||
outcome,
|
||||
candidate)
|
||||
unpack!(target_block =
|
||||
self.candidate_under_assumption(target_block,
|
||||
&match_pair.lvalue,
|
||||
&test.kind,
|
||||
outcome,
|
||||
candidate))
|
||||
})
|
||||
.collect();
|
||||
self.match_candidates(span, var_extent, applicable_candidates, target_block);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
//! sort of test: for example, testing which variant an enum is, or
|
||||
//! testing a value against a constant.
|
||||
|
||||
use build::Builder;
|
||||
use build::{BlockAnd, Builder};
|
||||
use build::matches::{Binding, MatchPair, Candidate};
|
||||
use hair::*;
|
||||
use repr::*;
|
||||
|
@ -31,20 +31,25 @@ use std::mem;
|
|||
|
||||
impl<H:Hair> Builder<H> {
|
||||
pub fn simplify_candidate(&mut self,
|
||||
mut block: BasicBlock,
|
||||
candidate: &mut Candidate<H>)
|
||||
-> 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 {
|
||||
if let Err(match_pair) = self.simplify_match_pair(match_pair, candidate) {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
progress -= 1; // this one was not simplified
|
||||
match self.simplify_match_pair(block, match_pair, candidate) {
|
||||
Ok(b) => { block = b; }
|
||||
Err(match_pair) => {
|
||||
candidate.match_pairs.push(match_pair);
|
||||
progress -= 1; // this one was not simplified
|
||||
}
|
||||
}
|
||||
}
|
||||
if progress == 0 {
|
||||
return; // if we were not able to simplify any, done.
|
||||
return block.unit(); // if we were not able to simplify any, done.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,14 +59,15 @@ impl<H:Hair> Builder<H> {
|
|||
/// have been pushed into the candidate. On failure (if false is
|
||||
/// returned), no changes are made to candidate.
|
||||
fn simplify_match_pair(&mut self,
|
||||
mut block: BasicBlock,
|
||||
match_pair: MatchPair<H>,
|
||||
candidate: &mut Candidate<H>)
|
||||
-> Result<(), MatchPair<H>> // returns Err() if cannot simplify
|
||||
-> Result<BasicBlock, MatchPair<H>> // returns Err() if cannot simplify
|
||||
{
|
||||
match match_pair.pattern.kind {
|
||||
PatternKind::Wild(..) => {
|
||||
// nothing left to do
|
||||
Ok(())
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Binding { name, mutability, mode, var, ty, subpattern } => {
|
||||
|
@ -81,7 +87,7 @@ impl<H:Hair> Builder<H> {
|
|||
candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Constant { .. } => {
|
||||
|
@ -89,16 +95,14 @@ impl<H:Hair> Builder<H> {
|
|||
Err(match_pair)
|
||||
}
|
||||
|
||||
PatternKind::Array { prefix, slice: None, suffix } => {
|
||||
self.append_prefix_suffix_pairs(
|
||||
&mut candidate.match_pairs, match_pair.lvalue.clone(), prefix, suffix);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
PatternKind::Array { prefix: _, slice: Some(_), suffix: _ } => {
|
||||
self.hir.span_bug(
|
||||
match_pair.pattern.span,
|
||||
&format!("slice patterns not implemented in MIR"));
|
||||
PatternKind::Array { prefix, slice, suffix } => {
|
||||
unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs,
|
||||
block,
|
||||
match_pair.lvalue.clone(),
|
||||
prefix,
|
||||
slice,
|
||||
suffix));
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Slice { .. } |
|
||||
|
@ -112,14 +116,14 @@ impl<H:Hair> Builder<H> {
|
|||
// tuple struct, match subpats (if any)
|
||||
candidate.match_pairs.extend(
|
||||
self.field_match_pairs(match_pair.lvalue, subpatterns));
|
||||
Ok(())
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Deref { subpattern } => {
|
||||
let lvalue = match_pair.lvalue.deref();
|
||||
let subpattern = self.hir.mirror(subpattern);
|
||||
candidate.match_pairs.push(MatchPair::new(lvalue, subpattern));
|
||||
Ok(())
|
||||
Ok(block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// identify what tests are needed, perform the tests, and then filter
|
||||
// the candidates based on the result.
|
||||
|
||||
use build::Builder;
|
||||
use build::{BlockAnd, Builder};
|
||||
use build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||
use hair::*;
|
||||
use repr::*;
|
||||
|
@ -25,72 +25,40 @@ impl<H:Hair> Builder<H> {
|
|||
///
|
||||
/// It is a bug to call this with a simplifyable pattern.
|
||||
pub fn test(&mut self, match_pair: &MatchPair<H>) -> Test<H> {
|
||||
match match_pair.pattern.kind.clone() {
|
||||
PatternKind::Variant { adt_def, variant_index, subpatterns } => {
|
||||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||
let downcast_lvalue = match_pair.lvalue.clone().elem(elem);
|
||||
|
||||
let consequent_match_pairs =
|
||||
subpatterns.into_iter()
|
||||
.map(|subpattern| {
|
||||
let lvalue =
|
||||
downcast_lvalue.clone().field(
|
||||
subpattern.field);
|
||||
self.match_pair(lvalue, subpattern.pattern)
|
||||
})
|
||||
.collect();
|
||||
|
||||
match match_pair.pattern.kind {
|
||||
PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Switch { adt_def: adt_def },
|
||||
outcome: variant_index,
|
||||
match_pairs: consequent_match_pairs,
|
||||
kind: TestKind::Switch { adt_def: adt_def.clone() },
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Constant { expr } => {
|
||||
let expr = self.as_constant(expr);
|
||||
PatternKind::Constant { ref expr } => {
|
||||
let expr = self.as_constant(expr.clone());
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Eq { value: expr,
|
||||
ty: match_pair.pattern.ty.clone() },
|
||||
outcome: 0, // 0 == true, of course. :)
|
||||
match_pairs: vec![]
|
||||
kind: TestKind::Eq { value: expr, ty: match_pair.pattern.ty.clone() },
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Range { lo, hi } => {
|
||||
let lo = self.as_constant(lo);
|
||||
let hi = self.as_constant(hi);
|
||||
PatternKind::Range { ref lo, ref hi } => {
|
||||
let lo = self.as_constant(lo.clone());
|
||||
let hi = self.as_constant(hi.clone());
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Range { lo: lo,
|
||||
hi: hi,
|
||||
ty: match_pair.pattern.ty.clone() },
|
||||
outcome: 0, // 0 == true, of course. :)
|
||||
match_pairs: vec![]
|
||||
kind: TestKind::Range { lo: lo, hi: hi, ty: match_pair.pattern.ty.clone() },
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Slice { prefix, slice: None, suffix } => {
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
let len = prefix.len() + suffix.len();
|
||||
let mut consequent_match_pairs = vec![];
|
||||
self.append_prefix_suffix_pairs(
|
||||
&mut consequent_match_pairs, match_pair.lvalue.clone(), prefix, suffix);
|
||||
let op = if slice.is_some() {BinOp::Ge} else {BinOp::Eq};
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
kind: TestKind::Len { len: len, op: BinOp::Eq },
|
||||
outcome: 0, // 0 == true, of course. :)
|
||||
match_pairs: consequent_match_pairs
|
||||
kind: TestKind::Len { len: len, op: op },
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Slice { prefix: _, slice: Some(_), suffix: _ } => {
|
||||
self.hir.span_bug(
|
||||
match_pair.pattern.span,
|
||||
&format!("slice patterns not implemented in MIR"));
|
||||
}
|
||||
|
||||
PatternKind::Array { .. } |
|
||||
PatternKind::Wild |
|
||||
PatternKind::Binding { .. } |
|
||||
|
@ -225,28 +193,36 @@ impl<H:Hair> Builder<H> {
|
|||
/// were `Ok`, we would return `Some([x.0.downcast<Ok>.0 @ P1, x.1
|
||||
/// @ 22])`.
|
||||
pub fn candidate_under_assumption(&mut self,
|
||||
mut block: BasicBlock,
|
||||
test_lvalue: &Lvalue<H>,
|
||||
test_kind: &TestKind<H>,
|
||||
test_outcome: usize,
|
||||
candidate: &Candidate<H>)
|
||||
-> Option<Candidate<H>> {
|
||||
-> BlockAnd<Option<Candidate<H>>> {
|
||||
let candidate = candidate.clone();
|
||||
let match_pairs = candidate.match_pairs;
|
||||
match self.match_pairs_under_assumption(test_lvalue, test_kind, test_outcome, match_pairs) {
|
||||
let result = unpack!(block = self.match_pairs_under_assumption(block,
|
||||
test_lvalue,
|
||||
test_kind,
|
||||
test_outcome,
|
||||
match_pairs));
|
||||
block.and(match result {
|
||||
Some(match_pairs) => Some(Candidate { match_pairs: match_pairs, ..candidate }),
|
||||
None => None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Helper for candidate_under_assumption that does the actual
|
||||
/// work of transforming the list of match pairs.
|
||||
fn match_pairs_under_assumption(&mut self,
|
||||
mut block: BasicBlock,
|
||||
test_lvalue: &Lvalue<H>,
|
||||
test_kind: &TestKind<H>,
|
||||
test_outcome: usize,
|
||||
match_pairs: Vec<MatchPair<H>>)
|
||||
-> Option<Vec<MatchPair<H>>> {
|
||||
-> BlockAnd<Option<Vec<MatchPair<H>>>> {
|
||||
let mut result = vec![];
|
||||
|
||||
for match_pair in match_pairs {
|
||||
// if the match pair is testing a different lvalue, it
|
||||
// is unaffected by this test.
|
||||
|
@ -275,22 +251,92 @@ impl<H:Hair> Builder<H> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if test_outcome != desired_test.outcome {
|
||||
// if we did the right kind of test, but it had the
|
||||
// wrong outcome, then this *entire candidate* can no
|
||||
// longer apply, huzzah! Therefore, we can stop this
|
||||
// iteration and just return `None` to our caller.
|
||||
return None;
|
||||
let opt_consequent_match_pairs =
|
||||
unpack!(block = self.consequent_match_pairs_under_assumption(block,
|
||||
match_pair,
|
||||
test_outcome));
|
||||
match opt_consequent_match_pairs {
|
||||
None => {
|
||||
// Right kind of test, but wrong outcome. That
|
||||
// means this **entire candidate** is
|
||||
// inapplicable, since the candidate is only
|
||||
// applicable if all of its match-pairs apply (and
|
||||
// this one doesn't).
|
||||
return block.and(None);
|
||||
}
|
||||
|
||||
Some(consequent_match_pairs) => {
|
||||
// Test passed; add any new patterns we have to test to the final result.
|
||||
result.extend(consequent_match_pairs)
|
||||
}
|
||||
}
|
||||
}
|
||||
block.and(Some(result))
|
||||
}
|
||||
|
||||
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
||||
///
|
||||
/// It is a bug to call this with a simplifyable pattern.
|
||||
pub fn consequent_match_pairs_under_assumption(&mut self,
|
||||
mut block: BasicBlock,
|
||||
match_pair: MatchPair<H>,
|
||||
test_outcome: usize)
|
||||
-> BlockAnd<Option<Vec<MatchPair<H>>>> {
|
||||
match match_pair.pattern.kind {
|
||||
PatternKind::Variant { adt_def, variant_index, subpatterns } => {
|
||||
if test_outcome != variant_index {
|
||||
return block.and(None);
|
||||
}
|
||||
|
||||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||
let downcast_lvalue = match_pair.lvalue.clone().elem(elem);
|
||||
let consequent_match_pairs =
|
||||
subpatterns.into_iter()
|
||||
.map(|subpattern| {
|
||||
let lvalue =
|
||||
downcast_lvalue.clone().field(
|
||||
subpattern.field);
|
||||
self.match_pair(lvalue, subpattern.pattern)
|
||||
})
|
||||
.collect();
|
||||
block.and(Some(consequent_match_pairs))
|
||||
}
|
||||
|
||||
// otherwise, the test passed, so we now have to include the
|
||||
// "unlocked" set of match pairs. For example, if we had `x @
|
||||
// Some(P1)`, and here we `test_kind==Switch` and
|
||||
// `outcome=Some`, then we would return `x.downcast<Some>.0 @
|
||||
// P1`.
|
||||
result.extend(desired_test.match_pairs);
|
||||
PatternKind::Constant { .. } |
|
||||
PatternKind::Range { .. } => {
|
||||
// these are boolean tests: if we are on the 0th
|
||||
// successor, then they passed, and otherwise they
|
||||
// failed, but there are never any more tests to come.
|
||||
if test_outcome == 0 {
|
||||
block.and(Some(vec![]))
|
||||
} else {
|
||||
block.and(None)
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Slice { prefix, slice, suffix } => {
|
||||
if test_outcome == 0 {
|
||||
let mut consequent_match_pairs = vec![];
|
||||
unpack!(block = self.prefix_suffix_slice(&mut consequent_match_pairs,
|
||||
block,
|
||||
match_pair.lvalue,
|
||||
prefix,
|
||||
slice,
|
||||
suffix));
|
||||
block.and(Some(consequent_match_pairs))
|
||||
} else {
|
||||
block.and(None)
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Array { .. } |
|
||||
PatternKind::Wild |
|
||||
PatternKind::Binding { .. } |
|
||||
PatternKind::Leaf { .. } |
|
||||
PatternKind::Deref { .. } => {
|
||||
self.error_simplifyable(&match_pair)
|
||||
}
|
||||
}
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn error_simplifyable(&mut self, match_pair: &MatchPair<H>) -> ! {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use build::Builder;
|
||||
use build::{BlockAnd, Builder};
|
||||
use build::matches::MatchPair;
|
||||
use hair::*;
|
||||
use repr::*;
|
||||
|
@ -32,11 +32,54 @@ impl<H:Hair> Builder<H> {
|
|||
MatchPair::new(lvalue, pattern)
|
||||
}
|
||||
|
||||
pub fn append_prefix_suffix_pairs(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<H>>,
|
||||
lvalue: Lvalue<H>,
|
||||
prefix: Vec<PatternRef<H>>,
|
||||
suffix: Vec<PatternRef<H>>)
|
||||
/// When processing an array/slice pattern like `lv @ [x, y, ..s, z]`,
|
||||
/// this function converts the prefix (`x`, `y`) and suffix (`z`) into
|
||||
/// distinct match pairs:
|
||||
///
|
||||
/// lv[0 of 3] @ x // see ProjectionElem::ConstantIndex (and its Debug impl)
|
||||
/// lv[1 of 3] @ y // to explain the `[x of y]` notation
|
||||
/// lv[-1 of 3] @ z
|
||||
///
|
||||
/// If a slice like `s` is present, then the function also creates
|
||||
/// a temporary like:
|
||||
///
|
||||
/// tmp0 = lv[2..-1] // using the special Rvalue::Slice
|
||||
///
|
||||
/// and creates a match pair `tmp0 @ s`
|
||||
pub fn prefix_suffix_slice(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<H>>,
|
||||
block: BasicBlock,
|
||||
lvalue: Lvalue<H>,
|
||||
prefix: Vec<PatternRef<H>>,
|
||||
opt_slice: Option<PatternRef<H>>,
|
||||
suffix: Vec<PatternRef<H>>)
|
||||
-> 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 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));
|
||||
}
|
||||
|
||||
self.prefix_suffix(match_pairs, lvalue, prefix, suffix);
|
||||
|
||||
block.unit()
|
||||
}
|
||||
|
||||
/// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
|
||||
fn prefix_suffix(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<H>>,
|
||||
lvalue: Lvalue<H>,
|
||||
prefix: Vec<PatternRef<H>>,
|
||||
suffix: Vec<PatternRef<H>>)
|
||||
{
|
||||
let min_length = prefix.len() + suffix.len();
|
||||
assert!(min_length < u32::MAX as usize);
|
||||
|
|
|
@ -471,9 +471,9 @@ impl<H:Hair> Debug for Lvalue<H> {
|
|||
ProjectionElem::Index(ref index) =>
|
||||
write!(fmt,"{:?}[{:?}]", data.base, index),
|
||||
ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
|
||||
write!(fmt,"{:?}[{:?}; {:?}]", data.base, offset, min_length),
|
||||
write!(fmt,"{:?}[{:?} of {:?}]", data.base, offset, min_length),
|
||||
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
|
||||
write!(fmt,"{:?}[-{:?}; {:?}]", data.base, offset, min_length),
|
||||
write!(fmt,"{:?}[-{:?} of {:?}]", data.base, offset, min_length),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -535,6 +535,17 @@ pub enum Rvalue<H:Hair> {
|
|||
// away after type-checking and before lowering.
|
||||
Aggregate(AggregateKind<H>, Vec<Operand<H>>),
|
||||
|
||||
// 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
|
||||
// slice pattern matching, so e.g. a pattern of the form `[x, y,
|
||||
// .., z]` might create a slice with `from_start=2` and
|
||||
// `from_end=1`.
|
||||
Slice {
|
||||
input: Lvalue<H>,
|
||||
from_start: usize,
|
||||
from_end: usize,
|
||||
},
|
||||
|
||||
InlineAsm(H::InlineAsm),
|
||||
}
|
||||
|
||||
|
@ -623,6 +634,8 @@ impl<H:Hair> Debug for Rvalue<H> {
|
|||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue