@@ -71,57 +71,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7171 self . check_pat_lit ( pat. span , lt, expected, discrim_span)
7272 }
7373 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,
11577 }
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
12578 }
12679 PatKind :: Binding ( ba, var_id, _, ref sub) => {
12780 let bm = if ba == hir:: BindingAnnotation :: Unannotated {
@@ -597,6 +550,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
597550 pat_ty
598551 }
599552
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+ }
600613
601614 fn borrow_pat_suggestion (
602615 & self ,
0 commit comments