1
1
//! See docs in build/expr/mod.rs
2
2
3
- use rustc_abi:: VariantIdx ;
4
3
use rustc_ast:: { AsmMacro , InlineAsmOptions } ;
5
4
use rustc_data_structures:: fx:: FxHashMap ;
6
5
use rustc_data_structures:: stack:: ensure_sufficient_stack;
@@ -9,17 +8,14 @@ use rustc_hir::lang_items::LangItem;
9
8
use rustc_middle:: mir:: * ;
10
9
use rustc_middle:: span_bug;
11
10
use rustc_middle:: thir:: * ;
12
- use rustc_middle:: ty:: util:: Discr ;
13
11
use rustc_middle:: ty:: { CanonicalUserTypeAnnotation , Ty } ;
14
- use rustc_pattern_analysis:: constructor:: Constructor ;
15
- use rustc_pattern_analysis:: rustc:: { DeconstructedPat , RustcPatCtxt } ;
16
12
use rustc_span:: DUMMY_SP ;
17
13
use rustc_span:: source_map:: Spanned ;
18
14
use rustc_trait_selection:: infer:: InferCtxtExt ;
19
15
use tracing:: { debug, instrument} ;
20
16
21
17
use crate :: builder:: expr:: category:: { Category , RvalueFunc } ;
22
- use crate :: builder:: matches:: DeclareLetBindings ;
18
+ use crate :: builder:: matches:: { DeclareLetBindings , HasMatchGuard } ;
23
19
use crate :: builder:: { BlockAnd , BlockAndExtension , BlockFrame , Builder , NeedsTemporary } ;
24
20
25
21
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
@@ -251,28 +247,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
251
247
ExprKind :: LoopMatch { state, region_scope, ref arms } => {
252
248
// FIXME add diagram
253
249
254
- let dropless_arena = rustc_arena:: DroplessArena :: default ( ) ;
255
- let typeck_results = this. tcx . typeck ( this. def_id ) ;
256
-
257
- // the PatCtxt is normally used in pattern exhaustiveness checking, but reused here
258
- // because it performs normalization and const evaluation.
259
- let cx = RustcPatCtxt {
260
- tcx : this. tcx ,
261
- typeck_results,
262
- module : this. tcx . parent_module ( this. hir_id ) . to_def_id ( ) ,
263
- // FIXME(#132279): We're in a body, should handle opaques.
264
- typing_env : rustc_middle:: ty:: TypingEnv :: non_body_analysis (
265
- this. tcx ,
266
- this. def_id ,
267
- ) ,
268
- dropless_arena : & dropless_arena,
269
- match_lint_level : this. hir_id ,
270
- whole_match_span : Some ( rustc_span:: Span :: default ( ) ) ,
271
- scrut_span : rustc_span:: Span :: default ( ) ,
272
- refutable : true ,
273
- known_valid_scrutinee : true ,
274
- } ;
275
-
276
250
let loop_block = this. cfg . start_new_block ( ) ;
277
251
278
252
// Start the loop.
@@ -290,131 +264,52 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
290
264
) ;
291
265
this. diverge_from ( loop_block) ;
292
266
293
- let state_place = unpack ! ( body_block = this. as_place( body_block, state) ) ;
294
- let state_ty = this. thir . exprs [ state] . ty ;
295
-
296
- // the type of the value that is switched on by the `SwitchInt`
297
- let discr_ty = match state_ty {
298
- ty if ty. is_enum ( ) => ty. discriminant_ty ( this. tcx ) ,
299
- ty if ty. is_integral ( ) => ty,
300
- other => todo ! ( "{other:?}" ) ,
301
- } ;
302
-
303
- let rvalue = match state_ty {
304
- ty if ty. is_enum ( ) => Rvalue :: Discriminant ( state_place) ,
305
- ty if ty. is_integral ( ) => Rvalue :: Use ( Operand :: Copy ( state_place) ) ,
306
- _ => todo ! ( ) ,
307
- } ;
267
+ let scrutinee_place_builder =
268
+ unpack ! ( body_block = this. as_place_builder( body_block, state) ) ;
269
+ let scrutinee_span = this. thir . exprs [ state] . span ;
270
+ let match_start_span = scrutinee_span; // span.shrink_to_lo().to(scrutinee_span); FIXME
271
+ let patterns = arms
272
+ . iter ( )
273
+ . map ( |& arm_id| {
274
+ // FIXME nice error for guards (which are not allowed)
275
+ let arm = & this. thir [ arm_id] ;
276
+ assert ! ( arm. guard. is_none( ) ) ;
277
+ ( & * arm. pattern , HasMatchGuard :: No )
278
+ } )
279
+ . collect ( ) ;
280
+
281
+ let built_tree = this. lower_match_tree (
282
+ body_block,
283
+ scrutinee_span,
284
+ & scrutinee_place_builder,
285
+ match_start_span,
286
+ patterns,
287
+ false ,
288
+ ) ;
308
289
309
- // block and arm of the wildcard pattern (if any)
310
- let mut otherwise = None ;
290
+ let state_place = scrutinee_place_builder. to_place ( this) ;
311
291
312
292
unpack ! (
313
293
body_block = this. in_scope(
314
294
( region_scope, source_info) ,
315
295
LintLevel :: Inherited ,
316
296
move |this| {
317
- let mut arm_blocks = Vec :: with_capacity( arms. len( ) ) ;
318
- for & arm in arms {
319
- let pat = & this. thir[ arm] . pattern;
320
-
321
- this. loop_match_patterns(
322
- arm,
323
- & cx. lower_pat( pat) ,
324
- None ,
325
- & mut arm_blocks,
326
- & mut otherwise,
327
- ) ;
328
- }
329
-
330
- // handle patterns like `None | None` or two different arms that
331
- // have the same pattern.
332
- //
333
- // NOTE: why this works is a bit subtle: we always want to pick the
334
- // first arm for a pattern, and because this is a stable sort that
335
- // works out.
336
- arm_blocks. sort_by_key( |( _, discr, _, _) | discr. val) ;
337
- arm_blocks. dedup_by_key( |( _, discr, _, _) | discr. val) ;
338
-
339
- // if we're matching on an enum, the discriminant order in the `SwitchInt`
340
- // targets should match the order yielded by `AdtDef::discriminants`.
341
- if state_ty. is_enum( ) {
342
- arm_blocks. sort_by_key( |( variant_idx, ..) | * variant_idx) ;
343
- }
344
-
345
- let targets = SwitchTargets :: new(
346
- arm_blocks
347
- . iter( )
348
- . map( |& ( _, discr, block, _arm) | ( discr. val, block) ) ,
349
- if let Some ( ( block, _) ) = otherwise {
350
- block
351
- } else {
352
- let unreachable_block = this. cfg. start_new_block( ) ;
353
- this. cfg. terminate(
354
- unreachable_block,
355
- source_info,
356
- TerminatorKind :: Unreachable ,
357
- ) ;
358
- unreachable_block
359
- } ,
360
- ) ;
361
-
362
297
this. in_breakable_scope( None , state_place, expr_span, |this| {
363
298
Some ( this. in_const_continuable_scope(
364
- targets. clone( ) ,
299
+ arms. clone( ) ,
300
+ built_tree. clone( ) ,
365
301
state_place,
366
302
expr_span,
367
303
|this| {
368
- let discr = this. temp( discr_ty, source_info. span) ;
369
- this. cfg. push_assign(
370
- body_block,
371
- source_info,
372
- discr,
373
- rvalue,
374
- ) ;
375
- let discr = Operand :: Copy ( discr) ;
376
- this. cfg. terminate(
377
- body_block,
378
- source_info,
379
- TerminatorKind :: SwitchInt { discr, targets } ,
380
- ) ;
381
-
382
- let it = arm_blocks
383
- . into_iter( )
384
- . map( |( _, _, block, arm) | ( block, arm) )
385
- . chain( otherwise) ;
386
-
387
- for ( mut block, arm_id) in it {
388
- if this. cfg. block_data( block) . terminator. is_some( ) {
389
- continue ; // this can occur with or-patterns
390
- }
391
-
392
- let arm = & this. thir[ arm_id] ;
393
- let arm_source_info = this. source_info( arm. span) ;
394
- let arm_scope = ( arm. scope, arm_source_info) ;
395
-
396
- let empty_place = this. get_unit_temp( ) ;
397
- unpack!(
398
- block = {
399
- this. in_scope(
400
- arm_scope,
401
- arm. lint_level,
402
- |this| {
403
- this. expr_into_dest(
404
- empty_place,
405
- block,
406
- arm. body,
407
- )
408
- } ,
409
- )
410
- }
411
- ) ;
412
- this. cfg. terminate(
413
- block,
414
- source_info,
415
- TerminatorKind :: Unreachable ,
416
- ) ;
417
- }
304
+ this. lower_match_arms(
305
+ destination,
306
+ scrutinee_place_builder,
307
+ scrutinee_span,
308
+ arms,
309
+ built_tree,
310
+ // FIXME this should be the span of just the match
311
+ this. source_info( expr_span) ,
312
+ )
418
313
} ,
419
314
) )
420
315
} )
@@ -893,55 +788,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
893
788
_ => false ,
894
789
}
895
790
}
896
-
897
- fn loop_match_patterns (
898
- & mut self ,
899
- arm_id : ArmId ,
900
- pat : & DeconstructedPat < ' _ , ' tcx > ,
901
- current_block : Option < BasicBlock > ,
902
- result : & mut Vec < ( VariantIdx , Discr < ' tcx > , BasicBlock , ArmId ) > ,
903
- otherwise : & mut Option < ( BasicBlock , ArmId ) > ,
904
- ) {
905
- match pat. ctor ( ) {
906
- Constructor :: Variant ( variant_index) => {
907
- let PatKind :: Variant { adt_def, .. } = pat. data ( ) . kind else { unreachable ! ( ) } ;
908
-
909
- let discr = adt_def. discriminant_for_variant ( self . tcx , * variant_index) ;
910
-
911
- let block = current_block. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
912
- result. push ( ( * variant_index, discr, block, arm_id) ) ;
913
- }
914
- Constructor :: IntRange ( int_range) => {
915
- assert ! ( int_range. is_singleton( ) ) ;
916
-
917
- let bits = pat. ty ( ) . primitive_size ( self . tcx ) . bits ( ) ;
918
-
919
- let value = if pat. ty ( ) . is_signed ( ) {
920
- int_range. lo . as_finite_int ( bits) . unwrap ( )
921
- } else {
922
- int_range. lo . as_finite_uint ( ) . unwrap ( )
923
- } ;
924
-
925
- let discr = Discr { val : value, ty : * * pat. ty ( ) } ;
926
-
927
- let block = current_block. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
928
- result. push ( ( VariantIdx :: ZERO , discr, block, arm_id) ) ;
929
- }
930
- Constructor :: Wildcard => {
931
- // the first wildcard wins
932
- if otherwise. is_none ( ) {
933
- let block = current_block. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
934
- * otherwise = Some ( ( block, arm_id) )
935
- }
936
- }
937
- Constructor :: Or => {
938
- let block = current_block. unwrap_or_else ( || self . cfg . start_new_block ( ) ) ;
939
-
940
- for indexed in pat. iter_fields ( ) {
941
- self . loop_match_patterns ( arm_id, & indexed. pat , Some ( block) , result, otherwise) ;
942
- }
943
- }
944
- other => todo ! ( "{:?}" , other) ,
945
- }
946
- }
947
791
}
0 commit comments