@@ -3,11 +3,11 @@ use std::sync::Arc;
3
3
use rustc_ast:: ptr:: P ;
4
4
use rustc_ast:: * ;
5
5
use rustc_data_structures:: stack:: ensure_sufficient_stack;
6
- use rustc_hir as hir ;
7
- use rustc_hir:: def :: Res ;
6
+ use rustc_hir:: def :: { DefKind , Res } ;
7
+ use rustc_hir:: { self as hir , LangItem } ;
8
8
use rustc_middle:: span_bug;
9
9
use rustc_span:: source_map:: { Spanned , respan} ;
10
- use rustc_span:: { Ident , Span } ;
10
+ use rustc_span:: { DesugaringKind , Ident , Span , kw } ;
11
11
12
12
use super :: errors:: {
13
13
ArbitraryExpressionInPattern , ExtraDoubleDot , MisplacedDoubleDot , SubTupleBinding ,
@@ -430,22 +430,124 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
430
430
self . arena . alloc ( hir:: PatExpr { hir_id : self . lower_node_id ( expr. id ) , span, kind } )
431
431
}
432
432
433
- pub ( crate ) fn lower_ty_pat ( & mut self , pattern : & TyPat ) -> & ' hir hir:: TyPat < ' hir > {
434
- self . arena . alloc ( self . lower_ty_pat_mut ( pattern) )
433
+ pub ( crate ) fn lower_ty_pat (
434
+ & mut self ,
435
+ pattern : & TyPat ,
436
+ base_type : Span ,
437
+ ) -> & ' hir hir:: TyPat < ' hir > {
438
+ self . arena . alloc ( self . lower_ty_pat_mut ( pattern, base_type) )
435
439
}
436
440
437
- fn lower_ty_pat_mut ( & mut self , pattern : & TyPat ) -> hir:: TyPat < ' hir > {
441
+ fn lower_ty_pat_mut ( & mut self , pattern : & TyPat , base_type : Span ) -> hir:: TyPat < ' hir > {
438
442
// loop here to avoid recursion
439
443
let pat_hir_id = self . lower_node_id ( pattern. id ) ;
440
444
let node = match & pattern. kind {
441
- TyPatKind :: Range ( e1, e2, Spanned { node : end, .. } ) => hir:: TyPatKind :: Range (
442
- e1. as_deref ( ) . map ( |e| self . lower_anon_const_to_const_arg ( e) ) ,
443
- e2. as_deref ( ) . map ( |e| self . lower_anon_const_to_const_arg ( e) ) ,
444
- self . lower_range_end ( end, e2. is_some ( ) ) ,
445
+ TyPatKind :: Range ( e1, e2, Spanned { node : end, span } ) => hir:: TyPatKind :: Range (
446
+ e1. as_deref ( ) . map ( |e| self . lower_anon_const_to_const_arg ( e) ) . unwrap_or_else ( || {
447
+ self . lower_ty_pat_range_end (
448
+ hir:: LangItem :: RangeMin ,
449
+ span. shrink_to_lo ( ) ,
450
+ base_type,
451
+ )
452
+ } ) ,
453
+ e2. as_deref ( )
454
+ . map ( |e| match end {
455
+ RangeEnd :: Included ( ..) => self . lower_anon_const_to_const_arg ( e) ,
456
+ RangeEnd :: Excluded => self . lower_excluded_range_end ( e) ,
457
+ } )
458
+ . unwrap_or_else ( || {
459
+ self . lower_ty_pat_range_end (
460
+ hir:: LangItem :: RangeMax ,
461
+ span. shrink_to_hi ( ) ,
462
+ base_type,
463
+ )
464
+ } ) ,
445
465
) ,
446
466
TyPatKind :: Err ( guar) => hir:: TyPatKind :: Err ( * guar) ,
447
467
} ;
448
468
449
469
hir:: TyPat { hir_id : pat_hir_id, kind : node, span : self . lower_span ( pattern. span ) }
450
470
}
471
+
472
+ /// Lowers the range end of an exclusive range (`2..5`) to an inclusive range 2..=(5 - 1).
473
+ /// This way the type system doesn't have to handle the distinction between inclusive/exclusive ranges.
474
+ fn lower_excluded_range_end ( & mut self , e : & AnonConst ) -> & ' hir hir:: ConstArg < ' hir > {
475
+ let span = self . lower_span ( e. value . span ) ;
476
+ let unstable_span = self . mark_span_with_reason (
477
+ DesugaringKind :: PatTyRange ,
478
+ span,
479
+ Some ( Arc :: clone ( & self . allow_pattern_type ) ) ,
480
+ ) ;
481
+ let anon_const = self . with_new_scopes ( span, |this| {
482
+ let def_id = this. local_def_id ( e. id ) ;
483
+ let hir_id = this. lower_node_id ( e. id ) ;
484
+ let body = this. lower_body ( |this| {
485
+ // Need to use a custom function as we can't just subtract `1` from a `char`.
486
+ let kind = hir:: ExprKind :: Path ( this. make_lang_item_qpath (
487
+ hir:: LangItem :: RangeSub ,
488
+ unstable_span,
489
+ None ,
490
+ ) ) ;
491
+ let fn_def = this. arena . alloc ( hir:: Expr { hir_id : this. next_id ( ) , kind, span } ) ;
492
+ let args = this. arena . alloc ( [ this. lower_expr_mut ( & e. value ) ] ) ;
493
+ (
494
+ & [ ] ,
495
+ hir:: Expr {
496
+ hir_id : this. next_id ( ) ,
497
+ kind : hir:: ExprKind :: Call ( fn_def, args) ,
498
+ span,
499
+ } ,
500
+ )
501
+ } ) ;
502
+ hir:: AnonConst { def_id, hir_id, body, span }
503
+ } ) ;
504
+ self . arena . alloc ( hir:: ConstArg {
505
+ hir_id : self . next_id ( ) ,
506
+ kind : hir:: ConstArgKind :: Anon ( self . arena . alloc ( anon_const) ) ,
507
+ } )
508
+ }
509
+
510
+ /// When a range has no end specified (`1..` or `1..=`) or no start specified (`..5` or `..=5`),
511
+ /// we instead use a constant of the MAX/MIN of the type.
512
+ /// This way the type system does not have to handle the lack of a start/end.
513
+ fn lower_ty_pat_range_end (
514
+ & mut self ,
515
+ lang_item : LangItem ,
516
+ span : Span ,
517
+ base_type : Span ,
518
+ ) -> & ' hir hir:: ConstArg < ' hir > {
519
+ let parent_def_id = self . current_hir_id_owner . def_id ;
520
+ let node_id = self . next_node_id ( ) ;
521
+
522
+ // Add a definition for the in-band const def.
523
+ // We're generating a range end that didn't exist in the AST,
524
+ // so the def collector didn't create the def ahead of time. That's why we have to do
525
+ // it here.
526
+ let def_id = self . create_def ( parent_def_id, node_id, kw:: Empty , DefKind :: AnonConst , span) ;
527
+ let hir_id = self . lower_node_id ( node_id) ;
528
+
529
+ let unstable_span = self . mark_span_with_reason (
530
+ DesugaringKind :: PatTyRange ,
531
+ self . lower_span ( span) ,
532
+ Some ( Arc :: clone ( & self . allow_pattern_type ) ) ,
533
+ ) ;
534
+ let span = self . lower_span ( base_type) ;
535
+
536
+ let path_expr = hir:: Expr {
537
+ hir_id : self . next_id ( ) ,
538
+ kind : hir:: ExprKind :: Path ( self . make_lang_item_qpath ( lang_item, unstable_span, None ) ) ,
539
+ span,
540
+ } ;
541
+
542
+ let ct = self . with_new_scopes ( span, |this| {
543
+ self . arena . alloc ( hir:: AnonConst {
544
+ def_id,
545
+ hir_id,
546
+ body : this. lower_body ( |_this| ( & [ ] , path_expr) ) ,
547
+ span,
548
+ } )
549
+ } ) ;
550
+ let hir_id = self . next_id ( ) ;
551
+ self . arena . alloc ( hir:: ConstArg { kind : hir:: ConstArgKind :: Anon ( ct) , hir_id } )
552
+ }
451
553
}
0 commit comments