1
1
use crate :: build:: expr:: as_place:: { PlaceBase , PlaceBuilder } ;
2
2
use crate :: build:: matches:: { MatchPair , TestCase } ;
3
3
use crate :: build:: Builder ;
4
+ use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
4
5
use rustc_middle:: mir:: * ;
5
- use rustc_middle:: thir:: * ;
6
+ use rustc_middle:: thir:: { self , * } ;
6
7
use rustc_middle:: ty;
7
8
use rustc_middle:: ty:: TypeVisitableExt ;
8
9
@@ -116,48 +117,102 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
116
117
place = place. project ( ProjectionElem :: OpaqueCast ( pattern. ty ) ) ;
117
118
}
118
119
120
+ let default_irrefutable = || TestCase :: Irrefutable { binding : None , ascription : None } ;
119
121
let mut subpairs = Vec :: new ( ) ;
120
122
let test_case = match pattern. kind {
121
- PatKind :: Never | PatKind :: Wild | PatKind :: Error ( _) => TestCase :: Irrefutable ,
123
+ PatKind :: Never | PatKind :: Wild | PatKind :: Error ( _) => default_irrefutable ( ) ,
122
124
PatKind :: Or { .. } => TestCase :: Or ,
123
125
124
126
PatKind :: Range ( ref range) => {
125
127
if range. is_full_range ( cx. tcx ) == Some ( true ) {
126
- TestCase :: Irrefutable
128
+ default_irrefutable ( )
127
129
} else {
128
130
TestCase :: Range ( range)
129
131
}
130
132
}
131
133
132
134
PatKind :: Constant { value } => TestCase :: Constant { value } ,
133
135
134
- PatKind :: AscribeUserType { ref subpattern, .. } => {
136
+ PatKind :: AscribeUserType {
137
+ ascription : thir:: Ascription { ref annotation, variance } ,
138
+ ref subpattern,
139
+ ..
140
+ } => {
141
+ // Apply the type ascription to the value at `match_pair.place`
142
+ let ascription = place. try_to_place ( cx) . map ( |source| super :: Ascription {
143
+ annotation : annotation. clone ( ) ,
144
+ source,
145
+ variance,
146
+ } ) ;
147
+
135
148
subpairs. push ( MatchPair :: new ( place. clone ( ) , subpattern, cx) ) ;
136
- TestCase :: Irrefutable
149
+ TestCase :: Irrefutable { ascription , binding : None }
137
150
}
138
151
139
- PatKind :: Binding { ref subpattern, .. } => {
152
+ PatKind :: Binding {
153
+ name : _,
154
+ mutability : _,
155
+ mode,
156
+ var,
157
+ ty : _,
158
+ ref subpattern,
159
+ is_primary : _,
160
+ } => {
161
+ let binding = place. try_to_place ( cx) . map ( |source| super :: Binding {
162
+ span : pattern. span ,
163
+ source,
164
+ var_id : var,
165
+ binding_mode : mode,
166
+ } ) ;
167
+
140
168
if let Some ( subpattern) = subpattern. as_ref ( ) {
141
169
// this is the `x @ P` case; have to keep matching against `P` now
142
170
subpairs. push ( MatchPair :: new ( place. clone ( ) , subpattern, cx) ) ;
143
171
}
144
- TestCase :: Irrefutable
172
+ TestCase :: Irrefutable { ascription : None , binding }
145
173
}
146
174
147
- PatKind :: InlineConstant { subpattern : ref pattern, .. } => {
175
+ PatKind :: InlineConstant { subpattern : ref pattern, def, .. } => {
176
+ // Apply a type ascription for the inline constant to the value at `match_pair.place`
177
+ let ascription = place. try_to_place ( cx) . map ( |source| {
178
+ let span = pattern. span ;
179
+ let parent_id = cx. tcx . typeck_root_def_id ( cx. def_id . to_def_id ( ) ) ;
180
+ let args = ty:: InlineConstArgs :: new (
181
+ cx. tcx ,
182
+ ty:: InlineConstArgsParts {
183
+ parent_args : ty:: GenericArgs :: identity_for_item ( cx. tcx , parent_id) ,
184
+ ty : cx. infcx . next_ty_var ( TypeVariableOrigin {
185
+ kind : TypeVariableOriginKind :: MiscVariable ,
186
+ span,
187
+ } ) ,
188
+ } ,
189
+ )
190
+ . args ;
191
+ let user_ty = cx. infcx . canonicalize_user_type_annotation ( ty:: UserType :: TypeOf (
192
+ def. to_def_id ( ) ,
193
+ ty:: UserArgs { args, user_self_ty : None } ,
194
+ ) ) ;
195
+ let annotation = ty:: CanonicalUserTypeAnnotation {
196
+ inferred_ty : pattern. ty ,
197
+ span,
198
+ user_ty : Box :: new ( user_ty) ,
199
+ } ;
200
+ super :: Ascription { annotation, source, variance : ty:: Contravariant }
201
+ } ) ;
202
+
148
203
subpairs. push ( MatchPair :: new ( place. clone ( ) , pattern, cx) ) ;
149
- TestCase :: Irrefutable
204
+ TestCase :: Irrefutable { ascription , binding : None }
150
205
}
151
206
152
207
PatKind :: Array { ref prefix, ref slice, ref suffix } => {
153
208
cx. prefix_slice_suffix ( & mut subpairs, & place, prefix, slice, suffix) ;
154
- TestCase :: Irrefutable
209
+ default_irrefutable ( )
155
210
}
156
211
PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
157
212
cx. prefix_slice_suffix ( & mut subpairs, & place, prefix, slice, suffix) ;
158
213
159
214
if prefix. is_empty ( ) && slice. is_some ( ) && suffix. is_empty ( ) {
160
- TestCase :: Irrefutable
215
+ default_irrefutable ( )
161
216
} else {
162
217
TestCase :: Slice {
163
218
len : prefix. len ( ) + suffix. len ( ) ,
@@ -182,21 +237,21 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
182
237
} ) && ( adt_def. did ( ) . is_local ( )
183
238
|| !adt_def. is_variant_list_non_exhaustive ( ) ) ;
184
239
if irrefutable {
185
- TestCase :: Irrefutable
240
+ default_irrefutable ( )
186
241
} else {
187
242
TestCase :: Variant { adt_def, variant_index }
188
243
}
189
244
}
190
245
191
246
PatKind :: Leaf { ref subpatterns } => {
192
247
subpairs = cx. field_match_pairs ( place. clone ( ) , subpatterns) ;
193
- TestCase :: Irrefutable
248
+ default_irrefutable ( )
194
249
}
195
250
196
251
PatKind :: Deref { ref subpattern } => {
197
252
let place_builder = place. clone ( ) . deref ( ) ;
198
253
subpairs. push ( MatchPair :: new ( place_builder, subpattern, cx) ) ;
199
- TestCase :: Irrefutable
254
+ default_irrefutable ( )
200
255
}
201
256
} ;
202
257
0 commit comments