11//! See docs in build/expr/mod.rs
22
3- use rustc_abi:: VariantIdx ;
43use rustc_ast:: { AsmMacro , InlineAsmOptions } ;
54use rustc_data_structures:: fx:: FxHashMap ;
65use rustc_data_structures:: stack:: ensure_sufficient_stack;
@@ -9,17 +8,14 @@ use rustc_hir::lang_items::LangItem;
98use rustc_middle:: mir:: * ;
109use rustc_middle:: span_bug;
1110use rustc_middle:: thir:: * ;
12- use rustc_middle:: ty:: util:: Discr ;
1311use rustc_middle:: ty:: { CanonicalUserTypeAnnotation , Ty } ;
14- use rustc_pattern_analysis:: constructor:: Constructor ;
15- use rustc_pattern_analysis:: rustc:: { DeconstructedPat , RustcPatCtxt } ;
1612use rustc_span:: DUMMY_SP ;
1713use rustc_span:: source_map:: Spanned ;
1814use rustc_trait_selection:: infer:: InferCtxtExt ;
1915use tracing:: { debug, instrument} ;
2016
2117use crate :: builder:: expr:: category:: { Category , RvalueFunc } ;
22- use crate :: builder:: matches:: DeclareLetBindings ;
18+ use crate :: builder:: matches:: { DeclareLetBindings , HasMatchGuard } ;
2319use crate :: builder:: { BlockAnd , BlockAndExtension , BlockFrame , Builder , NeedsTemporary } ;
2420
2521impl < ' a , ' tcx > Builder < ' a , ' tcx > {
@@ -251,28 +247,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
251247 ExprKind :: LoopMatch { state, region_scope, ref arms } => {
252248 // FIXME add diagram
253249
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-
276250 let loop_block = this. cfg . start_new_block ( ) ;
277251
278252 // Start the loop.
@@ -290,131 +264,52 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
290264 ) ;
291265 this. diverge_from ( loop_block) ;
292266
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+ ) ;
308289
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) ;
311291
312292 unpack ! (
313293 body_block = this. in_scope(
314294 ( region_scope, source_info) ,
315295 LintLevel :: Inherited ,
316296 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-
362297 this. in_breakable_scope( None , state_place, expr_span, |this| {
363298 Some ( this. in_const_continuable_scope(
364- targets. clone( ) ,
299+ arms. clone( ) ,
300+ built_tree. clone( ) ,
365301 state_place,
366302 expr_span,
367303 |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+ )
418313 } ,
419314 ) )
420315 } )
@@ -893,55 +788,4 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
893788 _ => false ,
894789 }
895790 }
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- }
947791}
0 commit comments