about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-24 03:59:15 +0200
committerMazdak Farrokhzad <twingoow@gmail.com>2019-08-24 19:15:16 +0200
commitd4afae943f642be2909c649997f663b384115237 (patch)
tree9ade41e25b6f5210bb426aafb6111cfef67c82bd
parentd891e70b6421e2ef48a64badf3e432059a5c4b96 (diff)
downloadrust-d4afae943f642be2909c649997f663b384115237.tar.gz
rust-d4afae943f642be2909c649997f663b384115237.zip
typeck/pat.rs: extract `check_pat_range`.
-rw-r--r--src/librustc_typeck/check/pat.rs113
1 files changed, 63 insertions, 50 deletions
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 95013f60cd6..9693ab57bc7 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -71,57 +71,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat_lit(pat.span, lt, expected, discrim_span)
             }
             PatKind::Range(ref begin, ref end, _) => {
-                let lhs_ty = self.check_expr(begin);
-                let rhs_ty = self.check_expr(end);
-
-                // Check that both end-points are of numeric or char type.
-                let numeric_or_char = |ty: Ty<'_>| {
-                    ty.is_numeric()
-                    || ty.is_char()
-                    || ty.references_error()
-                };
-                let lhs_compat = numeric_or_char(lhs_ty);
-                let rhs_compat = numeric_or_char(rhs_ty);
-
-                if !lhs_compat || !rhs_compat {
-                    let span = if !lhs_compat && !rhs_compat {
-                        pat.span
-                    } else if !lhs_compat {
-                        begin.span
-                    } else {
-                        end.span
-                    };
-
-                    let mut err = struct_span_err!(
-                        tcx.sess,
-                        span,
-                        E0029,
-                        "only char and numeric types are allowed in range patterns"
-                    );
-                    err.span_label(span, "ranges require char or numeric types");
-                    err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
-                    err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
-                    if tcx.sess.teach(&err.get_code().unwrap()) {
-                        err.note(
-                            "In a match expression, only numbers and characters can be matched \
-                             against a range. This is because the compiler checks that the range \
-                             is non-empty at compile-time, and is unable to evaluate arbitrary \
-                             comparison functions. If you want to capture values of an orderable \
-                             type between two end-points, you can use a guard."
-                         );
-                    }
-                    err.emit();
-                    return;
+                match self.check_pat_range(pat.span, begin, end, expected, discrim_span) {
+                    None => return,
+                    Some(ty) => ty,
                 }
-
-                // Now that we know the types can be unified we find the unified type and use
-                // it to type the entire expression.
-                let common_type = self.resolve_vars_if_possible(&lhs_ty);
-
-                // Subtyping doesn't matter here, as the value is some kind of scalar.
-                self.demand_eqtype_pat(pat.span, expected, lhs_ty, discrim_span);
-                self.demand_eqtype_pat(pat.span, expected, rhs_ty, discrim_span);
-                common_type
             }
             PatKind::Binding(ba, var_id, _, ref sub) => {
                 let bm = if ba == hir::BindingAnnotation::Unannotated {
@@ -597,6 +550,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat_ty
     }
 
+    fn check_pat_range(
+        &self,
+        span: Span,
+        begin: &'tcx hir::Expr,
+        end: &'tcx hir::Expr,
+        expected: Ty<'tcx>,
+        discrim_span: Option<Span>,
+    ) -> Option<Ty<'tcx>> {
+        let lhs_ty = self.check_expr(begin);
+        let rhs_ty = self.check_expr(end);
+
+        // Check that both end-points are of numeric or char type.
+        let numeric_or_char = |ty: Ty<'_>| {
+            ty.is_numeric()
+            || ty.is_char()
+            || ty.references_error()
+        };
+        let lhs_compat = numeric_or_char(lhs_ty);
+        let rhs_compat = numeric_or_char(rhs_ty);
+
+        if !lhs_compat || !rhs_compat {
+            let span = if !lhs_compat && !rhs_compat {
+                span
+            } else if !lhs_compat {
+                begin.span
+            } else {
+                end.span
+            };
+
+            let mut err = struct_span_err!(
+                self.tcx.sess,
+                span,
+                E0029,
+                "only char and numeric types are allowed in range patterns"
+            );
+            err.span_label(span, "ranges require char or numeric types");
+            err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
+            err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
+            if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                err.note(
+                    "In a match expression, only numbers and characters can be matched \
+                        against a range. This is because the compiler checks that the range \
+                        is non-empty at compile-time, and is unable to evaluate arbitrary \
+                        comparison functions. If you want to capture values of an orderable \
+                        type between two end-points, you can use a guard."
+                    );
+            }
+            err.emit();
+            return None;
+        }
+
+        // Now that we know the types can be unified we find the unified type and use
+        // it to type the entire expression.
+        let common_type = self.resolve_vars_if_possible(&lhs_ty);
+
+        // Subtyping doesn't matter here, as the value is some kind of scalar.
+        self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span);
+        self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span);
+        Some(common_type)
+    }
 
     fn borrow_pat_suggestion(
         &self,