about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2019-11-14 14:16:20 +0900
committerGitHub <noreply@github.com>2019-11-14 14:16:20 +0900
commit20c356263d14df237aa915dc255d55a6158a197d (patch)
tree0a5f3964fe7890db0e2737b41e5769dda12da5cb
parent2acbd3dd54ea06f05514c605f09bc41061a695d7 (diff)
parent030fa9a337cb7f224c1d74fda04304c69e07787a (diff)
downloadrust-20c356263d14df237aa915dc255d55a6158a197d.tar.gz
rust-20c356263d14df237aa915dc255d55a6158a197d.zip
Rollup merge of #66351 - JohnTitor:tweak-range-err-msg, r=Centril
Tweak non-char/numeric in range pattern diagnostic

Fixes #66283

r? @estebank
-rw-r--r--src/librustc_typeck/check/pat.rs90
-rw-r--r--src/test/ui/error-codes/E0029-teach.stderr7
-rw-r--r--src/test/ui/error-codes/E0029.stderr8
-rw-r--r--src/test/ui/match/match-range-fail.rs9
-rw-r--r--src/test/ui/match/match-range-fail.stderr28
-rw-r--r--src/test/ui/parser/recover-range-pats.stderr72
-rw-r--r--src/test/ui/pattern/patkind-litrange-no-expr.stderr8
-rw-r--r--src/test/ui/qualified/qualified-path-params.stderr7
8 files changed, 123 insertions, 106 deletions
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index a4c9862bc74..9421dbc2b2c 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -362,37 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || 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 lhs_fail = !numeric_or_char(lhs_ty);
+        let rhs_fail = !numeric_or_char(rhs_ty);
 
-            let mut err = struct_span_err!(
-                self.tcx.sess,
-                span,
-                E0029,
-                "only char and numeric types are allowed in range patterns"
+        if lhs_fail || rhs_fail {
+            self.emit_err_pat_range(
+                span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty
             );
-            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;
         }
 
@@ -406,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Some(common_type)
     }
 
+    fn emit_err_pat_range(
+        &self,
+        span: Span,
+        begin_span: Span,
+        end_span: Span,
+        lhs_fail: bool,
+        rhs_fail: bool,
+        lhs_ty: Ty<'tcx>,
+        rhs_ty: Ty<'tcx>,
+    ) {
+        let span = if lhs_fail && rhs_fail {
+            span
+        } else if lhs_fail {
+            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"
+        );
+        let msg = |ty| {
+            format!("this is of type `{}` but it should be `char` or numeric", ty)
+        };
+        let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
+            err.span_label(first_span, &msg(first_ty));
+            if !second_ty.references_error() {
+                err.span_label(
+                    second_span,
+                    &format!("this is of type `{}`", second_ty)
+                );
+            }
+        };
+        if lhs_fail && rhs_fail {
+            err.span_label(begin_span, &msg(lhs_ty));
+            err.span_label(end_span, &msg(rhs_ty));
+        } else if lhs_fail {
+            one_side_err(begin_span, lhs_ty, end_span, rhs_ty);
+        } else {
+            one_side_err(end_span, rhs_ty, begin_span, lhs_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();
+    }
+
     fn check_pat_ident(
         &self,
         pat: &Pat,
diff --git a/src/test/ui/error-codes/E0029-teach.stderr b/src/test/ui/error-codes/E0029-teach.stderr
index 998ef4bc1d7..ec146ca86f5 100644
--- a/src/test/ui/error-codes/E0029-teach.stderr
+++ b/src/test/ui/error-codes/E0029-teach.stderr
@@ -2,10 +2,11 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/E0029-teach.rs:7:9
    |
 LL |         "hello" ..= "world" => {}
-   |         ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
+   |         -------^^^^^-------
+   |         |           |
+   |         |           this is of type `&'static str` but it should be `char` or numeric
+   |         this is of type `&'static str` but it should be `char` or numeric
    |
-   = note: start type: &'static str
-   = note: end type: &'static str
    = 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.
 
 error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0029.stderr b/src/test/ui/error-codes/E0029.stderr
index 209d219191c..e54722ae7b9 100644
--- a/src/test/ui/error-codes/E0029.stderr
+++ b/src/test/ui/error-codes/E0029.stderr
@@ -2,10 +2,10 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/E0029.rs:5:9
    |
 LL |         "hello" ..= "world" => {}
-   |         ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
-   |
-   = note: start type: &'static str
-   = note: end type: &'static str
+   |         -------^^^^^-------
+   |         |           |
+   |         |           this is of type `&'static str` but it should be `char` or numeric
+   |         this is of type `&'static str` but it should be `char` or numeric
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-range-fail.rs b/src/test/ui/match/match-range-fail.rs
index 8a3678577b4..252d4cbf162 100644
--- a/src/test/ui/match/match-range-fail.rs
+++ b/src/test/ui/match/match-range-fail.rs
@@ -3,15 +3,16 @@ fn main() {
         "bar" ..= "foo" => { }
     };
     //~^^ ERROR only char and numeric types are allowed in range
-    //~| start type: &'static str
-    //~| end type: &'static str
 
     match "wow" {
         10 ..= "what" => ()
     };
     //~^^ ERROR only char and numeric types are allowed in range
-    //~| start type: {integer}
-    //~| end type: &'static str
+
+    match "wow" {
+        true ..= "what" => {}
+    };
+    //~^^ ERROR only char and numeric types are allowed in range
 
     match 5 {
         'c' ..= 100 => { }
diff --git a/src/test/ui/match/match-range-fail.stderr b/src/test/ui/match/match-range-fail.stderr
index 3fd2a499e2b..25fa9c2f618 100644
--- a/src/test/ui/match/match-range-fail.stderr
+++ b/src/test/ui/match/match-range-fail.stderr
@@ -2,22 +2,30 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/match-range-fail.rs:3:9
    |
 LL |         "bar" ..= "foo" => { }
-   |         ^^^^^^^^^^^^^^^ ranges require char or numeric types
-   |
-   = note: start type: &'static str
-   = note: end type: &'static str
+   |         -----^^^^^-----
+   |         |         |
+   |         |         this is of type `&'static str` but it should be `char` or numeric
+   |         this is of type `&'static str` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
-  --> $DIR/match-range-fail.rs:10:16
+  --> $DIR/match-range-fail.rs:8:16
    |
 LL |         10 ..= "what" => ()
-   |                ^^^^^^ ranges require char or numeric types
+   |         --     ^^^^^^ this is of type `&'static str` but it should be `char` or numeric
+   |         |
+   |         this is of type `{integer}`
+
+error[E0029]: only char and numeric types are allowed in range patterns
+  --> $DIR/match-range-fail.rs:13:9
    |
-   = note: start type: {integer}
-   = note: end type: &'static str
+LL |         true ..= "what" => {}
+   |         ----^^^^^------
+   |         |        |
+   |         |        this is of type `&'static str` but it should be `char` or numeric
+   |         this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
-  --> $DIR/match-range-fail.rs:17:9
+  --> $DIR/match-range-fail.rs:18:9
    |
 LL |         'c' ..= 100 => { }
    |         ^^^^^^^^^^^ expected integer, found char
@@ -25,7 +33,7 @@ LL |         'c' ..= 100 => { }
    = note: expected type `{integer}`
               found type `char`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0029, E0308.
 For more information about an error, try `rustc --explain E0029`.
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index 89ec059cb82..160ab18e34a 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -401,19 +401,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:19:12
    |
 LL |     if let true..Y = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: u8
+   |            ^^^^  - this is of type `u8`
+   |            |
+   |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:20:15
    |
 LL |     if let X..true = 0 {}
-   |               ^^^^ ranges require char or numeric types
-   |
-   = note: start type: u8
-   = note: end type: bool
+   |            -  ^^^^ this is of type `bool` but it should be `char` or numeric
+   |            |
+   |            this is of type `u8`
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:21:12
@@ -437,19 +435,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:32:12
    |
 LL |     if let true..=Y = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: u8
+   |            ^^^^   - this is of type `u8`
+   |            |
+   |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:33:16
    |
 LL |     if let X..=true = 0 {}
-   |                ^^^^ ranges require char or numeric types
-   |
-   = note: start type: u8
-   = note: end type: bool
+   |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
+   |            |
+   |            this is of type `u8`
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:34:12
@@ -473,19 +469,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:45:12
    |
 LL |     if let true...Y = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: u8
+   |            ^^^^   - this is of type `u8`
+   |            |
+   |            this is of type `bool` but it should be `char` or numeric
 
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:47:16
    |
 LL |     if let X...true = 0 {}
-   |                ^^^^ ranges require char or numeric types
-   |
-   = note: start type: u8
-   = note: end type: bool
+   |            -   ^^^^ this is of type `bool` but it should be `char` or numeric
+   |            |
+   |            this is of type `u8`
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:49:12
@@ -509,10 +503,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:60:12
    |
 LL |     if let true.. = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: [type error]
+   |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:62:12
@@ -527,10 +518,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:70:12
    |
 LL |     if let true..= = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: [type error]
+   |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:72:12
@@ -545,10 +533,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:82:12
    |
 LL |     if let true... = 0 {}
-   |            ^^^^ ranges require char or numeric types
-   |
-   = note: start type: bool
-   = note: end type: [type error]
+   |            ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:85:12
@@ -563,10 +548,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:94:14
    |
 LL |     if let ..true = 0 {}
-   |              ^^^^ ranges require char or numeric types
-   |
-   = note: start type: [type error]
-   = note: end type: bool
+   |              ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:96:12
@@ -581,10 +563,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:104:15
    |
 LL |     if let ..=true = 0 {}
-   |               ^^^^ ranges require char or numeric types
-   |
-   = note: start type: [type error]
-   = note: end type: bool
+   |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:106:12
@@ -599,10 +578,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/recover-range-pats.rs:116:15
    |
 LL |     if let ...true = 0 {}
-   |               ^^^^ ranges require char or numeric types
-   |
-   = note: start type: [type error]
-   = note: end type: bool
+   |               ^^^^ this is of type `bool` but it should be `char` or numeric
 
 error[E0308]: mismatched types
   --> $DIR/recover-range-pats.rs:119:12
diff --git a/src/test/ui/pattern/patkind-litrange-no-expr.stderr b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
index 7474d326793..78768d282e7 100644
--- a/src/test/ui/pattern/patkind-litrange-no-expr.stderr
+++ b/src/test/ui/pattern/patkind-litrange-no-expr.stderr
@@ -7,11 +7,11 @@ LL |     Arith = 1 + 1,
 error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/patkind-litrange-no-expr.rs:20:13
    |
+LL |                 $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
+   |                               -- this is of type `{integer}`
+...
 LL |     Arith = 1 + 1,
-   |             ^^^^^ ranges require char or numeric types
-   |
-   = note: start type: {integer}
-   = note: end type: {integer}
+   |             ^^^^^ this is of type `_` but it should be `char` or numeric
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr
index 92792f2e86a..7a74a37021b 100644
--- a/src/test/ui/qualified/qualified-path-params.stderr
+++ b/src/test/ui/qualified/qualified-path-params.stderr
@@ -8,10 +8,9 @@ error[E0029]: only char and numeric types are allowed in range patterns
   --> $DIR/qualified-path-params.rs:22:15
    |
 LL |         0 ..= <S as Tr>::A::f::<u8> => {}
-   |               ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
-   |
-   = note: start type: {integer}
-   = note: end type: fn() {S::f::<u8>}
+   |         -     ^^^^^^^^^^^^^^^^^^^^^ this is of type `fn() {S::f::<u8>}` but it should be `char` or numeric
+   |         |
+   |         this is of type `{integer}`
 
 error: aborting due to 2 previous errors