about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-01-06 21:10:51 -0800
committerEsteban Küber <esteban@kuber.com.ar>2018-01-14 22:46:23 -0800
commitaec16237e4cd8c2d4d650cacac72b9a33cac1f99 (patch)
treea92044fd8e8499d16464b02a6a6f76488e7ed797
parentbb345a0be3ba3fa1970fe02789791c5c72788d8f (diff)
downloadrust-aec16237e4cd8c2d4d650cacac72b9a33cac1f99.tar.gz
rust-aec16237e4cd8c2d4d650cacac72b9a33cac1f99.zip
Suggest casting on numeric type error
-rw-r--r--src/librustc/hir/mod.rs31
-rw-r--r--src/librustc_typeck/check/demand.rs176
-rw-r--r--src/test/ui/mismatched_types/issue-26480.stderr4
-rw-r--r--src/test/ui/suggestions/numeric-cast-2.rs17
-rw-r--r--src/test/ui/suggestions/numeric-cast-2.stderr22
-rw-r--r--src/test/ui/suggestions/numeric-cast.rs336
-rw-r--r--src/test/ui/suggestions/numeric-cast.stderr1364
7 files changed, 1946 insertions, 4 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 8d43b9b4aa7..38b6bffcadd 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1173,6 +1173,37 @@ impl fmt::Debug for Expr {
     }
 }
 
+impl Expr {
+
+    /// If casting this expression to a given numeric type would be appropriate in case of a type
+    /// mismatch.
+    ///
+    /// We want to minimize the amount of casting operations that are suggested, as it can be a
+    /// lossy operation with potentially bad side effects, so we only suggest when encountering an
+    /// expression that indicates that the original type couldn't be directly changed.
+    pub fn could_cast_in_type_mismatch(&self) -> bool {
+        match self.node {
+            ExprCall(..) |
+            ExprMethodCall(..) |
+            ExprBinary(..) |
+            ExprField(..) |
+            ExprTupField(..) |
+            ExprIndex(..) |
+            ExprPath(..) => true,
+            _ => false,
+        }
+    }
+
+    pub fn needs_parens_around_cast(&self) -> bool {
+        match self.node {
+            ExprBinary(..) |
+            ExprCast(..) |
+            ExprType(..) => true,
+            _ => false,
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Expr_ {
     /// A `box x` expression.
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 6703bbba86b..7c55df7ff44 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
             err.span_suggestion(expr.span, msg, suggestion);
-        } else {
+        } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
             let methods = self.get_conversion_methods(expected, checked_ty);
             if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
                 let suggestions = iter::repeat(expr_text).zip(methods.iter())
@@ -287,8 +287,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         // Maybe remove `&`?
                         hir::ExprAddrOf(_, ref expr) => {
                             if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                                return Some(("consider removing the borrow",
-                                             code));
+                                return Some(("consider removing the borrow", code));
                             }
                         }
 
@@ -303,7 +302,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                  format!("*{}", code)));
                                 }
                             }
-                        },
+                        }
                     }
                 }
                 None
@@ -311,4 +310,173 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             _ => None,
         }
     }
+
+    fn check_for_cast(&self,
+                      err: &mut DiagnosticBuilder<'tcx>,
+                      expr: &hir::Expr,
+                      checked_ty: Ty<'tcx>,
+                      expected_ty: Ty<'tcx>)
+                      -> bool {
+        let will_truncate = "will truncate the source value";
+        let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
+                                  `isize`";
+        let depending_on_usize = "will truncate or zero-extend depending on the bit width of \
+                                  `usize`";
+        let will_sign_extend = "will sign-extend the source value";
+        let will_zero_extend = "will zero-extend the source value";
+
+        let needs_paren = expr.needs_parens_around_cast();
+
+        if let (Ok(src), true) = (self.tcx.sess.codemap().span_to_snippet(expr.span),
+                                  expr.could_cast_in_type_mismatch()) {
+            let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
+            let suggestion = format!("{}{} as {}{}",
+                                     if needs_paren { "(" } else { "" },
+                                     src,
+                                     if needs_paren { ")" } else { "" },
+                                     expected_ty);
+
+            match (&expected_ty.sty, &checked_ty.sty) {
+                (&ty::TyInt(ref exp), &ty::TyInt(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_truncate),
+                                                suggestion);
+                        }
+                        (None, _) | (_, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_isize),
+                                                suggestion);
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_truncate),
+                                                suggestion);
+                        }
+                        (None, _) | (_, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_usize),
+                                                suggestion);
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_zero_extend),
+                                                suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp - 1 => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_truncate),
+                                                suggestion);
+                        }
+                        (None, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_truncate),
+                                                suggestion);
+                        }
+                        (None, _) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_isize),
+                                                suggestion);
+                        }
+                        (_, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_usize),
+                                                suggestion);
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_zero_extend),
+                                                suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found - 1 > exp => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_truncate),
+                                                suggestion);
+                        }
+                        (None, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                suggestion);
+                        }
+                        (None, _) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_usize),
+                                                suggestion);
+                        }
+                        (_, None) => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, depending_on_isize),
+                                                suggestion);
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
+                    if found.bit_width() > exp.bit_width() {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the closest possible value",
+                                                     msg),
+                                            suggestion);
+                        err.warn("casting here will cause Undefined Behavior if the value is \
+                                  finite but larger or smaller than the largest or smallest \
+                                  finite value representable by `f32` (this is a bug and will be \
+                                  fixed)");
+                    } else {
+                        err.span_suggestion(expr.span,
+                                            &format!("{} in a lossless way",
+                                                     msg),
+                                            suggestion);
+                    }
+                    true
+                }
+                (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
+                    err.span_suggestion(expr.span,
+                                        &format!("{}, rounding the float towards zero",
+                                                 msg),
+                                        suggestion);
+                    err.warn("casting here will cause Undefined Behavior if the rounded value \
+                              cannot be represented by the target integer type, including `Inf` \
+                              and `NaN` (this is a bug and will be fixed)");
+                    true
+                }
+                (&ty::TyFloat(_), &ty::TyUint(_)) | (&ty::TyFloat(_), &ty::TyInt(_)) => {
+                    err.span_suggestion(expr.span,
+                                        &format!("{}, producing the floating point representation \
+                                                  of the integer, rounded if necessary",
+                                                  msg),
+                                        suggestion);
+                    true
+                }
+                _ => false,
+            }
+        } else {
+            false
+        }
+    }
 }
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index 5d25cb2f93c..36c5767fc0b 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -6,6 +6,10 @@ error[E0308]: mismatched types
 ...
 37 |     write!(hello);
    |     -------------- in this macro invocation
+help: you can cast an `usize` to `u64`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+26 |                   ($arr.len() * size_of($arr[0]) as )u64); //~ ERROR mismatched types
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:32:19
diff --git a/src/test/ui/suggestions/numeric-cast-2.rs b/src/test/ui/suggestions/numeric-cast-2.rs
new file mode 100644
index 00000000000..24796fbe460
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast-2.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> i32 {
+    4
+}
+fn main() {
+    let x: u32 = foo();
+    let z: i32 = x + x;
+}
diff --git a/src/test/ui/suggestions/numeric-cast-2.stderr b/src/test/ui/suggestions/numeric-cast-2.stderr
new file mode 100644
index 00000000000..c31095c102d
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast-2.stderr
@@ -0,0 +1,22 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:15:18
+   |
+15 |     let x: u32 = foo();
+   |                  ^^^^^ expected u32, found i32
+help: you can cast an `i32` to `u32`, which will sign-extend the source value
+   |
+15 |     let x: u32 = foo() as u32;
+   |                  ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:16:18
+   |
+16 |     let z: i32 = x + x;
+   |                  ^^^^^ expected i32, found u32
+help: you can cast an `u32` to `i32`, which will truncate the source value
+   |
+16 |     let z: i32 = (x + x as )i32;
+   |                  ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/suggestions/numeric-cast.rs b/src/test/ui/suggestions/numeric-cast.rs
new file mode 100644
index 00000000000..cca735d30d8
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.rs
@@ -0,0 +1,336 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+fn foo<N>(_x: N) {}
+
+fn main() {
+    let x_usize: usize = 1;
+    let x_u64: u64 = 2;
+    let x_u32: u32 = 3;
+    let x_u16: u16 = 4;
+    let x_u8: u8 = 5;
+    let x_isize: isize = 6;
+    let x_i64: i64 = 7;
+    let x_i32: i32 = 8;
+    let x_i16: i16 = 9;
+    let x_i8: i8 = 10;
+    let x_f64: f64 = 11.0;
+    let x_f32: f32 = 12.0;
+
+    foo::<usize>(x_usize);
+    foo::<usize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<usize>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<isize>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_isize);
+    foo::<isize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<isize>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<u64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u64);
+    foo::<u64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<u64>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<i64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i64);
+    foo::<i64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<i64>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<u32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u32);
+    foo::<u32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<u32>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<i32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i32);
+    foo::<i32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<i32>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<u16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u16);
+    foo::<u16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<u16>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<i16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i16);
+    foo::<i16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<i16>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<u8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u8);
+    foo::<u8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<u8>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<i8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i8);
+    foo::<i8>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<i8>(x_f32);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+
+    foo::<f64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_f64);
+    foo::<f64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f64);
+    //~^ ERROR mismatched types
+    //~| WARN casting here will cause Undefined Behavior
+    foo::<f32>(x_f32);
+}
diff --git a/src/test/ui/suggestions/numeric-cast.stderr b/src/test/ui/suggestions/numeric-cast.stderr
new file mode 100644
index 00000000000..4f4e4205f1f
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.stderr
@@ -0,0 +1,1364 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:29:18
+   |
+29 |     foo::<usize>(x_u64);
+   |                  ^^^^^ expected usize, found u64
+help: you can cast an `u64` to `usize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+29 |     foo::<usize>(x_u64 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:31:18
+   |
+31 |     foo::<usize>(x_u32);
+   |                  ^^^^^ expected usize, found u32
+help: you can cast an `u32` to `usize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+31 |     foo::<usize>(x_u32 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:33:18
+   |
+33 |     foo::<usize>(x_u16);
+   |                  ^^^^^ expected usize, found u16
+help: you can cast an `u16` to `usize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+33 |     foo::<usize>(x_u16 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:35:18
+   |
+35 |     foo::<usize>(x_u8);
+   |                  ^^^^ expected usize, found u8
+help: you can cast an `u8` to `usize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+35 |     foo::<usize>(x_u8 as usize);
+   |                  ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:37:18
+   |
+37 |     foo::<usize>(x_isize);
+   |                  ^^^^^^^ expected usize, found isize
+help: you can cast an `isize` to `usize`, which will sign-extend the source value
+   |
+37 |     foo::<usize>(x_isize as usize);
+   |                  ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:39:18
+   |
+39 |     foo::<usize>(x_i64);
+   |                  ^^^^^ expected usize, found i64
+help: you can cast an `i64` to `usize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+39 |     foo::<usize>(x_i64 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:41:18
+   |
+41 |     foo::<usize>(x_i32);
+   |                  ^^^^^ expected usize, found i32
+help: you can cast an `i32` to `usize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+41 |     foo::<usize>(x_i32 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:43:18
+   |
+43 |     foo::<usize>(x_i16);
+   |                  ^^^^^ expected usize, found i16
+help: you can cast an `i16` to `usize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+43 |     foo::<usize>(x_i16 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:45:18
+   |
+45 |     foo::<usize>(x_i8);
+   |                  ^^^^ expected usize, found i8
+help: you can cast an `i8` to `usize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+45 |     foo::<usize>(x_i8 as usize);
+   |                  ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:47:18
+   |
+47 |     foo::<usize>(x_f64);
+   |                  ^^^^^ expected usize, found f64
+   |
+   = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `usize`, rounding the float towards zero
+   |
+47 |     foo::<usize>(x_f64 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:50:18
+   |
+50 |     foo::<usize>(x_f32);
+   |                  ^^^^^ expected usize, found f32
+   |
+   = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `usize`, rounding the float towards zero
+   |
+50 |     foo::<usize>(x_f32 as usize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:54:18
+   |
+54 |     foo::<isize>(x_usize);
+   |                  ^^^^^^^ expected isize, found usize
+help: you can cast an `usize` to `isize`, which will truncate the source value
+   |
+54 |     foo::<isize>(x_usize as isize);
+   |                  ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:56:18
+   |
+56 |     foo::<isize>(x_u64);
+   |                  ^^^^^ expected isize, found u64
+help: you can cast an `u64` to `isize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+56 |     foo::<isize>(x_u64 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:58:18
+   |
+58 |     foo::<isize>(x_u32);
+   |                  ^^^^^ expected isize, found u32
+help: you can cast an `u32` to `isize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+58 |     foo::<isize>(x_u32 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:60:18
+   |
+60 |     foo::<isize>(x_u16);
+   |                  ^^^^^ expected isize, found u16
+help: you can cast an `u16` to `isize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+60 |     foo::<isize>(x_u16 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:62:18
+   |
+62 |     foo::<isize>(x_u8);
+   |                  ^^^^ expected isize, found u8
+help: you can cast an `u8` to `isize`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+62 |     foo::<isize>(x_u8 as isize);
+   |                  ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:65:18
+   |
+65 |     foo::<isize>(x_i64);
+   |                  ^^^^^ expected isize, found i64
+help: you can cast an `i64` to `isize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+65 |     foo::<isize>(x_i64 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:67:18
+   |
+67 |     foo::<isize>(x_i32);
+   |                  ^^^^^ expected isize, found i32
+help: you can cast an `i32` to `isize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+67 |     foo::<isize>(x_i32 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:69:18
+   |
+69 |     foo::<isize>(x_i16);
+   |                  ^^^^^ expected isize, found i16
+help: you can cast an `i16` to `isize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+69 |     foo::<isize>(x_i16 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:71:18
+   |
+71 |     foo::<isize>(x_i8);
+   |                  ^^^^ expected isize, found i8
+help: you can cast an `i8` to `isize`, which will truncate or zero-extend depending on the bit width of `isize`
+   |
+71 |     foo::<isize>(x_i8 as isize);
+   |                  ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:73:18
+   |
+73 |     foo::<isize>(x_f64);
+   |                  ^^^^^ expected isize, found f64
+   |
+   = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `isize`, rounding the float towards zero
+   |
+73 |     foo::<isize>(x_f64 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:76:18
+   |
+76 |     foo::<isize>(x_f32);
+   |                  ^^^^^ expected isize, found f32
+   |
+   = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `isize`, rounding the float towards zero
+   |
+76 |     foo::<isize>(x_f32 as isize);
+   |                  ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:80:16
+   |
+80 |     foo::<u64>(x_usize);
+   |                ^^^^^^^ expected u64, found usize
+help: you can cast an `usize` to `u64`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+80 |     foo::<u64>(x_usize as u64);
+   |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:83:16
+   |
+83 |     foo::<u64>(x_u32);
+   |                ^^^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+83 |     foo::<u64>(x_u32 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:85:16
+   |
+85 |     foo::<u64>(x_u16);
+   |                ^^^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+85 |     foo::<u64>(x_u16 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:87:16
+   |
+87 |     foo::<u64>(x_u8);
+   |                ^^^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+87 |     foo::<u64>(x_u8 as u64);
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:89:16
+   |
+89 |     foo::<u64>(x_isize);
+   |                ^^^^^^^ expected u64, found isize
+help: you can cast an `isize` to `u64`, which will truncate or zero-extend depending on the bit width of `usize`
+   |
+89 |     foo::<u64>(x_isize as u64);
+   |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:91:16
+   |
+91 |     foo::<u64>(x_i64);
+   |                ^^^^^ expected u64, found i64
+help: you can cast an `i64` to `u64`, which will sign-extend the source value
+   |
+91 |     foo::<u64>(x_i64 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:93:16
+   |
+93 |     foo::<u64>(x_i32);
+   |                ^^^^^ expected u64, found i32
+help: you can cast an `i32` to `u64`, which will sign-extend the source value
+   |
+93 |     foo::<u64>(x_i32 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:95:16
+   |
+95 |     foo::<u64>(x_i16);
+   |                ^^^^^ expected u64, found i16
+help: you can cast an `i16` to `u64`, which will sign-extend the source value
+   |
+95 |     foo::<u64>(x_i16 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:97:16
+   |
+97 |     foo::<u64>(x_i8);
+   |                ^^^^ expected u64, found i8
+help: you can cast an `i8` to `u64`, which will sign-extend the source value
+   |
+97 |     foo::<u64>(x_i8 as u64);
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:99:16
+   |
+99 |     foo::<u64>(x_f64);
+   |                ^^^^^ expected u64, found f64
+   |
+   = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `u64`, rounding the float towards zero
+   |
+99 |     foo::<u64>(x_f64 as u64);
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:102:16
+    |
+102 |     foo::<u64>(x_f32);
+    |                ^^^^^ expected u64, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `u64`, rounding the float towards zero
+    |
+102 |     foo::<u64>(x_f32 as u64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:106:16
+    |
+106 |     foo::<i64>(x_usize);
+    |                ^^^^^^^ expected i64, found usize
+help: you can cast an `usize` to `i64`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+106 |     foo::<i64>(x_usize as i64);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:108:16
+    |
+108 |     foo::<i64>(x_u64);
+    |                ^^^^^ expected i64, found u64
+help: you can cast an `u64` to `i64`, which will truncate the source value
+    |
+108 |     foo::<i64>(x_u64 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:110:16
+    |
+110 |     foo::<i64>(x_u32);
+    |                ^^^^^ expected i64, found u32
+help: you can cast an `u32` to `i64`, which will zero-extend the source value
+    |
+110 |     foo::<i64>(x_u32 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:112:16
+    |
+112 |     foo::<i64>(x_u16);
+    |                ^^^^^ expected i64, found u16
+help: you can cast an `u16` to `i64`, which will zero-extend the source value
+    |
+112 |     foo::<i64>(x_u16 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:114:16
+    |
+114 |     foo::<i64>(x_u8);
+    |                ^^^^ expected i64, found u8
+help: you can cast an `u8` to `i64`, which will zero-extend the source value
+    |
+114 |     foo::<i64>(x_u8 as i64);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:116:16
+    |
+116 |     foo::<i64>(x_isize);
+    |                ^^^^^^^ expected i64, found isize
+help: you can cast an `isize` to `i64`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+116 |     foo::<i64>(x_isize as i64);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:119:16
+    |
+119 |     foo::<i64>(x_i32);
+    |                ^^^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+    |
+119 |     foo::<i64>(x_i32 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:121:16
+    |
+121 |     foo::<i64>(x_i16);
+    |                ^^^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+    |
+121 |     foo::<i64>(x_i16 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:123:16
+    |
+123 |     foo::<i64>(x_i8);
+    |                ^^^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+    |
+123 |     foo::<i64>(x_i8 as i64);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:125:16
+    |
+125 |     foo::<i64>(x_f64);
+    |                ^^^^^ expected i64, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `i64`, rounding the float towards zero
+    |
+125 |     foo::<i64>(x_f64 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:128:16
+    |
+128 |     foo::<i64>(x_f32);
+    |                ^^^^^ expected i64, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `i64`, rounding the float towards zero
+    |
+128 |     foo::<i64>(x_f32 as i64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:132:16
+    |
+132 |     foo::<u32>(x_usize);
+    |                ^^^^^^^ expected u32, found usize
+help: you can cast an `usize` to `u32`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+132 |     foo::<u32>(x_usize as u32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:134:16
+    |
+134 |     foo::<u32>(x_u64);
+    |                ^^^^^ expected u32, found u64
+help: you can cast an `u64` to `u32`, which will truncate the source value
+    |
+134 |     foo::<u32>(x_u64 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:137:16
+    |
+137 |     foo::<u32>(x_u16);
+    |                ^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+    |
+137 |     foo::<u32>(x_u16 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:139:16
+    |
+139 |     foo::<u32>(x_u8);
+    |                ^^^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+    |
+139 |     foo::<u32>(x_u8 as u32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:141:16
+    |
+141 |     foo::<u32>(x_isize);
+    |                ^^^^^^^ expected u32, found isize
+help: you can cast an `isize` to `u32`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+141 |     foo::<u32>(x_isize as u32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:143:16
+    |
+143 |     foo::<u32>(x_i64);
+    |                ^^^^^ expected u32, found i64
+help: you can cast an `i64` to `u32`, which will truncate the source value
+    |
+143 |     foo::<u32>(x_i64 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:145:16
+    |
+145 |     foo::<u32>(x_i32);
+    |                ^^^^^ expected u32, found i32
+help: you can cast an `i32` to `u32`, which will sign-extend the source value
+    |
+145 |     foo::<u32>(x_i32 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:147:16
+    |
+147 |     foo::<u32>(x_i16);
+    |                ^^^^^ expected u32, found i16
+help: you can cast an `i16` to `u32`, which will sign-extend the source value
+    |
+147 |     foo::<u32>(x_i16 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:149:16
+    |
+149 |     foo::<u32>(x_i8);
+    |                ^^^^ expected u32, found i8
+help: you can cast an `i8` to `u32`, which will sign-extend the source value
+    |
+149 |     foo::<u32>(x_i8 as u32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:151:16
+    |
+151 |     foo::<u32>(x_f64);
+    |                ^^^^^ expected u32, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `u32`, rounding the float towards zero
+    |
+151 |     foo::<u32>(x_f64 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:154:16
+    |
+154 |     foo::<u32>(x_f32);
+    |                ^^^^^ expected u32, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `u32`, rounding the float towards zero
+    |
+154 |     foo::<u32>(x_f32 as u32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:158:16
+    |
+158 |     foo::<i32>(x_usize);
+    |                ^^^^^^^ expected i32, found usize
+help: you can cast an `usize` to `i32`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+158 |     foo::<i32>(x_usize as i32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:160:16
+    |
+160 |     foo::<i32>(x_u64);
+    |                ^^^^^ expected i32, found u64
+help: you can cast an `u64` to `i32`, which will truncate the source value
+    |
+160 |     foo::<i32>(x_u64 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:162:16
+    |
+162 |     foo::<i32>(x_u32);
+    |                ^^^^^ expected i32, found u32
+help: you can cast an `u32` to `i32`, which will truncate the source value
+    |
+162 |     foo::<i32>(x_u32 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:164:16
+    |
+164 |     foo::<i32>(x_u16);
+    |                ^^^^^ expected i32, found u16
+help: you can cast an `u16` to `i32`, which will zero-extend the source value
+    |
+164 |     foo::<i32>(x_u16 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:166:16
+    |
+166 |     foo::<i32>(x_u8);
+    |                ^^^^ expected i32, found u8
+help: you can cast an `u8` to `i32`, which will zero-extend the source value
+    |
+166 |     foo::<i32>(x_u8 as i32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:168:16
+    |
+168 |     foo::<i32>(x_isize);
+    |                ^^^^^^^ expected i32, found isize
+help: you can cast an `isize` to `i32`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+168 |     foo::<i32>(x_isize as i32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:170:16
+    |
+170 |     foo::<i32>(x_i64);
+    |                ^^^^^ expected i32, found i64
+help: you can cast an `i64` to `i32`, which will truncate the source value
+    |
+170 |     foo::<i32>(x_i64 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:173:16
+    |
+173 |     foo::<i32>(x_i16);
+    |                ^^^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+    |
+173 |     foo::<i32>(x_i16 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:175:16
+    |
+175 |     foo::<i32>(x_i8);
+    |                ^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+    |
+175 |     foo::<i32>(x_i8 as i32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:177:16
+    |
+177 |     foo::<i32>(x_f64);
+    |                ^^^^^ expected i32, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `i32`, rounding the float towards zero
+    |
+177 |     foo::<i32>(x_f64 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:180:16
+    |
+180 |     foo::<i32>(x_f32);
+    |                ^^^^^ expected i32, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `i32`, rounding the float towards zero
+    |
+180 |     foo::<i32>(x_f32 as i32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:184:16
+    |
+184 |     foo::<u16>(x_usize);
+    |                ^^^^^^^ expected u16, found usize
+help: you can cast an `usize` to `u16`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+184 |     foo::<u16>(x_usize as u16);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:186:16
+    |
+186 |     foo::<u16>(x_u64);
+    |                ^^^^^ expected u16, found u64
+help: you can cast an `u64` to `u16`, which will truncate the source value
+    |
+186 |     foo::<u16>(x_u64 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:188:16
+    |
+188 |     foo::<u16>(x_u32);
+    |                ^^^^^ expected u16, found u32
+help: you can cast an `u32` to `u16`, which will truncate the source value
+    |
+188 |     foo::<u16>(x_u32 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:191:16
+    |
+191 |     foo::<u16>(x_u8);
+    |                ^^^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+    |
+191 |     foo::<u16>(x_u8 as u16);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:193:16
+    |
+193 |     foo::<u16>(x_isize);
+    |                ^^^^^^^ expected u16, found isize
+help: you can cast an `isize` to `u16`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+193 |     foo::<u16>(x_isize as u16);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:195:16
+    |
+195 |     foo::<u16>(x_i64);
+    |                ^^^^^ expected u16, found i64
+help: you can cast an `i64` to `u16`, which will truncate the source value
+    |
+195 |     foo::<u16>(x_i64 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:197:16
+    |
+197 |     foo::<u16>(x_i32);
+    |                ^^^^^ expected u16, found i32
+help: you can cast an `i32` to `u16`, which will truncate the source value
+    |
+197 |     foo::<u16>(x_i32 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:199:16
+    |
+199 |     foo::<u16>(x_i16);
+    |                ^^^^^ expected u16, found i16
+help: you can cast an `i16` to `u16`, which will sign-extend the source value
+    |
+199 |     foo::<u16>(x_i16 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:201:16
+    |
+201 |     foo::<u16>(x_i8);
+    |                ^^^^ expected u16, found i8
+help: you can cast an `i8` to `u16`, which will sign-extend the source value
+    |
+201 |     foo::<u16>(x_i8 as u16);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:203:16
+    |
+203 |     foo::<u16>(x_f64);
+    |                ^^^^^ expected u16, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `u16`, rounding the float towards zero
+    |
+203 |     foo::<u16>(x_f64 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:206:16
+    |
+206 |     foo::<u16>(x_f32);
+    |                ^^^^^ expected u16, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `u16`, rounding the float towards zero
+    |
+206 |     foo::<u16>(x_f32 as u16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:210:16
+    |
+210 |     foo::<i16>(x_usize);
+    |                ^^^^^^^ expected i16, found usize
+help: you can cast an `usize` to `i16`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+210 |     foo::<i16>(x_usize as i16);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:212:16
+    |
+212 |     foo::<i16>(x_u64);
+    |                ^^^^^ expected i16, found u64
+help: you can cast an `u64` to `i16`, which will truncate the source value
+    |
+212 |     foo::<i16>(x_u64 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:214:16
+    |
+214 |     foo::<i16>(x_u32);
+    |                ^^^^^ expected i16, found u32
+help: you can cast an `u32` to `i16`, which will truncate the source value
+    |
+214 |     foo::<i16>(x_u32 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:216:16
+    |
+216 |     foo::<i16>(x_u16);
+    |                ^^^^^ expected i16, found u16
+help: you can cast an `u16` to `i16`, which will truncate the source value
+    |
+216 |     foo::<i16>(x_u16 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:218:16
+    |
+218 |     foo::<i16>(x_u8);
+    |                ^^^^ expected i16, found u8
+help: you can cast an `u8` to `i16`, which will zero-extend the source value
+    |
+218 |     foo::<i16>(x_u8 as i16);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:220:16
+    |
+220 |     foo::<i16>(x_isize);
+    |                ^^^^^^^ expected i16, found isize
+help: you can cast an `isize` to `i16`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+220 |     foo::<i16>(x_isize as i16);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:222:16
+    |
+222 |     foo::<i16>(x_i64);
+    |                ^^^^^ expected i16, found i64
+help: you can cast an `i64` to `i16`, which will truncate the source value
+    |
+222 |     foo::<i16>(x_i64 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:224:16
+    |
+224 |     foo::<i16>(x_i32);
+    |                ^^^^^ expected i16, found i32
+help: you can cast an `i32` to `i16`, which will truncate the source value
+    |
+224 |     foo::<i16>(x_i32 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:227:16
+    |
+227 |     foo::<i16>(x_i8);
+    |                ^^^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+    |
+227 |     foo::<i16>(x_i8 as i16);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:229:16
+    |
+229 |     foo::<i16>(x_f64);
+    |                ^^^^^ expected i16, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `i16`, rounding the float towards zero
+    |
+229 |     foo::<i16>(x_f64 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:232:16
+    |
+232 |     foo::<i16>(x_f32);
+    |                ^^^^^ expected i16, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `i16`, rounding the float towards zero
+    |
+232 |     foo::<i16>(x_f32 as i16);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:236:15
+    |
+236 |     foo::<u8>(x_usize);
+    |               ^^^^^^^ expected u8, found usize
+help: you can cast an `usize` to `u8`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+236 |     foo::<u8>(x_usize as u8);
+    |               ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:238:15
+    |
+238 |     foo::<u8>(x_u64);
+    |               ^^^^^ expected u8, found u64
+help: you can cast an `u64` to `u8`, which will truncate the source value
+    |
+238 |     foo::<u8>(x_u64 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:240:15
+    |
+240 |     foo::<u8>(x_u32);
+    |               ^^^^^ expected u8, found u32
+help: you can cast an `u32` to `u8`, which will truncate the source value
+    |
+240 |     foo::<u8>(x_u32 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:242:15
+    |
+242 |     foo::<u8>(x_u16);
+    |               ^^^^^ expected u8, found u16
+help: you can cast an `u16` to `u8`, which will truncate the source value
+    |
+242 |     foo::<u8>(x_u16 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:245:15
+    |
+245 |     foo::<u8>(x_isize);
+    |               ^^^^^^^ expected u8, found isize
+help: you can cast an `isize` to `u8`, which will truncate or zero-extend depending on the bit width of `usize`
+    |
+245 |     foo::<u8>(x_isize as u8);
+    |               ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:247:15
+    |
+247 |     foo::<u8>(x_i64);
+    |               ^^^^^ expected u8, found i64
+help: you can cast an `i64` to `u8`, which will truncate the source value
+    |
+247 |     foo::<u8>(x_i64 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:249:15
+    |
+249 |     foo::<u8>(x_i32);
+    |               ^^^^^ expected u8, found i32
+help: you can cast an `i32` to `u8`, which will truncate the source value
+    |
+249 |     foo::<u8>(x_i32 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:251:15
+    |
+251 |     foo::<u8>(x_i16);
+    |               ^^^^^ expected u8, found i16
+help: you can cast an `i16` to `u8`, which will truncate the source value
+    |
+251 |     foo::<u8>(x_i16 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:253:15
+    |
+253 |     foo::<u8>(x_i8);
+    |               ^^^^ expected u8, found i8
+help: you can cast an `i8` to `u8`, which will sign-extend the source value
+    |
+253 |     foo::<u8>(x_i8 as u8);
+    |               ^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:255:15
+    |
+255 |     foo::<u8>(x_f64);
+    |               ^^^^^ expected u8, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `u8`, rounding the float towards zero
+    |
+255 |     foo::<u8>(x_f64 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:258:15
+    |
+258 |     foo::<u8>(x_f32);
+    |               ^^^^^ expected u8, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `u8`, rounding the float towards zero
+    |
+258 |     foo::<u8>(x_f32 as u8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:262:15
+    |
+262 |     foo::<i8>(x_usize);
+    |               ^^^^^^^ expected i8, found usize
+help: you can cast an `usize` to `i8`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+262 |     foo::<i8>(x_usize as i8);
+    |               ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:264:15
+    |
+264 |     foo::<i8>(x_u64);
+    |               ^^^^^ expected i8, found u64
+help: you can cast an `u64` to `i8`, which will truncate the source value
+    |
+264 |     foo::<i8>(x_u64 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:266:15
+    |
+266 |     foo::<i8>(x_u32);
+    |               ^^^^^ expected i8, found u32
+help: you can cast an `u32` to `i8`, which will truncate the source value
+    |
+266 |     foo::<i8>(x_u32 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:268:15
+    |
+268 |     foo::<i8>(x_u16);
+    |               ^^^^^ expected i8, found u16
+help: you can cast an `u16` to `i8`, which will truncate the source value
+    |
+268 |     foo::<i8>(x_u16 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:270:15
+    |
+270 |     foo::<i8>(x_u8);
+    |               ^^^^ expected i8, found u8
+help: you can cast an `u8` to `i8`, which will truncate the source value
+    |
+270 |     foo::<i8>(x_u8 as i8);
+    |               ^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:272:15
+    |
+272 |     foo::<i8>(x_isize);
+    |               ^^^^^^^ expected i8, found isize
+help: you can cast an `isize` to `i8`, which will truncate or zero-extend depending on the bit width of `isize`
+    |
+272 |     foo::<i8>(x_isize as i8);
+    |               ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:274:15
+    |
+274 |     foo::<i8>(x_i64);
+    |               ^^^^^ expected i8, found i64
+help: you can cast an `i64` to `i8`, which will truncate the source value
+    |
+274 |     foo::<i8>(x_i64 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:276:15
+    |
+276 |     foo::<i8>(x_i32);
+    |               ^^^^^ expected i8, found i32
+help: you can cast an `i32` to `i8`, which will truncate the source value
+    |
+276 |     foo::<i8>(x_i32 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:278:15
+    |
+278 |     foo::<i8>(x_i16);
+    |               ^^^^^ expected i8, found i16
+help: you can cast an `i16` to `i8`, which will truncate the source value
+    |
+278 |     foo::<i8>(x_i16 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:281:15
+    |
+281 |     foo::<i8>(x_f64);
+    |               ^^^^^ expected i8, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f64` to `i8`, rounding the float towards zero
+    |
+281 |     foo::<i8>(x_f64 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:284:15
+    |
+284 |     foo::<i8>(x_f32);
+    |               ^^^^^ expected i8, found f32
+    |
+    = warning: Currently this will cause Undefined Behavior if the rounded value cannot be represented by the target integer type. This includes `Inf` and `NaN`. This is a bug and will be fixed.
+help: you can cast an `f32` to `i8`, rounding the float towards zero
+    |
+284 |     foo::<i8>(x_f32 as i8);
+    |               ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:288:16
+    |
+288 |     foo::<f64>(x_usize);
+    |                ^^^^^^^ expected f64, found usize
+help: you can cast an `usize` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+288 |     foo::<f64>(x_usize as f64);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:290:16
+    |
+290 |     foo::<f64>(x_u64);
+    |                ^^^^^ expected f64, found u64
+help: you can cast an `u64` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+290 |     foo::<f64>(x_u64 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:292:16
+    |
+292 |     foo::<f64>(x_u32);
+    |                ^^^^^ expected f64, found u32
+help: you can cast an `u32` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+292 |     foo::<f64>(x_u32 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:294:16
+    |
+294 |     foo::<f64>(x_u16);
+    |                ^^^^^ expected f64, found u16
+help: you can cast an `u16` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+294 |     foo::<f64>(x_u16 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:296:16
+    |
+296 |     foo::<f64>(x_u8);
+    |                ^^^^ expected f64, found u8
+help: you can cast an `u8` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+296 |     foo::<f64>(x_u8 as f64);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:298:16
+    |
+298 |     foo::<f64>(x_isize);
+    |                ^^^^^^^ expected f64, found isize
+help: you can cast an `isize` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+298 |     foo::<f64>(x_isize as f64);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:300:16
+    |
+300 |     foo::<f64>(x_i64);
+    |                ^^^^^ expected f64, found i64
+help: you can cast an `i64` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+300 |     foo::<f64>(x_i64 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:302:16
+    |
+302 |     foo::<f64>(x_i32);
+    |                ^^^^^ expected f64, found i32
+help: you can cast an `i32` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+302 |     foo::<f64>(x_i32 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:304:16
+    |
+304 |     foo::<f64>(x_i16);
+    |                ^^^^^ expected f64, found i16
+help: you can cast an `i16` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+304 |     foo::<f64>(x_i16 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:306:16
+    |
+306 |     foo::<f64>(x_i8);
+    |                ^^^^ expected f64, found i8
+help: you can cast an `i8` to `f64`, producing the floating point representation of the integer, rounded if necessary
+    |
+306 |     foo::<f64>(x_i8 as f64);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:309:16
+    |
+309 |     foo::<f64>(x_f32);
+    |                ^^^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+    |
+309 |     foo::<f64>(x_f32 as f64);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:312:16
+    |
+312 |     foo::<f32>(x_usize);
+    |                ^^^^^^^ expected f32, found usize
+help: you can cast an `usize` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+312 |     foo::<f32>(x_usize as f32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:314:16
+    |
+314 |     foo::<f32>(x_u64);
+    |                ^^^^^ expected f32, found u64
+help: you can cast an `u64` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+314 |     foo::<f32>(x_u64 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:316:16
+    |
+316 |     foo::<f32>(x_u32);
+    |                ^^^^^ expected f32, found u32
+help: you can cast an `u32` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+316 |     foo::<f32>(x_u32 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:318:16
+    |
+318 |     foo::<f32>(x_u16);
+    |                ^^^^^ expected f32, found u16
+help: you can cast an `u16` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+318 |     foo::<f32>(x_u16 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:320:16
+    |
+320 |     foo::<f32>(x_u8);
+    |                ^^^^ expected f32, found u8
+help: you can cast an `u8` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+320 |     foo::<f32>(x_u8 as f32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:322:16
+    |
+322 |     foo::<f32>(x_isize);
+    |                ^^^^^^^ expected f32, found isize
+help: you can cast an `isize` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+322 |     foo::<f32>(x_isize as f32);
+    |                ^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:324:16
+    |
+324 |     foo::<f32>(x_i64);
+    |                ^^^^^ expected f32, found i64
+help: you can cast an `i64` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+324 |     foo::<f32>(x_i64 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:326:16
+    |
+326 |     foo::<f32>(x_i32);
+    |                ^^^^^ expected f32, found i32
+help: you can cast an `i32` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+326 |     foo::<f32>(x_i32 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:328:16
+    |
+328 |     foo::<f32>(x_i16);
+    |                ^^^^^ expected f32, found i16
+help: you can cast an `i16` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+328 |     foo::<f32>(x_i16 as f32);
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:330:16
+    |
+330 |     foo::<f32>(x_i8);
+    |                ^^^^ expected f32, found i8
+help: you can cast an `i8` to `f32`, producing the floating point representation of the integer, rounded if necessary
+    |
+330 |     foo::<f32>(x_i8 as f32);
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:332:16
+    |
+332 |     foo::<f32>(x_f64);
+    |                ^^^^^ expected f32, found f64
+    |
+    = warning: Currently this will cause Undefined Behavior if the value is finite but larger or smaller than the largest or smallest finite value representable by `f32`. This is a bug and will be fixed.
+help: you can cast an `f64` to `f32`, producing the closest possible value
+    |
+332 |     foo::<f32>(x_f64 as f32);
+    |                ^^^^^^^^^^^^
+
+error: aborting due to 132 previous errors
+