1 //! Simplifying Candidates
3 //! *Simplifying* a match pair `place @ pattern` means breaking it down
4 //! into bindings or other, simpler match pairs. For example:
6 //! - `place @ (P1, P2)` can be simplified to `[place.0 @ P1, place.1 @ P2]`
7 //! - `place @ x` can be simplified to `[]` by binding `x` to `place`
9 //! The `simplify_candidate` routine just repeatedly applies these
10 //! sort of simplifications until there is nothing left to
11 //! simplify. Match pairs cannot be simplified if they require some
12 //! sort of test: for example, testing which variant an enum is, or
13 //! testing a value against a constant.
16 use build::matches::{Ascription, Binding, MatchPair, Candidate};
19 use rustc::ty::layout::{Integer, IntegerExt, Size};
20 use syntax::attr::{SignedInt, UnsignedInt};
21 use rustc::hir::RangeEnd;
25 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
26 pub fn simplify_candidate<'pat>(&mut self,
27 candidate: &mut Candidate<'pat, 'tcx>) {
28 // repeatedly simplify match pairs until fixed point is reached
30 let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
31 let mut changed = false;
32 for match_pair in match_pairs {
33 match self.simplify_match_pair(match_pair, candidate) {
38 candidate.match_pairs.push(match_pair);
43 return; // if we were not able to simplify any, done.
48 /// Tries to simplify `match_pair`, returning true if
49 /// successful. If successful, new match pairs and bindings will
50 /// have been pushed into the candidate. If no simplification is
51 /// possible, Err is returned and no changes are made to
53 fn simplify_match_pair<'pat>(&mut self,
54 match_pair: MatchPair<'pat, 'tcx>,
55 candidate: &mut Candidate<'pat, 'tcx>)
56 -> Result<(), MatchPair<'pat, 'tcx>> {
57 let tcx = self.hir.tcx();
58 match *match_pair.pattern.kind {
59 PatternKind::AscribeUserType {
65 // Apply the type ascription to the value at `match_pair.place`, which is the
66 // value being matched, taking the variance field into account.
67 candidate.ascriptions.push(Ascription {
69 user_ty: user_ty.clone(),
70 source: match_pair.place.clone(),
74 candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
79 PatternKind::Wild => {
84 PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => {
85 candidate.bindings.push(Binding {
88 span: match_pair.pattern.span,
89 source: match_pair.place.clone(),
95 if let Some(subpattern) = subpattern.as_ref() {
96 // this is the `x @ P` case; have to keep matching against `P` now
97 candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
103 PatternKind::Constant { .. } => {
104 // FIXME normalize patterns when possible
108 PatternKind::Range(PatternRange { lo, hi, ty, end }) => {
109 let (range, bias) = match ty.sty {
111 (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
114 // FIXME(49937): refactor these bit manipulations into interpret.
115 let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
116 let max = !0u128 >> (128 - size.bits());
117 let bias = 1u128 << (size.bits() - 1);
118 (Some((0, max, size)), bias)
121 // FIXME(49937): refactor these bit manipulations into interpret.
122 let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
123 let max = !0u128 >> (128 - size.bits());
124 (Some((0, max, size)), 0)
128 if let Some((min, max, sz)) = range {
129 if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
130 // We want to compare ranges numerically, but the order of the bitwise
131 // representation of signed integers does not match their numeric order.
132 // Thus, to correct the ordering, we need to shift the range of signed
133 // integers to correct the comparison. This is achieved by XORing with a
134 // bias (see pattern/_match.rs for another pertinent example of this
136 let (lo, hi) = (lo ^ bias, hi ^ bias);
137 if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
138 // Irrefutable pattern match.
146 PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
147 if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
149 self.prefix_slice_suffix(&mut candidate.match_pairs,
160 PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
161 let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| {
162 i == variant_index || {
163 self.hir.tcx().features().never_type &&
164 self.hir.tcx().features().exhaustive_patterns &&
165 self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
169 let place = match_pair.place.downcast(adt_def, variant_index);
170 candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
177 PatternKind::Array { ref prefix, ref slice, ref suffix } => {
178 self.prefix_slice_suffix(&mut candidate.match_pairs,
186 PatternKind::Leaf { ref subpatterns } => {
187 // tuple struct, match subpats (if any)
188 candidate.match_pairs
189 .extend(self.field_match_pairs(match_pair.place, subpatterns));
193 PatternKind::Deref { ref subpattern } => {
194 let place = match_pair.place.deref();
195 candidate.match_pairs.push(MatchPair::new(place, subpattern));