1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Simplifying Candidates
13 //! *Simplifying* a match pair `lvalue @ pattern` means breaking it down
14 //! into bindings or other, simpler match pairs. For example:
16 //! - `lvalue @ (P1, P2)` can be simplified to `[lvalue.0 @ P1, lvalue.1 @ P2]`
17 //! - `lvalue @ x` can be simplified to `[]` by binding `x` to `lvalue`
19 //! The `simplify_candidate` routine just repeatedly applies these
20 //! sort of simplifications until there is nothing left to
21 //! simplify. Match pairs cannot be simplified if they require some
22 //! sort of test: for example, testing which variant an enum is, or
23 //! testing a value against a constant.
25 use build
::{BlockAnd, BlockAndExtension, Builder}
;
26 use build
::matches
::{Binding, MatchPair, Candidate}
;
28 use rustc
::mir
::repr
::*;
32 impl<'a
,'tcx
> Builder
<'a
,'tcx
> {
33 pub fn simplify_candidate
<'pat
>(&mut self,
34 mut block
: BasicBlock
,
35 candidate
: &mut Candidate
<'pat
, 'tcx
>)
37 // repeatedly simplify match pairs until fixed point is reached
39 let match_pairs
= mem
::replace(&mut candidate
.match_pairs
, vec
![]);
40 let mut progress
= match_pairs
.len(); // count how many were simplified
41 for match_pair
in match_pairs
{
42 match self.simplify_match_pair(block
, match_pair
, candidate
) {
47 candidate
.match_pairs
.push(match_pair
);
48 progress
-= 1; // this one was not simplified
53 return block
.unit(); // if we were not able to simplify any, done.
58 /// Tries to simplify `match_pair`, returning true if
59 /// successful. If successful, new match pairs and bindings will
60 /// have been pushed into the candidate. If no simplification is
61 /// possible, Err is returned and no changes are made to
63 fn simplify_match_pair
<'pat
>(&mut self,
64 mut block
: BasicBlock
,
65 match_pair
: MatchPair
<'pat
, 'tcx
>,
66 candidate
: &mut Candidate
<'pat
, 'tcx
>)
67 -> Result
<BasicBlock
, MatchPair
<'pat
, 'tcx
>> {
68 match *match_pair
.pattern
.kind
{
69 PatternKind
::Wild
=> {
74 PatternKind
::Binding { name, mutability, mode, var, ty, ref subpattern }
=> {
75 candidate
.bindings
.push(Binding
{
77 mutability
: mutability
,
78 span
: match_pair
.pattern
.span
,
79 source
: match_pair
.lvalue
.clone(),
85 if let Some(subpattern
) = subpattern
.as_ref() {
86 // this is the `x @ P` case; have to keep matching against `P` now
87 candidate
.match_pairs
.push(MatchPair
::new(match_pair
.lvalue
, subpattern
));
93 PatternKind
::Constant { .. }
=> {
94 // FIXME normalize patterns when possible
98 PatternKind
::Range { .. }
|
99 PatternKind
::Variant { .. }
=> {
100 // cannot simplify, test is required
104 PatternKind
::Slice { .. }
if !match_pair
.slice_len_checked
=> {
108 PatternKind
::Array { ref prefix, ref slice, ref suffix }
|
109 PatternKind
::Slice { ref prefix, ref slice, ref suffix }
=> {
110 unpack
!(block
= self.prefix_suffix_slice(&mut candidate
.match_pairs
,
112 match_pair
.lvalue
.clone(),
119 PatternKind
::Leaf { ref subpatterns }
=> {
120 // tuple struct, match subpats (if any)
121 candidate
.match_pairs
122 .extend(self.field_match_pairs(match_pair
.lvalue
, subpatterns
));
126 PatternKind
::Deref { ref subpattern }
=> {
127 let lvalue
= match_pair
.lvalue
.deref();
128 candidate
.match_pairs
.push(MatchPair
::new(lvalue
, subpattern
));