1 use crate::build
::expr
::as_place
::PlaceBase
;
2 use crate::build
::expr
::as_place
::PlaceBuilder
;
3 use crate::build
::matches
::MatchPair
;
4 use crate::build
::Builder
;
5 use rustc_middle
::mir
::*;
6 use rustc_middle
::thir
::*;
8 use rustc_middle
::ty
::TypeVisitable
;
9 use smallvec
::SmallVec
;
10 use std
::convert
::TryInto
;
12 impl<'a
, 'tcx
> Builder
<'a
, 'tcx
> {
13 pub(crate) fn field_match_pairs
<'pat
>(
15 place
: PlaceBuilder
<'tcx
>,
16 subpatterns
: &'pat
[FieldPat
<'tcx
>],
17 ) -> Vec
<MatchPair
<'pat
, 'tcx
>> {
22 place
.clone_project(PlaceElem
::Field(fieldpat
.field
, fieldpat
.pattern
.ty
));
23 MatchPair
::new(place
, &fieldpat
.pattern
, self)
28 pub(crate) fn prefix_slice_suffix
<'pat
>(
30 match_pairs
: &mut SmallVec
<[MatchPair
<'pat
, 'tcx
>; 1]>,
31 place
: &PlaceBuilder
<'tcx
>,
32 prefix
: &'pat
[Box
<Pat
<'tcx
>>],
33 opt_slice
: &'pat Option
<Box
<Pat
<'tcx
>>>,
34 suffix
: &'pat
[Box
<Pat
<'tcx
>>],
37 let (min_length
, exact_size
) = if let Some(place_resolved
) = place
.try_to_place(self) {
38 match place_resolved
.ty(&self.local_decls
, tcx
).ty
.kind() {
39 ty
::Array(_
, length
) => (length
.eval_usize(tcx
, self.param_env
), true),
40 _
=> ((prefix
.len() + suffix
.len()).try_into().unwrap(), false),
43 ((prefix
.len() + suffix
.len()).try_into().unwrap(), false)
46 match_pairs
.extend(prefix
.iter().enumerate().map(|(idx
, subpattern
)| {
48 ProjectionElem
::ConstantIndex { offset: idx as u64, min_length, from_end: false }
;
49 MatchPair
::new(place
.clone_project(elem
), subpattern
, self)
52 if let Some(subslice_pat
) = opt_slice
{
53 let suffix_len
= suffix
.len() as u64;
54 let subslice
= place
.clone_project(PlaceElem
::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
, self));
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
, self)
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 pub(crate) fn false_edges(
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 pub(in crate::build
) fn new(
99 mut place
: PlaceBuilder
<'tcx
>,
100 pattern
: &'pat Pat
<'tcx
>,
101 cx
: &Builder
<'_
, 'tcx
>,
102 ) -> MatchPair
<'pat
, 'tcx
> {
103 // Force the place type to the pattern's type.
104 // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
105 if let Some(resolved
) = place
.resolve_upvar(cx
) {
109 // Only add the OpaqueCast projection if the given place is an opaque type and the
110 // expected type from the pattern is not.
111 let may_need_cast
= match place
.base() {
112 PlaceBase
::Local(local
) => {
113 let ty
= Place
::ty_from(local
, place
.projection(), &cx
.local_decls
, cx
.tcx
).ty
;
114 ty
!= pattern
.ty
&& ty
.has_opaque_types()
119 place
= place
.project(ProjectionElem
::OpaqueCast(pattern
.ty
));
121 MatchPair { place, pattern }