1 use crate::build
::expr
::as_place
::PlaceBuilder
;
2 use crate::build
::matches
::MatchPair
;
3 use crate::build
::Builder
;
5 use rustc_middle
::mir
::*;
7 use smallvec
::SmallVec
;
8 use std
::convert
::TryInto
;
10 impl<'a
, 'tcx
> Builder
<'a
, 'tcx
> {
11 crate fn field_match_pairs
<'pat
>(
13 place
: PlaceBuilder
<'tcx
>,
14 subpatterns
: &'pat
[FieldPat
<'tcx
>],
15 ) -> Vec
<MatchPair
<'pat
, 'tcx
>> {
19 let place
= place
.clone().field(fieldpat
.field
, fieldpat
.pattern
.ty
);
20 MatchPair
::new(place
, &fieldpat
.pattern
)
25 crate fn prefix_slice_suffix
<'pat
>(
27 match_pairs
: &mut SmallVec
<[MatchPair
<'pat
, 'tcx
>; 1]>,
28 place
: &PlaceBuilder
<'tcx
>,
29 prefix
: &'pat
[Pat
<'tcx
>],
30 opt_slice
: Option
<&'pat Pat
<'tcx
>>,
31 suffix
: &'pat
[Pat
<'tcx
>],
34 let (min_length
, exact_size
) = match place
36 .into_place(tcx
, self.typeck_results
)
37 .ty(&self.local_decls
, tcx
)
41 ty
::Array(_
, length
) => (length
.eval_usize(tcx
, self.param_env
), true),
42 _
=> ((prefix
.len() + suffix
.len()).try_into().unwrap(), false),
45 match_pairs
.extend(prefix
.iter().enumerate().map(|(idx
, subpattern
)| {
47 ProjectionElem
::ConstantIndex { offset: idx as u64, min_length, from_end: false }
;
48 let place
= place
.clone().project(elem
);
49 MatchPair
::new(place
, subpattern
)
52 if let Some(subslice_pat
) = opt_slice
{
53 let suffix_len
= suffix
.len() as u64;
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
,
59 match_pairs
.push(MatchPair
::new(subslice
, subslice_pat
));
62 match_pairs
.extend(suffix
.iter().rev().enumerate().map(|(idx
, subpattern
)| {
63 let end_offset
= (idx
+ 1) as u64;
64 let elem
= ProjectionElem
::ConstantIndex
{
65 offset
: if exact_size { min_length - end_offset }
else { end_offset }
,
67 from_end
: !exact_size
,
69 let place
= place
.clone().project(elem
);
70 MatchPair
::new(place
, subpattern
)
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.
79 from_block
: BasicBlock
,
80 real_target
: BasicBlock
,
81 imaginary_target
: Option
<BasicBlock
>,
82 source_info
: SourceInfo
,
84 match imaginary_target
{
85 Some(target
) if target
!= real_target
=> {
89 TerminatorKind
::FalseEdge { real_target, imaginary_target: target }
,
92 _
=> self.cfg
.goto(from_block
, source_info
, real_target
),
97 impl<'pat
, 'tcx
> MatchPair
<'pat
, 'tcx
> {
98 crate fn new(place
: PlaceBuilder
<'tcx
>, pattern
: &'pat Pat
<'tcx
>) -> MatchPair
<'pat
, 'tcx
> {
99 MatchPair { place, pattern }