Remove the mirroring for patterns and just convert them eagerly; then,
pass around references instead of boxed values to save on clone costs.
This commit is contained in:
parent
ad3bd1b46d
commit
87358728a4
13 changed files with 290 additions and 348 deletions
|
|
@ -44,7 +44,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
// be unreachable or reachable multiple times.
|
||||
let var_extent = self.extent_of_innermost_scope().unwrap();
|
||||
for arm in &arms {
|
||||
self.declare_bindings(var_extent, arm.patterns[0].clone());
|
||||
self.declare_bindings(var_extent, &arm.patterns[0]);
|
||||
}
|
||||
|
||||
let mut arm_blocks = ArmBlocks {
|
||||
|
|
@ -64,18 +64,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
// highest priority candidate comes last in the list. This the
|
||||
// reverse of the order in which candidates are written in the
|
||||
// source.
|
||||
let candidates: Vec<Candidate<'tcx>> =
|
||||
let candidates: Vec<_> =
|
||||
arms.iter()
|
||||
.enumerate()
|
||||
.rev() // highest priority comes last
|
||||
.flat_map(|(arm_index, arm)| {
|
||||
arm.patterns.iter()
|
||||
.rev()
|
||||
.map(move |pat| (arm_index, pat.clone(), arm.guard.clone()))
|
||||
.map(move |pat| (arm_index, pat, arm.guard.clone()))
|
||||
})
|
||||
.map(|(arm_index, pattern, guard)| {
|
||||
Candidate {
|
||||
match_pairs: vec![self.match_pair(discriminant_lvalue.clone(), pattern)],
|
||||
match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)],
|
||||
bindings: vec![],
|
||||
guard: guard,
|
||||
arm_index: arm_index,
|
||||
|
|
@ -102,12 +102,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
pub fn expr_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
var_extent: CodeExtent, // lifetime of vars
|
||||
irrefutable_pat: PatternRef<'tcx>,
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: ExprRef<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
// optimize the case of `let x = ...`
|
||||
let irrefutable_pat = self.hir.mirror(irrefutable_pat);
|
||||
match irrefutable_pat.kind {
|
||||
match *irrefutable_pat.kind {
|
||||
PatternKind::Binding { mutability,
|
||||
name,
|
||||
mode: BindingMode::ByValue,
|
||||
|
|
@ -128,22 +127,22 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let lvalue = unpack!(block = self.as_lvalue(block, initializer));
|
||||
self.lvalue_into_pattern(block,
|
||||
var_extent,
|
||||
PatternRef::Mirror(Box::new(irrefutable_pat)),
|
||||
irrefutable_pat,
|
||||
&lvalue)
|
||||
}
|
||||
|
||||
pub fn lvalue_into_pattern(&mut self,
|
||||
mut block: BasicBlock,
|
||||
var_extent: CodeExtent,
|
||||
irrefutable_pat: PatternRef<'tcx>,
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: &Lvalue<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
// first, creating the bindings
|
||||
self.declare_bindings(var_extent, irrefutable_pat.clone());
|
||||
self.declare_bindings(var_extent, &irrefutable_pat);
|
||||
|
||||
// create a dummy candidate
|
||||
let mut candidate = Candidate::<'tcx> {
|
||||
match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())],
|
||||
let mut candidate = Candidate {
|
||||
match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
|
||||
bindings: vec![],
|
||||
guard: None,
|
||||
arm_index: 0, // since we don't call `match_candidates`, this field is unused
|
||||
|
|
@ -166,29 +165,29 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
block.unit()
|
||||
}
|
||||
|
||||
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 } => {
|
||||
pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: &Pattern<'tcx>) {
|
||||
match *pattern.kind {
|
||||
PatternKind::Binding { mutability, name, mode: _, var, ty, ref subpattern } => {
|
||||
self.declare_binding(var_extent, mutability, name, var, ty, pattern.span);
|
||||
if let Some(subpattern) = subpattern {
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
}
|
||||
}
|
||||
PatternKind::Array { prefix, slice, suffix } |
|
||||
PatternKind::Slice { prefix, slice, suffix } => {
|
||||
for subpattern in prefix.into_iter().chain(slice).chain(suffix) {
|
||||
PatternKind::Array { ref prefix, ref slice, ref suffix } |
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
|
||||
for subpattern in prefix.iter().chain(slice).chain(suffix) {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
|
||||
PatternKind::Deref { subpattern } => {
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
|
||||
}
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
self.declare_bindings(var_extent, subpattern);
|
||||
}
|
||||
PatternKind::Leaf { subpatterns } |
|
||||
PatternKind::Variant { subpatterns, .. } => {
|
||||
PatternKind::Leaf { ref subpatterns } |
|
||||
PatternKind::Variant { ref subpatterns, .. } => {
|
||||
for subpattern in subpatterns {
|
||||
self.declare_bindings(var_extent, subpattern.pattern);
|
||||
self.declare_bindings(var_extent, &subpattern.pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -202,9 +201,9 @@ struct ArmBlocks {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Candidate<'tcx> {
|
||||
struct Candidate<'pat, 'tcx:'pat> {
|
||||
// all of these must be satisfied...
|
||||
match_pairs: Vec<MatchPair<'tcx>>,
|
||||
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
|
||||
|
||||
// ...these bindings established...
|
||||
bindings: Vec<Binding<'tcx>>,
|
||||
|
|
@ -228,12 +227,12 @@ struct Binding<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct MatchPair<'tcx> {
|
||||
struct MatchPair<'pat, 'tcx:'pat> {
|
||||
// this lvalue...
|
||||
lvalue: Lvalue<'tcx>,
|
||||
|
||||
// ... must match this pattern.
|
||||
pattern: Pattern<'tcx>,
|
||||
pattern: &'pat Pattern<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
@ -280,11 +279,11 @@ struct Test<'tcx> {
|
|||
// Main matching algorithm
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
fn match_candidates(&mut self,
|
||||
span: Span,
|
||||
arm_blocks: &mut ArmBlocks,
|
||||
mut candidates: Vec<Candidate<'tcx>>,
|
||||
mut block: BasicBlock)
|
||||
fn match_candidates<'pat>(&mut self,
|
||||
span: Span,
|
||||
arm_blocks: &mut ArmBlocks,
|
||||
mut candidates: Vec<Candidate<'pat, 'tcx>>,
|
||||
mut block: BasicBlock)
|
||||
{
|
||||
debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})",
|
||||
span, block, candidates);
|
||||
|
|
@ -347,7 +346,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
|
||||
|
||||
for (outcome, target_block) in target_blocks.into_iter().enumerate() {
|
||||
let applicable_candidates: Vec<Candidate<'tcx>> =
|
||||
let applicable_candidates: Vec<_> =
|
||||
candidates.iter()
|
||||
.filter_map(|candidate| {
|
||||
self.candidate_under_assumption(&match_pair.lvalue,
|
||||
|
|
@ -372,11 +371,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// bindings, further tests would be a use-after-move (which would
|
||||
/// in turn be detected by the borrowck code that runs on the
|
||||
/// MIR).
|
||||
fn bind_and_guard_matched_candidate(&mut self,
|
||||
mut block: BasicBlock,
|
||||
arm_blocks: &mut ArmBlocks,
|
||||
candidate: Candidate<'tcx>)
|
||||
-> Option<BasicBlock> {
|
||||
fn bind_and_guard_matched_candidate<'pat>(&mut self,
|
||||
mut block: BasicBlock,
|
||||
arm_blocks: &mut ArmBlocks,
|
||||
candidate: Candidate<'pat, 'tcx>)
|
||||
-> Option<BasicBlock> {
|
||||
debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
|
||||
block, candidate);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,10 +30,10 @@ use repr::*;
|
|||
use std::mem;
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
pub fn simplify_candidate(&mut self,
|
||||
mut block: BasicBlock,
|
||||
candidate: &mut Candidate<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
pub fn simplify_candidate<'pat>(&mut self,
|
||||
mut block: BasicBlock,
|
||||
candidate: &mut Candidate<'pat, 'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
// repeatedly simplify match pairs until fixed point is reached
|
||||
loop {
|
||||
let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
|
||||
|
|
@ -60,18 +60,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// have been pushed into the candidate. If no simplification is
|
||||
/// possible, Err is returned and no changes are made to
|
||||
/// candidate.
|
||||
fn simplify_match_pair(&mut self,
|
||||
mut block: BasicBlock,
|
||||
match_pair: MatchPair<'tcx>,
|
||||
candidate: &mut Candidate<'tcx>)
|
||||
-> Result<BasicBlock, MatchPair<'tcx>> {
|
||||
match match_pair.pattern.kind {
|
||||
fn simplify_match_pair<'pat>(&mut self,
|
||||
mut block: BasicBlock,
|
||||
match_pair: MatchPair<'pat, 'tcx>,
|
||||
candidate: &mut Candidate<'pat, 'tcx>)
|
||||
-> Result<BasicBlock, MatchPair<'pat, 'tcx>> {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Wild(..) => {
|
||||
// nothing left to do
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Binding { name, mutability, mode, var, ty, subpattern } => {
|
||||
PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
|
||||
candidate.bindings.push(Binding {
|
||||
name: name,
|
||||
mutability: mutability,
|
||||
|
|
@ -82,9 +82,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
binding_mode: mode,
|
||||
});
|
||||
|
||||
if let Some(subpattern) = subpattern {
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
// this is the `x @ P` case; have to keep matching against `P` now
|
||||
let subpattern = self.hir.mirror(subpattern);
|
||||
candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern));
|
||||
}
|
||||
|
||||
|
|
@ -96,12 +95,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
Err(match_pair)
|
||||
}
|
||||
|
||||
PatternKind::Array { prefix, slice, suffix } => {
|
||||
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||
unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs,
|
||||
block,
|
||||
match_pair.lvalue.clone(),
|
||||
prefix,
|
||||
slice,
|
||||
slice.as_ref(),
|
||||
suffix));
|
||||
Ok(block)
|
||||
}
|
||||
|
|
@ -113,16 +112,15 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
Err(match_pair)
|
||||
}
|
||||
|
||||
PatternKind::Leaf { subpatterns } => {
|
||||
PatternKind::Leaf { ref subpatterns } => {
|
||||
// tuple struct, match subpats (if any)
|
||||
candidate.match_pairs
|
||||
.extend(self.field_match_pairs(match_pair.lvalue, subpatterns));
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
PatternKind::Deref { subpattern } => {
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
let lvalue = match_pair.lvalue.deref();
|
||||
let subpattern = self.hir.mirror(subpattern);
|
||||
candidate.match_pairs.push(MatchPair::new(lvalue, subpattern));
|
||||
Ok(block)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// Identifies what test is needed to decide if `match_pair` is applicable.
|
||||
///
|
||||
/// It is a bug to call this with a simplifyable pattern.
|
||||
pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> {
|
||||
match match_pair.pattern.kind {
|
||||
pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => {
|
||||
Test {
|
||||
span: match_pair.pattern.span,
|
||||
|
|
@ -99,19 +99,19 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_cases_to_switch(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
candidate: &Candidate<'tcx>,
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: &mut Vec<ConstVal>,
|
||||
indices: &mut FnvHashMap<ConstVal, usize>)
|
||||
pub fn add_cases_to_switch<'pat>(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: &mut Vec<ConstVal>,
|
||||
indices: &mut FnvHashMap<ConstVal, usize>)
|
||||
{
|
||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
|
||||
Some(match_pair) => match_pair,
|
||||
_ => { return; }
|
||||
};
|
||||
|
||||
match match_pair.pattern.kind {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Constant { value: Literal::Value { ref value } } => {
|
||||
// if the lvalues match, the type should match
|
||||
assert_eq!(match_pair.pattern.ty, switch_ty);
|
||||
|
|
@ -282,12 +282,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// parameter), we would return `None`. But if the test_outcome
|
||||
/// were `Ok`, we would return `Some([x.0.downcast<Ok>.0 @ P1, x.1
|
||||
/// @ 22])`.
|
||||
pub fn candidate_under_assumption(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize,
|
||||
candidate: &Candidate<'tcx>)
|
||||
-> Option<Candidate<'tcx>> {
|
||||
pub fn candidate_under_assumption<'pat>(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize,
|
||||
candidate: &Candidate<'pat, 'tcx>)
|
||||
-> Option<Candidate<'pat, 'tcx>> {
|
||||
let candidate = candidate.clone();
|
||||
let match_pairs = candidate.match_pairs;
|
||||
let result = self.match_pairs_under_assumption(test_lvalue,
|
||||
|
|
@ -302,12 +302,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
|
||||
/// Helper for candidate_under_assumption that does the actual
|
||||
/// work of transforming the list of match pairs.
|
||||
fn match_pairs_under_assumption(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize,
|
||||
match_pairs: Vec<MatchPair<'tcx>>)
|
||||
-> Option<Vec<MatchPair<'tcx>>> {
|
||||
fn match_pairs_under_assumption<'pat>(&mut self,
|
||||
test_lvalue: &Lvalue<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize,
|
||||
match_pairs: Vec<MatchPair<'pat, 'tcx>>)
|
||||
-> Option<Vec<MatchPair<'pat, 'tcx>>> {
|
||||
let mut result = vec![];
|
||||
|
||||
for match_pair in match_pairs {
|
||||
|
|
@ -357,12 +357,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// the discriminant equals 4, and we find that it does not,
|
||||
/// but the `match_pair` is testing if the discriminant equals 5,
|
||||
/// that does not help us.
|
||||
fn test_informs_match_pair(&mut self,
|
||||
match_pair: &MatchPair<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
_test_outcome: usize)
|
||||
-> bool {
|
||||
match match_pair.pattern.kind {
|
||||
fn test_informs_match_pair<'pat>(&mut self,
|
||||
match_pair: &MatchPair<'pat, 'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
_test_outcome: usize)
|
||||
-> bool {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Variant { .. } => {
|
||||
match *test_kind {
|
||||
TestKind::Switch { .. } => true,
|
||||
|
|
@ -444,13 +444,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// On the second arm, a `None` will be returned, because if we
|
||||
/// observed that `option` has the discriminant `Ok`, then the
|
||||
/// second arm cannot apply.
|
||||
pub fn consequent_match_pairs_under_assumption(&mut self,
|
||||
match_pair: MatchPair<'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize)
|
||||
-> Option<Vec<MatchPair<'tcx>>> {
|
||||
match match_pair.pattern.kind {
|
||||
PatternKind::Variant { adt_def, variant_index, subpatterns } => {
|
||||
pub fn consequent_match_pairs_under_assumption<'pat>(&mut self,
|
||||
match_pair: MatchPair<'pat, 'tcx>,
|
||||
test_kind: &TestKind<'tcx>,
|
||||
test_outcome: usize)
|
||||
-> Option<Vec<MatchPair<'pat, 'tcx>>> {
|
||||
match *match_pair.pattern.kind {
|
||||
PatternKind::Variant { adt_def, variant_index, ref subpatterns } => {
|
||||
assert!(match *test_kind { TestKind::Switch { .. } => true,
|
||||
_ => false });
|
||||
|
||||
|
|
@ -464,12 +464,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
let elem = ProjectionElem::Downcast(adt_def, variant_index);
|
||||
let downcast_lvalue = match_pair.lvalue.clone().elem(elem);
|
||||
let consequent_match_pairs =
|
||||
subpatterns.into_iter()
|
||||
subpatterns.iter()
|
||||
.map(|subpattern| {
|
||||
let lvalue =
|
||||
downcast_lvalue.clone().field(
|
||||
subpattern.field);
|
||||
self.match_pair(lvalue, subpattern.pattern)
|
||||
MatchPair::new(lvalue, &subpattern.pattern)
|
||||
})
|
||||
.collect();
|
||||
Some(consequent_match_pairs)
|
||||
|
|
@ -516,7 +516,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! {
|
||||
fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
|
||||
self.hir.span_bug(match_pair.pattern.span,
|
||||
&format!("simplifyable pattern found: {:?}", match_pair.pattern))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,26 +15,18 @@ use repr::*;
|
|||
use std::u32;
|
||||
|
||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
pub fn field_match_pairs(&mut self,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>)
|
||||
-> Vec<MatchPair<'tcx>> {
|
||||
subpatterns.into_iter()
|
||||
pub fn field_match_pairs<'pat>(&mut self,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
subpatterns: &'pat [FieldPattern<'tcx>])
|
||||
-> Vec<MatchPair<'pat, 'tcx>> {
|
||||
subpatterns.iter()
|
||||
.map(|fieldpat| {
|
||||
let lvalue = lvalue.clone().field(fieldpat.field);
|
||||
self.match_pair(lvalue, fieldpat.pattern)
|
||||
MatchPair::new(lvalue, &fieldpat.pattern)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn match_pair(&mut self,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
pattern: PatternRef<'tcx>)
|
||||
-> MatchPair<'tcx> {
|
||||
let pattern = self.hir.mirror(pattern);
|
||||
MatchPair::new(lvalue, pattern)
|
||||
}
|
||||
|
||||
/// 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:
|
||||
|
|
@ -49,18 +41,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
/// 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<'tcx>>,
|
||||
block: BasicBlock,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
opt_slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>)
|
||||
-> BlockAnd<()> {
|
||||
pub fn prefix_suffix_slice<'pat>(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||
block: BasicBlock,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
prefix: &'pat [Pattern<'tcx>],
|
||||
opt_slice: Option<&'pat Pattern<'tcx>>,
|
||||
suffix: &'pat [Pattern<'tcx>])
|
||||
-> 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 {
|
||||
|
|
@ -79,17 +70,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
}
|
||||
|
||||
/// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
|
||||
fn prefix_suffix(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<'tcx>>,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>) {
|
||||
fn prefix_suffix<'pat>(&mut self,
|
||||
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
|
||||
lvalue: Lvalue<'tcx>,
|
||||
prefix: &'pat [Pattern<'tcx>],
|
||||
suffix: &'pat [Pattern<'tcx>]) {
|
||||
let min_length = prefix.len() + suffix.len();
|
||||
assert!(min_length < u32::MAX as usize);
|
||||
let min_length = min_length as u32;
|
||||
|
||||
let prefix_pairs: Vec<_> =
|
||||
prefix.into_iter()
|
||||
prefix.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, subpattern)| {
|
||||
let elem = ProjectionElem::ConstantIndex {
|
||||
|
|
@ -98,12 +89,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
from_end: false,
|
||||
};
|
||||
let lvalue = lvalue.clone().elem(elem);
|
||||
self.match_pair(lvalue, subpattern)
|
||||
MatchPair::new(lvalue, subpattern)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let suffix_pairs: Vec<_> =
|
||||
suffix.into_iter()
|
||||
suffix.iter()
|
||||
.rev()
|
||||
.enumerate()
|
||||
.map(|(idx, subpattern)| {
|
||||
|
|
@ -113,7 +104,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
from_end: true,
|
||||
};
|
||||
let lvalue = lvalue.clone().elem(elem);
|
||||
self.match_pair(lvalue, subpattern)
|
||||
MatchPair::new(lvalue, subpattern)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -121,8 +112,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MatchPair<'tcx> {
|
||||
pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> {
|
||||
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> {
|
||||
MatchPair {
|
||||
lvalue: lvalue,
|
||||
pattern: pattern,
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use hair;
|
||||
use hair::cx::{Cx, PatNode};
|
||||
use hair::cx::Cx;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::ty::{FnOutput, Ty};
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
|
|
@ -78,7 +77,7 @@ macro_rules! unpack {
|
|||
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
|
||||
_span: Span,
|
||||
implicit_arguments: Vec<Ty<'tcx>>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
|
||||
argument_extent: CodeExtent,
|
||||
return_ty: FnOutput<'tcx>,
|
||||
ast_block: &'tcx hir::Block)
|
||||
|
|
@ -130,7 +129,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
fn args_and_body(&mut self,
|
||||
mut block: BasicBlock,
|
||||
implicit_arguments: Vec<Ty<'tcx>>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
|
||||
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
|
||||
argument_extent: CodeExtent,
|
||||
ast_block: &'tcx hir::Block)
|
||||
-> BlockAnd<Vec<ArgDecl<'tcx>>>
|
||||
|
|
@ -148,9 +147,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
.enumerate()
|
||||
.map(|(index, (ty, pattern))| {
|
||||
let lvalue = Lvalue::Arg(index as u32);
|
||||
let pattern = this.hir.irrefutable_pat(pattern);
|
||||
unpack!(block = this.lvalue_into_pattern(block,
|
||||
argument_extent,
|
||||
hair::PatternRef::Hair(pattern),
|
||||
pattern,
|
||||
&lvalue));
|
||||
ArgDecl { ty: ty }
|
||||
});
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer: None, stmts } => {
|
||||
this.in_scope(remainder_scope, block, |this| {
|
||||
unpack!(block = this.in_scope(init_scope, block, |this| {
|
||||
this.declare_bindings(remainder_scope, pattern);
|
||||
this.declare_bindings(remainder_scope, &pattern);
|
||||
block.unit()
|
||||
}));
|
||||
this.stmts(block, stmts)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use hair::*;
|
||||
use hair::cx::Cx;
|
||||
use hair::cx::pattern::PatNode;
|
||||
use hair::cx::to_ref::ToRef;
|
||||
use rustc::middle::region::{BlockRemainder, CodeExtentData};
|
||||
use rustc_front::hir;
|
||||
|
|
@ -65,12 +64,13 @@ 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);
|
||||
|
||||
let pattern = cx.irrefutable_pat(&local.pat);
|
||||
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(),
|
||||
pattern: pattern,
|
||||
initializer: local.init.to_ref(),
|
||||
stmts: following_stmts,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@
|
|||
use hair::*;
|
||||
use repr::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use std::rc::Rc;
|
||||
use hair::cx::Cx;
|
||||
use hair::cx::block;
|
||||
use hair::cx::pattern::PatNode;
|
||||
use hair::cx::to_ref::ToRef;
|
||||
use rustc::front::map;
|
||||
use rustc::middle::const_eval;
|
||||
|
|
@ -486,19 +484,20 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
let map = if arm.pats.len() == 1 {
|
||||
fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
|
||||
let mut map;
|
||||
let opt_map = if arm.pats.len() == 1 {
|
||||
None
|
||||
} else {
|
||||
let mut map = FnvHashMap();
|
||||
map = FnvHashMap();
|
||||
pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
|
||||
map.insert(path.node, p_id);
|
||||
});
|
||||
Some(Rc::new(map))
|
||||
Some(&map)
|
||||
};
|
||||
|
||||
Arm {
|
||||
patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(),
|
||||
patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(),
|
||||
guard: arm.guard.to_ref(),
|
||||
body: arm.body.to_ref(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ impl<'a,'tcx> Cx<'a,'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
|
||||
use hair::*;
|
||||
use hair::cx::Cx;
|
||||
use hair::cx::to_ref::ToRef;
|
||||
use repr::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use std::rc::Rc;
|
||||
use rustc::middle::const_eval;
|
||||
use rustc::middle::def;
|
||||
use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
|
||||
|
|
@ -36,183 +34,111 @@ use syntax::ptr::P;
|
|||
/// _ => { ... }
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PatNode<'tcx> {
|
||||
pat: &'tcx hir::Pat,
|
||||
binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>,
|
||||
struct PatCx<'patcx, 'cx: 'patcx, 'tcx: 'cx> {
|
||||
cx: &'patcx mut Cx<'cx, 'tcx>,
|
||||
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>,
|
||||
}
|
||||
|
||||
impl<'tcx> PatNode<'tcx> {
|
||||
pub fn new(pat: &'tcx hir::Pat,
|
||||
binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>)
|
||||
-> PatNode<'tcx> {
|
||||
PatNode {
|
||||
pat: pat,
|
||||
impl<'cx, 'tcx> Cx<'cx, 'tcx> {
|
||||
pub fn irrefutable_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
|
||||
PatCx::new(self, None).to_pat(pat)
|
||||
}
|
||||
|
||||
pub fn refutable_pat(&mut self,
|
||||
binding_map: Option<&FnvHashMap<ast::Name, ast::NodeId>>,
|
||||
pat: &'tcx hir::Pat)
|
||||
-> Pattern<'tcx> {
|
||||
PatCx::new(self, binding_map).to_pat(pat)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
|
||||
fn new(cx: &'patcx mut Cx<'cx, 'tcx>,
|
||||
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>)
|
||||
-> PatCx<'patcx, 'cx, 'tcx> {
|
||||
PatCx {
|
||||
cx: cx,
|
||||
binding_map: binding_map,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn irrefutable(pat: &'tcx hir::Pat) -> PatNode<'tcx> {
|
||||
PatNode::new(pat, None)
|
||||
}
|
||||
|
||||
fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> {
|
||||
PatNode::new(pat, self.binding_map.clone()).to_ref()
|
||||
}
|
||||
|
||||
fn pat_refs<'a>(&self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<PatternRef<'tcx>> {
|
||||
pats.iter().map(|p| self.pat_ref(p)).collect()
|
||||
}
|
||||
|
||||
fn opt_pat_ref<'a>(&self, pat: &'tcx Option<P<hir::Pat>>) -> Option<PatternRef<'tcx>> {
|
||||
pat.as_ref().map(|p| self.pat_ref(p))
|
||||
}
|
||||
|
||||
fn slice_or_array_pattern<'a>(&self,
|
||||
cx: &mut Cx<'a, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
prefix: &'tcx Vec<P<hir::Pat>>,
|
||||
slice: &'tcx Option<P<hir::Pat>>,
|
||||
suffix: &'tcx Vec<P<hir::Pat>>)
|
||||
-> PatternKind<'tcx> {
|
||||
match ty.sty {
|
||||
ty::TySlice(..) =>
|
||||
// matching a slice or fixed-length array
|
||||
PatternKind::Slice {
|
||||
prefix: self.pat_refs(prefix),
|
||||
slice: self.opt_pat_ref(slice),
|
||||
suffix: self.pat_refs(suffix),
|
||||
},
|
||||
|
||||
ty::TyArray(_, len) => {
|
||||
// fixed-length array
|
||||
assert!(len >= prefix.len() + suffix.len());
|
||||
PatternKind::Array {
|
||||
prefix: self.pat_refs(prefix),
|
||||
slice: self.opt_pat_ref(slice),
|
||||
suffix: self.pat_refs(suffix),
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn variant_or_leaf<'a>(&self,
|
||||
cx: &mut Cx<'a, 'tcx>,
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>)
|
||||
-> PatternKind<'tcx> {
|
||||
let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
|
||||
match def {
|
||||
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,
|
||||
}
|
||||
} else {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
}
|
||||
|
||||
// NB: resolving to DefStruct means the struct *constructor*,
|
||||
// not the struct as a type.
|
||||
def::DefStruct(..) | def::DefTy(..) => {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(self.pat.span,
|
||||
&format!("inappropriate def for pattern: {:?}", def));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
||||
type Output = Pattern<'tcx>;
|
||||
|
||||
fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
|
||||
let kind = match self.pat.node {
|
||||
fn to_pat(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
|
||||
let kind = match pat.node {
|
||||
hir::PatWild => PatternKind::Wild,
|
||||
|
||||
hir::PatLit(ref value) => {
|
||||
let value = const_eval::eval_const_expr(cx.tcx, value);
|
||||
let value = const_eval::eval_const_expr(self.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);
|
||||
let lo = const_eval::eval_const_expr(self.cx.tcx, lo);
|
||||
let lo = Literal::Value { value: lo };
|
||||
let hi = const_eval::eval_const_expr(cx.tcx, hi);
|
||||
let hi = const_eval::eval_const_expr(self.cx.tcx, hi);
|
||||
let hi = Literal::Value { value: hi };
|
||||
PatternKind::Range { lo: lo, hi: hi }
|
||||
},
|
||||
|
||||
hir::PatEnum(..) | hir::PatIdent(..) | hir::PatQPath(..)
|
||||
if pat_is_resolved_const(&cx.tcx.def_map.borrow(), self.pat) =>
|
||||
if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
|
||||
{
|
||||
let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
|
||||
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefConst(def_id) | def::DefAssociatedConst(def_id) =>
|
||||
match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) {
|
||||
match const_eval::lookup_const_by_id(self.cx.tcx, def_id, Some(pat.id)) {
|
||||
Some(const_expr) => {
|
||||
let opt_value =
|
||||
const_eval::eval_const_expr_partial(
|
||||
cx.tcx, const_expr,
|
||||
self.cx.tcx, const_expr,
|
||||
const_eval::EvalHint::ExprTypeChecked,
|
||||
None);
|
||||
let literal = if let Ok(value) = opt_value {
|
||||
Literal::Value { value: value }
|
||||
} else {
|
||||
let substs = cx.tcx.mk_substs(Substs::empty());
|
||||
let substs = self.cx.tcx.mk_substs(Substs::empty());
|
||||
Literal::Item { def_id: def_id, substs: substs }
|
||||
};
|
||||
PatternKind::Constant { value: literal }
|
||||
}
|
||||
None => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
self.cx.tcx.sess.span_bug(
|
||||
pat.span,
|
||||
&format!("cannot eval constant: {:?}", def_id))
|
||||
}
|
||||
},
|
||||
_ =>
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
self.cx.tcx.sess.span_bug(
|
||||
pat.span,
|
||||
&format!("def not a constant: {:?}", def)),
|
||||
}
|
||||
}
|
||||
|
||||
hir::PatRegion(ref subpattern, _) |
|
||||
hir::PatBox(ref subpattern) => {
|
||||
PatternKind::Deref { subpattern: self.pat_ref(subpattern) }
|
||||
PatternKind::Deref { subpattern: self.to_pat(subpattern) }
|
||||
}
|
||||
|
||||
hir::PatVec(ref prefix, ref slice, ref suffix) => {
|
||||
let ty = cx.tcx.node_id_to_type(self.pat.id);
|
||||
let ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
match ty.sty {
|
||||
ty::TyRef(_, mt) =>
|
||||
PatternKind::Deref {
|
||||
subpattern: Pattern {
|
||||
ty: mt.ty,
|
||||
span: self.pat.span,
|
||||
kind: self.slice_or_array_pattern(cx, mt.ty, prefix,
|
||||
slice, suffix),
|
||||
}.to_ref()
|
||||
span: pat.span,
|
||||
kind: Box::new(self.slice_or_array_pattern(pat, mt.ty, prefix,
|
||||
slice, suffix)),
|
||||
},
|
||||
},
|
||||
|
||||
ty::TySlice(..) |
|
||||
ty::TyArray(..) =>
|
||||
self.slice_or_array_pattern(cx, ty, prefix, slice, suffix),
|
||||
self.slice_or_array_pattern(pat, ty, prefix, slice, suffix),
|
||||
|
||||
ref sty =>
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
self.cx.tcx.sess.span_bug(
|
||||
pat.span,
|
||||
&format!("unexpanded type for vector pattern: {:?}", sty)),
|
||||
}
|
||||
}
|
||||
|
|
@ -221,9 +147,9 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
|||
let subpatterns =
|
||||
subpatterns.iter()
|
||||
.enumerate()
|
||||
.map(|(i, subpattern)| FieldPatternRef {
|
||||
.map(|(i, subpattern)| FieldPattern {
|
||||
field: Field::new(i),
|
||||
pattern: self.pat_ref(subpattern),
|
||||
pattern: self.to_pat(subpattern),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -231,13 +157,13 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
|||
}
|
||||
|
||||
hir::PatIdent(bm, ref ident, ref sub)
|
||||
if pat_is_binding(&cx.tcx.def_map.borrow(), self.pat) =>
|
||||
if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) =>
|
||||
{
|
||||
let id = match self.binding_map {
|
||||
None => self.pat.id,
|
||||
None => pat.id,
|
||||
Some(ref map) => map[&ident.node.name],
|
||||
};
|
||||
let var_ty = cx.tcx.node_id_to_type(self.pat.id);
|
||||
let var_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let region = match var_ty.sty {
|
||||
ty::TyRef(&r, _) => Some(r),
|
||||
_ => None,
|
||||
|
|
@ -258,12 +184,12 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
|||
name: ident.node.name,
|
||||
var: id,
|
||||
ty: var_ty,
|
||||
subpattern: self.opt_pat_ref(sub),
|
||||
subpattern: self.to_opt_pat(sub),
|
||||
}
|
||||
}
|
||||
|
||||
hir::PatIdent(..) => {
|
||||
self.variant_or_leaf(cx, vec![])
|
||||
self.variant_or_leaf(pat, vec![])
|
||||
}
|
||||
|
||||
hir::PatEnum(_, ref opt_subpatterns) => {
|
||||
|
|
@ -271,26 +197,26 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
|||
opt_subpatterns.iter()
|
||||
.flat_map(|v| v.iter())
|
||||
.enumerate()
|
||||
.map(|(i, field)| FieldPatternRef {
|
||||
.map(|(i, field)| FieldPattern {
|
||||
field: Field::new(i),
|
||||
pattern: self.pat_ref(field),
|
||||
pattern: self.to_pat(field),
|
||||
})
|
||||
.collect();
|
||||
self.variant_or_leaf(cx, subpatterns)
|
||||
self.variant_or_leaf(pat, subpatterns)
|
||||
}
|
||||
|
||||
hir::PatStruct(_, ref fields, _) => {
|
||||
let pat_ty = cx.tcx.node_id_to_type(self.pat.id);
|
||||
let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
let adt_def = match pat_ty.sty {
|
||||
ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
self.cx.tcx.sess.span_bug(
|
||||
pat.span,
|
||||
"struct pattern not applied to struct or enum");
|
||||
}
|
||||
};
|
||||
|
||||
let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
|
||||
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
let variant_def = adt_def.variant_of_def(def);
|
||||
|
||||
let subpatterns =
|
||||
|
|
@ -298,31 +224,104 @@ impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
|
|||
.map(|field| {
|
||||
let index = variant_def.index_of_field_named(field.node.name);
|
||||
let index = index.unwrap_or_else(|| {
|
||||
cx.tcx.sess.span_bug(
|
||||
self.pat.span,
|
||||
self.cx.tcx.sess.span_bug(
|
||||
pat.span,
|
||||
&format!("no field with name {:?}", field.node.name));
|
||||
});
|
||||
FieldPatternRef {
|
||||
FieldPattern {
|
||||
field: Field::new(index),
|
||||
pattern: self.pat_ref(&field.node.pat),
|
||||
pattern: self.to_pat(&field.node.pat),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.variant_or_leaf(cx, subpatterns)
|
||||
self.variant_or_leaf(pat, subpatterns)
|
||||
}
|
||||
|
||||
hir::PatQPath(..) => {
|
||||
cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
|
||||
self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
};
|
||||
|
||||
let ty = cx.tcx.node_id_to_type(self.pat.id);
|
||||
let ty = self.cx.tcx.node_id_to_type(pat.id);
|
||||
|
||||
Pattern {
|
||||
span: self.pat.span,
|
||||
span: pat.span,
|
||||
ty: ty,
|
||||
kind: kind,
|
||||
kind: Box::new(kind),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_pats(&mut self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<Pattern<'tcx>> {
|
||||
pats.iter().map(|p| self.to_pat(p)).collect()
|
||||
}
|
||||
|
||||
fn to_opt_pat(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pattern<'tcx>> {
|
||||
pat.as_ref().map(|p| self.to_pat(p))
|
||||
}
|
||||
|
||||
fn slice_or_array_pattern(&mut self,
|
||||
pat: &'tcx hir::Pat,
|
||||
ty: Ty<'tcx>,
|
||||
prefix: &'tcx Vec<P<hir::Pat>>,
|
||||
slice: &'tcx Option<P<hir::Pat>>,
|
||||
suffix: &'tcx Vec<P<hir::Pat>>)
|
||||
-> PatternKind<'tcx> {
|
||||
match ty.sty {
|
||||
ty::TySlice(..) => {
|
||||
// matching a slice or fixed-length array
|
||||
PatternKind::Slice {
|
||||
prefix: self.to_pats(prefix),
|
||||
slice: self.to_opt_pat(slice),
|
||||
suffix: self.to_pats(suffix),
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyArray(_, len) => {
|
||||
// fixed-length array
|
||||
assert!(len >= prefix.len() + suffix.len());
|
||||
PatternKind::Array {
|
||||
prefix: self.to_pats(prefix),
|
||||
slice: self.to_opt_pat(slice),
|
||||
suffix: self.to_pats(suffix),
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn variant_or_leaf(&mut self,
|
||||
pat: &'tcx hir::Pat,
|
||||
subpatterns: Vec<FieldPattern<'tcx>>)
|
||||
-> PatternKind<'tcx> {
|
||||
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
match def {
|
||||
def::DefVariant(enum_id, variant_id, _) => {
|
||||
let adt_def = self.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,
|
||||
}
|
||||
} else {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
}
|
||||
|
||||
// NB: resolving to DefStruct means the struct *constructor*,
|
||||
// not the struct as a type.
|
||||
def::DefStruct(..) | def::DefTy(..) => {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.cx.tcx.sess.span_bug(pat.span,
|
||||
&format!("inappropriate def for pattern: {:?}", def));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use hair::*;
|
||||
|
||||
use hair::cx::pattern::PatNode;
|
||||
use rustc_front::hir;
|
||||
use syntax::ptr::P;
|
||||
|
||||
|
|
@ -43,22 +42,6 @@ impl<'a,'tcx:'a> ToRef for Expr<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> ToRef for PatNode<'tcx> {
|
||||
type Output = PatternRef<'tcx>;
|
||||
|
||||
fn to_ref(self) -> PatternRef<'tcx> {
|
||||
PatternRef::Hair(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a> ToRef for Pattern<'tcx> {
|
||||
type Output = PatternRef<'tcx>;
|
||||
|
||||
fn to_ref(self) -> PatternRef<'tcx> {
|
||||
PatternRef::Mirror(Box::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option<T>
|
||||
where &'tcx T: ToRef<Output=U>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
|
|||
use rustc_front::hir;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use self::cx::{Cx, PatNode};
|
||||
use self::cx::Cx;
|
||||
|
||||
pub mod cx;
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ pub enum StmtKind<'tcx> {
|
|||
init_scope: CodeExtent,
|
||||
|
||||
/// let <PAT> = ...
|
||||
pattern: PatternRef<'tcx>,
|
||||
pattern: Pattern<'tcx>,
|
||||
|
||||
/// let pat = <INIT> ...
|
||||
initializer: Option<ExprRef<'tcx>>,
|
||||
|
|
@ -252,7 +252,7 @@ pub struct FieldExprRef<'tcx> {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Arm<'tcx> {
|
||||
pub patterns: Vec<PatternRef<'tcx>>,
|
||||
pub patterns: Vec<Pattern<'tcx>>,
|
||||
pub guard: Option<ExprRef<'tcx>>,
|
||||
pub body: ExprRef<'tcx>,
|
||||
}
|
||||
|
|
@ -261,7 +261,7 @@ pub struct Arm<'tcx> {
|
|||
pub struct Pattern<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub span: Span,
|
||||
pub kind: PatternKind<'tcx>,
|
||||
pub kind: Box<PatternKind<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
@ -281,23 +281,23 @@ pub enum PatternKind<'tcx> {
|
|||
mode: BindingMode,
|
||||
var: ast::NodeId,
|
||||
ty: Ty<'tcx>,
|
||||
subpattern: Option<PatternRef<'tcx>>,
|
||||
subpattern: Option<Pattern<'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>>,
|
||||
subpatterns: Vec<FieldPattern<'tcx>>,
|
||||
},
|
||||
|
||||
// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
|
||||
Leaf {
|
||||
subpatterns: Vec<FieldPatternRef<'tcx>>,
|
||||
subpatterns: Vec<FieldPattern<'tcx>>,
|
||||
},
|
||||
|
||||
Deref {
|
||||
subpattern: PatternRef<'tcx>,
|
||||
subpattern: Pattern<'tcx>,
|
||||
}, // box P, &P, &mut P, etc
|
||||
|
||||
Constant {
|
||||
|
|
@ -311,16 +311,16 @@ pub enum PatternKind<'tcx> {
|
|||
|
||||
// matches against a slice, checking the length and extracting elements
|
||||
Slice {
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>,
|
||||
prefix: Vec<Pattern<'tcx>>,
|
||||
slice: Option<Pattern<'tcx>>,
|
||||
suffix: Vec<Pattern<'tcx>>,
|
||||
},
|
||||
|
||||
// fixed match against an array, irrefutable
|
||||
Array {
|
||||
prefix: Vec<PatternRef<'tcx>>,
|
||||
slice: Option<PatternRef<'tcx>>,
|
||||
suffix: Vec<PatternRef<'tcx>>,
|
||||
prefix: Vec<Pattern<'tcx>>,
|
||||
slice: Option<Pattern<'tcx>>,
|
||||
suffix: Vec<Pattern<'tcx>>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -331,15 +331,9 @@ pub enum BindingMode {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PatternRef<'tcx> {
|
||||
Hair(PatNode<'tcx>),
|
||||
Mirror(Box<Pattern<'tcx>>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FieldPatternRef<'tcx> {
|
||||
pub struct FieldPattern<'tcx> {
|
||||
pub field: Field,
|
||||
pub pattern: PatternRef<'tcx>,
|
||||
pub pattern: Pattern<'tcx>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -400,25 +394,6 @@ 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> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> {
|
||||
type Output = 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Mirror<'tcx> for Block<'tcx> {
|
||||
type Output = Block<'tcx>;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ extern crate rustc_front;
|
|||
use build;
|
||||
use dot;
|
||||
use repr::Mir;
|
||||
use hair::cx::{PatNode, Cx};
|
||||
use hair::cx::Cx;
|
||||
use std::fs::File;
|
||||
|
||||
use self::rustc::middle::infer;
|
||||
|
|
@ -211,7 +211,7 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
|
|||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, arg)| {
|
||||
(fn_sig.inputs[index], PatNode::irrefutable(&arg.pat))
|
||||
(fn_sig.inputs[index], &*arg.pat)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue