]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/build/matches/simplify.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc_mir / build / matches / simplify.rs
CommitLineData
e9174d1e
SL
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.
4//
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.
10
11//! Simplifying Candidates
12//!
13//! *Simplifying* a match pair `lvalue @ pattern` means breaking it down
14//! into bindings or other, simpler match pairs. For example:
15//!
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`
18//!
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.
24
92a42be0 25use build::{BlockAnd, BlockAndExtension, Builder};
e9174d1e
SL
26use build::matches::{Binding, MatchPair, Candidate};
27use hair::*;
c30ab7b3 28use rustc::mir::*;
8bb4bdeb 29use rustc_data_structures::fx::FxHashMap;
e9174d1e
SL
30
31use std::mem;
32
a7813a04 33impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
92a42be0 34 pub fn simplify_candidate<'pat>(&mut self,
3157f602 35 block: BasicBlock,
92a42be0
SL
36 candidate: &mut Candidate<'pat, 'tcx>)
37 -> BlockAnd<()> {
e9174d1e
SL
38 // repeatedly simplify match pairs until fixed point is reached
39 loop {
40 let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
41 let mut progress = match_pairs.len(); // count how many were simplified
42 for match_pair in match_pairs {
3157f602
XL
43 match self.simplify_match_pair(match_pair, candidate) {
44 Ok(()) => {}
e9174d1e
SL
45 Err(match_pair) => {
46 candidate.match_pairs.push(match_pair);
47 progress -= 1; // this one was not simplified
48 }
49 }
50 }
51 if progress == 0 {
52 return block.unit(); // if we were not able to simplify any, done.
53 }
54 }
55 }
56
57 /// Tries to simplify `match_pair`, returning true if
58 /// successful. If successful, new match pairs and bindings will
b039eaaf
SL
59 /// have been pushed into the candidate. If no simplification is
60 /// possible, Err is returned and no changes are made to
61 /// candidate.
92a42be0 62 fn simplify_match_pair<'pat>(&mut self,
92a42be0
SL
63 match_pair: MatchPair<'pat, 'tcx>,
64 candidate: &mut Candidate<'pat, 'tcx>)
3157f602 65 -> Result<(), MatchPair<'pat, 'tcx>> {
92a42be0
SL
66 match *match_pair.pattern.kind {
67 PatternKind::Wild => {
e9174d1e 68 // nothing left to do
3157f602 69 Ok(())
e9174d1e
SL
70 }
71
92a42be0 72 PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
e9174d1e
SL
73 candidate.bindings.push(Binding {
74 name: name,
75 mutability: mutability,
76 span: match_pair.pattern.span,
77 source: match_pair.lvalue.clone(),
78 var_id: var,
79 var_ty: ty,
80 binding_mode: mode,
81 });
82
92a42be0 83 if let Some(subpattern) = subpattern.as_ref() {
e9174d1e 84 // this is the `x @ P` case; have to keep matching against `P` now
e9174d1e
SL
85 candidate.match_pairs.push(MatchPair::new(match_pair.lvalue, subpattern));
86 }
87
3157f602 88 Ok(())
e9174d1e
SL
89 }
90
91 PatternKind::Constant { .. } => {
92 // FIXME normalize patterns when possible
93 Err(match_pair)
94 }
95
54a0048b 96 PatternKind::Range { .. } |
3157f602 97 PatternKind::Slice { .. } => {
54a0048b
SL
98 Err(match_pair)
99 }
100
32a655c1
SL
101 PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
102 if self.hir.tcx().sess.features.borrow().never_type {
103 let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
104 i == variant_index || {
8bb4bdeb 105 let mut visited = FxHashMap::default();
32a655c1
SL
106 let node_set = v.uninhabited_from(&mut visited,
107 self.hir.tcx(),
108 substs,
109 adt_def.adt_kind());
110 !node_set.is_empty()
111 }
112 });
113 if irrefutable {
114 let lvalue = match_pair.lvalue.downcast(adt_def, variant_index);
115 candidate.match_pairs.extend(self.field_match_pairs(lvalue, subpatterns));
116 Ok(())
117 } else {
118 Err(match_pair)
119 }
120 } else {
121 Err(match_pair)
122 }
123 },
124
3157f602
XL
125 PatternKind::Array { ref prefix, ref slice, ref suffix } => {
126 self.prefix_slice_suffix(&mut candidate.match_pairs,
127 &match_pair.lvalue,
128 prefix,
129 slice.as_ref(),
130 suffix);
131 Ok(())
e9174d1e
SL
132 }
133
92a42be0 134 PatternKind::Leaf { ref subpatterns } => {
e9174d1e 135 // tuple struct, match subpats (if any)
b039eaaf
SL
136 candidate.match_pairs
137 .extend(self.field_match_pairs(match_pair.lvalue, subpatterns));
3157f602 138 Ok(())
e9174d1e
SL
139 }
140
92a42be0 141 PatternKind::Deref { ref subpattern } => {
e9174d1e 142 let lvalue = match_pair.lvalue.deref();
e9174d1e 143 candidate.match_pairs.push(MatchPair::new(lvalue, subpattern));
3157f602 144 Ok(())
e9174d1e
SL
145 }
146 }
147 }
148}