]>
Commit | Line | Data |
---|---|---|
6a06907d | 1 | use crate::build::expr::as_place::PlaceBuilder; |
dfeec247 XL |
2 | use crate::build::matches::MatchPair; |
3 | use crate::build::Builder; | |
ba9703b0 | 4 | use rustc_middle::mir::*; |
17df50a5 | 5 | use rustc_middle::thir::*; |
ba9703b0 | 6 | use rustc_middle::ty; |
dfeec247 XL |
7 | use smallvec::SmallVec; |
8 | use std::convert::TryInto; | |
dfeec247 XL |
9 | |
10 | impl<'a, 'tcx> Builder<'a, 'tcx> { | |
11 | crate fn field_match_pairs<'pat>( | |
12 | &mut self, | |
6a06907d | 13 | place: PlaceBuilder<'tcx>, |
dfeec247 XL |
14 | subpatterns: &'pat [FieldPat<'tcx>], |
15 | ) -> Vec<MatchPair<'pat, 'tcx>> { | |
16 | subpatterns | |
17 | .iter() | |
18 | .map(|fieldpat| { | |
6a06907d | 19 | let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty); |
dfeec247 XL |
20 | MatchPair::new(place, &fieldpat.pattern) |
21 | }) | |
22 | .collect() | |
23 | } | |
24 | ||
25 | crate fn prefix_slice_suffix<'pat>( | |
26 | &mut self, | |
27 | match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>, | |
6a06907d | 28 | place: &PlaceBuilder<'tcx>, |
dfeec247 XL |
29 | prefix: &'pat [Pat<'tcx>], |
30 | opt_slice: Option<&'pat Pat<'tcx>>, | |
31 | suffix: &'pat [Pat<'tcx>], | |
32 | ) { | |
6a06907d XL |
33 | let tcx = self.tcx; |
34 | let (min_length, exact_size) = match place | |
35 | .clone() | |
36 | .into_place(tcx, self.typeck_results) | |
37 | .ty(&self.local_decls, tcx) | |
38 | .ty | |
39 | .kind() | |
40 | { | |
41 | ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), | |
dfeec247 XL |
42 | _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), |
43 | }; | |
44 | ||
45 | match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { | |
46 | let elem = | |
1b1a35ee | 47 | ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; |
6a06907d | 48 | let place = place.clone().project(elem); |
dfeec247 XL |
49 | MatchPair::new(place, subpattern) |
50 | })); | |
51 | ||
52 | if let Some(subslice_pat) = opt_slice { | |
1b1a35ee | 53 | let suffix_len = suffix.len() as u64; |
6a06907d XL |
54 | let subslice = place.clone().project(ProjectionElem::Subslice { |
55 | from: prefix.len() as u64, | |
56 | to: if exact_size { min_length - suffix_len } else { suffix_len }, | |
57 | from_end: !exact_size, | |
58 | }); | |
dfeec247 XL |
59 | match_pairs.push(MatchPair::new(subslice, subslice_pat)); |
60 | } | |
61 | ||
62 | match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| { | |
1b1a35ee | 63 | let end_offset = (idx + 1) as u64; |
dfeec247 XL |
64 | let elem = ProjectionElem::ConstantIndex { |
65 | offset: if exact_size { min_length - end_offset } else { end_offset }, | |
66 | min_length, | |
67 | from_end: !exact_size, | |
68 | }; | |
6a06907d | 69 | let place = place.clone().project(elem); |
dfeec247 XL |
70 | MatchPair::new(place, subpattern) |
71 | })); | |
72 | } | |
73 | ||
74 | /// Creates a false edge to `imaginary_target` and a real edge to | |
75 | /// real_target. If `imaginary_target` is none, or is the same as the real | |
76 | /// target, a Goto is generated instead to simplify the generated MIR. | |
77 | crate fn false_edges( | |
78 | &mut self, | |
79 | from_block: BasicBlock, | |
80 | real_target: BasicBlock, | |
81 | imaginary_target: Option<BasicBlock>, | |
82 | source_info: SourceInfo, | |
83 | ) { | |
84 | match imaginary_target { | |
85 | Some(target) if target != real_target => { | |
86 | self.cfg.terminate( | |
87 | from_block, | |
88 | source_info, | |
f035d41b | 89 | TerminatorKind::FalseEdge { real_target, imaginary_target: target }, |
dfeec247 XL |
90 | ); |
91 | } | |
92 | _ => self.cfg.goto(from_block, source_info, real_target), | |
93 | } | |
94 | } | |
95 | } | |
96 | ||
97 | impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { | |
6a06907d | 98 | crate fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> { |
dfeec247 XL |
99 | MatchPair { place, pattern } |
100 | } | |
101 | } |