@@ -71,57 +71,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
71
71
self . check_pat_lit ( pat. span , lt, expected, discrim_span)
72
72
}
73
73
PatKind :: Range ( ref begin, ref end, _) => {
74
- let lhs_ty = self . check_expr ( begin) ;
75
- let rhs_ty = self . check_expr ( end) ;
76
-
77
- // Check that both end-points are of numeric or char type.
78
- let numeric_or_char = |ty : Ty < ' _ > | {
79
- ty. is_numeric ( )
80
- || ty. is_char ( )
81
- || ty. references_error ( )
82
- } ;
83
- let lhs_compat = numeric_or_char ( lhs_ty) ;
84
- let rhs_compat = numeric_or_char ( rhs_ty) ;
85
-
86
- if !lhs_compat || !rhs_compat {
87
- let span = if !lhs_compat && !rhs_compat {
88
- pat. span
89
- } else if !lhs_compat {
90
- begin. span
91
- } else {
92
- end. span
93
- } ;
94
-
95
- let mut err = struct_span_err ! (
96
- tcx. sess,
97
- span,
98
- E0029 ,
99
- "only char and numeric types are allowed in range patterns"
100
- ) ;
101
- err. span_label ( span, "ranges require char or numeric types" ) ;
102
- err. note ( & format ! ( "start type: {}" , self . ty_to_string( lhs_ty) ) ) ;
103
- err. note ( & format ! ( "end type: {}" , self . ty_to_string( rhs_ty) ) ) ;
104
- if tcx. sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
105
- err. note (
106
- "In a match expression, only numbers and characters can be matched \
107
- against a range. This is because the compiler checks that the range \
108
- is non-empty at compile-time, and is unable to evaluate arbitrary \
109
- comparison functions. If you want to capture values of an orderable \
110
- type between two end-points, you can use a guard."
111
- ) ;
112
- }
113
- err. emit ( ) ;
114
- return ;
74
+ match self . check_pat_range ( pat. span , begin, end, expected, discrim_span) {
75
+ None => return ,
76
+ Some ( ty) => ty,
115
77
}
116
-
117
- // Now that we know the types can be unified we find the unified type and use
118
- // it to type the entire expression.
119
- let common_type = self . resolve_vars_if_possible ( & lhs_ty) ;
120
-
121
- // Subtyping doesn't matter here, as the value is some kind of scalar.
122
- self . demand_eqtype_pat ( pat. span , expected, lhs_ty, discrim_span) ;
123
- self . demand_eqtype_pat ( pat. span , expected, rhs_ty, discrim_span) ;
124
- common_type
125
78
}
126
79
PatKind :: Binding ( ba, var_id, _, ref sub) => {
127
80
let bm = if ba == hir:: BindingAnnotation :: Unannotated {
@@ -597,6 +550,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
597
550
pat_ty
598
551
}
599
552
553
+ fn check_pat_range (
554
+ & self ,
555
+ span : Span ,
556
+ begin : & ' tcx hir:: Expr ,
557
+ end : & ' tcx hir:: Expr ,
558
+ expected : Ty < ' tcx > ,
559
+ discrim_span : Option < Span > ,
560
+ ) -> Option < Ty < ' tcx > > {
561
+ let lhs_ty = self . check_expr ( begin) ;
562
+ let rhs_ty = self . check_expr ( end) ;
563
+
564
+ // Check that both end-points are of numeric or char type.
565
+ let numeric_or_char = |ty : Ty < ' _ > | {
566
+ ty. is_numeric ( )
567
+ || ty. is_char ( )
568
+ || ty. references_error ( )
569
+ } ;
570
+ let lhs_compat = numeric_or_char ( lhs_ty) ;
571
+ let rhs_compat = numeric_or_char ( rhs_ty) ;
572
+
573
+ if !lhs_compat || !rhs_compat {
574
+ let span = if !lhs_compat && !rhs_compat {
575
+ span
576
+ } else if !lhs_compat {
577
+ begin. span
578
+ } else {
579
+ end. span
580
+ } ;
581
+
582
+ let mut err = struct_span_err ! (
583
+ self . tcx. sess,
584
+ span,
585
+ E0029 ,
586
+ "only char and numeric types are allowed in range patterns"
587
+ ) ;
588
+ err. span_label ( span, "ranges require char or numeric types" ) ;
589
+ err. note ( & format ! ( "start type: {}" , self . ty_to_string( lhs_ty) ) ) ;
590
+ err. note ( & format ! ( "end type: {}" , self . ty_to_string( rhs_ty) ) ) ;
591
+ if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
592
+ err. note (
593
+ "In a match expression, only numbers and characters can be matched \
594
+ against a range. This is because the compiler checks that the range \
595
+ is non-empty at compile-time, and is unable to evaluate arbitrary \
596
+ comparison functions. If you want to capture values of an orderable \
597
+ type between two end-points, you can use a guard."
598
+ ) ;
599
+ }
600
+ err. emit ( ) ;
601
+ return None ;
602
+ }
603
+
604
+ // Now that we know the types can be unified we find the unified type and use
605
+ // it to type the entire expression.
606
+ let common_type = self . resolve_vars_if_possible ( & lhs_ty) ;
607
+
608
+ // Subtyping doesn't matter here, as the value is some kind of scalar.
609
+ self . demand_eqtype_pat ( span, expected, lhs_ty, discrim_span) ;
610
+ self . demand_eqtype_pat ( span, expected, rhs_ty, discrim_span) ;
611
+ Some ( common_type)
612
+ }
600
613
601
614
fn borrow_pat_suggestion (
602
615
& self ,
0 commit comments