about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-01-21 22:38:29 +0000
committerbors <bors@rust-lang.org>2018-01-21 22:38:29 +0000
commitff2a7c85757542f454934e00605355bbca7bc196 (patch)
tree9baf95d78fe95a7d6b6424cab8e61c8877fb258a
parent97520ccb101609af63f29919bb0a39115269c89e (diff)
parentdcbf0bf5f5f59f936f32d18b729c66f236a974da (diff)
downloadrust-ff2a7c85757542f454934e00605355bbca7bc196.tar.gz
rust-ff2a7c85757542f454934e00605355bbca7bc196.zip
Auto merge of #47644 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 9 pull requests

- Successful merges: #47247, #47334, #47512, #47582, #47595, #47625, #47632, #47633, #47637
- Failed merges:
-rw-r--r--.mailmap5
-rw-r--r--src/bootstrap/channel.rs5
-rw-r--r--src/bootstrap/dist.rs1
-rw-r--r--src/bootstrap/lib.rs53
-rwxr-xr-xsrc/ci/init_repo.sh6
-rw-r--r--src/liballoc/btree/set.rs24
-rw-r--r--src/liballoc/slice.rs8
-rw-r--r--src/liballoc/vec_deque.rs15
-rw-r--r--src/librustc/hir/lowering.rs3
-rw-r--r--src/librustc/hir/mod.rs64
-rw-r--r--src/librustc/hir/print.rs51
-rw-r--r--src/librustc_resolve/diagnostics.rs53
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs244
-rw-r--r--src/libstd/sys/unix/l4re.rs4
-rw-r--r--src/libstd/sys/unix/net.rs20
-rw-r--r--src/libstd/sys_common/net.rs24
-rw-r--r--src/libsyntax/ast.rs46
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/util/parser.rs182
-rw-r--r--src/test/compile-fail/E0659.rs26
-rw-r--r--src/test/ui/imports/duplicate.stderr8
-rw-r--r--src/test/ui/imports/macro-paths.stderr4
-rw-r--r--src/test/ui/imports/macros.stderr4
-rw-r--r--src/test/ui/imports/shadow_builtin_macros.stderr6
-rw-r--r--src/test/ui/issue-47623.rs13
-rw-r--r--src/test/ui/issue-47623.stderr8
-rw-r--r--src/test/ui/suggestions/numeric-cast-2.rs21
-rw-r--r--src/test/ui/suggestions/numeric-cast-2.stderr20
-rw-r--r--src/test/ui/suggestions/numeric-cast.rs315
-rw-r--r--src/test/ui/suggestions/numeric-cast.stderr886
31 files changed, 1935 insertions, 188 deletions
diff --git a/.mailmap b/.mailmap
index c2d3b28602b..9034aae1714 100644
--- a/.mailmap
+++ b/.mailmap
@@ -41,11 +41,12 @@ Boris Egorov <jightuse@gmail.com> <egorov@linux.com>
 Brandon Sanderson <singingboyo@gmail.com> Brandon Sanderson <singingboyo@hotmail.com>
 Brett Cannon <brett@python.org> Brett Cannon <brettcannon@users.noreply.github.com>
 Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com>
+Brian Anderson <banderson@mozilla.com> <banderson@mozilla.org>
 Brian Dawn <brian.t.dawn@gmail.com>
 Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com>
 Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
-Carol (Nichols || Goulding) <carol.nichols@gmail.com>
-Carol (Nichols || Goulding) <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <carol.nichols@gmail.com>
 Carol Willing <carolcode@willingconsulting.com>
 Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
 Chris Pressey <cpressey@gmail.com>
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 4e3f3a00b15..e412dd9e3e6 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -26,11 +26,6 @@ use config::Config;
 // The version number
 pub const CFG_RELEASE_NUM: &str = "1.25.0";
 
-// An optional number to put after the label, e.g. '.2' -> '-beta.2'
-// Be sure to make this starts with a dot to conform to semver pre-release
-// versions (section 9)
-pub const CFG_PRERELEASE_VERSION: &str = ".1";
-
 pub struct GitInfo {
     inner: Option<Info>,
 }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 7f0613aabe6..224b31ef268 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1652,7 +1652,6 @@ fn add_env(build: &Build, cmd: &mut Command, target: Interned<String>) {
     cmd.env("CFG_RELEASE_INFO", build.rust_version())
        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
        .env("CFG_RELEASE", build.rust_release())
-       .env("CFG_PRERELEASE_VERSION", channel::CFG_PRERELEASE_VERSION)
        .env("CFG_VER_MAJOR", parts.next().unwrap())
        .env("CFG_VER_MINOR", parts.next().unwrap())
        .env("CFG_VER_PATCH", parts.next().unwrap())
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 948bf29bbac..3738828a4ba 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -134,7 +134,7 @@ extern crate toml;
 #[cfg(unix)]
 extern crate libc;
 
-use std::cell::RefCell;
+use std::cell::{RefCell, Cell};
 use std::collections::{HashSet, HashMap};
 use std::env;
 use std::fs::{self, File};
@@ -250,6 +250,7 @@ pub struct Build {
     is_sudo: bool,
     ci_env: CiEnv,
     delayed_failures: RefCell<Vec<String>>,
+    prerelease_version: Cell<Option<u32>>,
 }
 
 #[derive(Debug)]
@@ -335,6 +336,7 @@ impl Build {
             is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
+            prerelease_version: Cell::new(None),
         }
     }
 
@@ -774,12 +776,59 @@ impl Build {
     fn release(&self, num: &str) -> String {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
-            "beta" => format!("{}-beta{}", num, channel::CFG_PRERELEASE_VERSION),
+            "beta" => format!("{}-beta.{}", num, self.beta_prerelease_version()),
             "nightly" => format!("{}-nightly", num),
             _ => format!("{}-dev", num),
         }
     }
 
+    fn beta_prerelease_version(&self) -> u32 {
+        if let Some(s) = self.prerelease_version.get() {
+            return s
+        }
+
+        let beta = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("beta")
+                .current_dir(&self.src)
+        );
+        let beta = beta.trim().split_whitespace().next().unwrap();
+        let master = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("master")
+                .current_dir(&self.src)
+        );
+        let master = master.trim().split_whitespace().next().unwrap();
+
+        // Figure out where the current beta branch started.
+        let base = output(
+            Command::new("git")
+                .arg("merge-base")
+                .arg(beta)
+                .arg(master)
+                .current_dir(&self.src),
+        );
+        let base = base.trim();
+
+        // Next figure out how many merge commits happened since we branched off
+        // beta. That's our beta number!
+        let count = output(
+            Command::new("git")
+                .arg("rev-list")
+                .arg("--count")
+                .arg("--merges")
+                .arg(format!("{}...HEAD", base))
+                .current_dir(&self.src),
+        );
+        let n = count.trim().parse().unwrap();
+        self.prerelease_version.set(Some(n));
+        n
+    }
+
     /// Returns the value of `release` above for Rust itself.
     fn rust_release(&self) -> String {
         self.release(channel::CFG_RELEASE_NUM)
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
index e073a3d99c1..14a1906ff42 100755
--- a/src/ci/init_repo.sh
+++ b/src/ci/init_repo.sh
@@ -36,6 +36,12 @@ fi
 rm -rf "$CACHE_DIR"
 mkdir "$CACHE_DIR"
 
+# On the beta channel we'll be automatically calculating the prerelease version
+# via the git history, so unshallow our shallow clone from CI.
+if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
+  git fetch origin --unshallow beta master
+fi
+
 travis_fold start update_cache
 travis_time_start
 
diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs
index e094070fc3d..327eaaf4651 100644
--- a/src/liballoc/btree/set.rs
+++ b/src/liballoc/btree/set.rs
@@ -658,26 +658,26 @@ impl<T: Ord> BTreeSet<T> {
     /// Basic usage:
     ///
     /// ```
-    /// use std::collections::BTreeMap;
+    /// use std::collections::BTreeSet;
     ///
-    /// let mut a = BTreeMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    /// a.insert(3, "c");
-    /// a.insert(17, "d");
-    /// a.insert(41, "e");
+    /// let mut a = BTreeSet::new();
+    /// a.insert(1);
+    /// a.insert(2);
+    /// a.insert(3);
+    /// a.insert(17);
+    /// a.insert(41);
     ///
     /// let b = a.split_off(&3);
     ///
     /// assert_eq!(a.len(), 2);
     /// assert_eq!(b.len(), 3);
     ///
-    /// assert_eq!(a[&1], "a");
-    /// assert_eq!(a[&2], "b");
+    /// assert!(a.contains(&1));
+    /// assert!(a.contains(&2));
     ///
-    /// assert_eq!(b[&3], "c");
-    /// assert_eq!(b[&17], "d");
-    /// assert_eq!(b[&41], "e");
+    /// assert!(b.contains(&3));
+    /// assert!(b.contains(&17));
+    /// assert!(b.contains(&41));
     /// ```
     #[stable(feature = "btree_split_off", since = "1.11.0")]
     pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where T: Borrow<Q> {
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 861f72bcf88..028983de556 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -630,6 +630,8 @@ impl<T> [T] {
     /// assert_eq!(iter.next().unwrap(), &['m']);
     /// assert!(iter.next().is_none());
     /// ```
+    ///
+    /// [`exact_chunks`]: #method.exact_chunks
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
@@ -660,6 +662,8 @@ impl<T> [T] {
     /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
     /// assert!(iter.next().is_none());
     /// ```
+    ///
+    /// [`chunks`]: #method.chunks
     #[unstable(feature = "exact_chunks", issue = "47115")]
     #[inline]
     pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
@@ -692,6 +696,8 @@ impl<T> [T] {
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 3]);
     /// ```
+    ///
+    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
@@ -728,6 +734,8 @@ impl<T> [T] {
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 0]);
     /// ```
+    ///
+    /// [`chunks_mut`]: #method.chunks_mut
     #[unstable(feature = "exact_chunks", issue = "47115")]
     #[inline]
     pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs
index 69557fe2789..9259138bab0 100644
--- a/src/liballoc/vec_deque.rs
+++ b/src/liballoc/vec_deque.rs
@@ -906,7 +906,7 @@ impl<T> VecDeque<T> {
         }
     }
 
-    /// Clears the buffer, removing all values.
+    /// Clears the `VecDeque`, removing all values.
     ///
     /// # Examples
     ///
@@ -1624,10 +1624,10 @@ impl<T> VecDeque<T> {
         return elem;
     }
 
-    /// Splits the collection into two at the given index.
+    /// Splits the `VecDeque` into two at the given index.
     ///
-    /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
-    /// and the returned `Self` contains elements `[at, len)`.
+    /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`,
+    /// and the returned `VecDeque` contains elements `[at, len)`.
     ///
     /// Note that the capacity of `self` does not change.
     ///
@@ -1635,7 +1635,7 @@ impl<T> VecDeque<T> {
     ///
     /// # Panics
     ///
-    /// Panics if `at > len`
+    /// Panics if `at > len`.
     ///
     /// # Examples
     ///
@@ -1815,7 +1815,8 @@ impl<T> VecDeque<T> {
 
 impl<T: Clone> VecDeque<T> {
     /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
-    /// either by removing excess elements or by appending clones of `value` to the back.
+    /// either by removing excess elements from the back or by appending clones of `value`
+    /// to the back.
     ///
     /// # Examples
     ///
@@ -2390,7 +2391,7 @@ impl<T> IntoIterator for VecDeque<T> {
     type Item = T;
     type IntoIter = IntoIter<T>;
 
-    /// Consumes the list into a front-to-back iterator yielding elements by
+    /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
     /// value.
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { inner: self }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 238145a061f..32b55a05124 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2046,7 +2046,8 @@ impl<'a> LoweringContext<'a> {
                 };
 
                 // Correctly resolve `self` imports
-                if path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
+                if path.segments.len() > 1 &&
+                   path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
                     let _ = path.segments.pop();
                     if ident.name == keywords::SelfValue.name() {
                         *name = path.segments.last().unwrap().identifier.name;
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 8d43b9b4aa7..3da2855929d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -34,13 +34,14 @@ use util::nodemap::{NodeMap, FxHashSet};
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
-use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
+use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
 use syntax::util::ThinVec;
+use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
 
 use rustc_data_structures::indexed_vec;
@@ -958,6 +959,31 @@ impl BinOp_ {
     }
 }
 
+impl Into<ast::BinOpKind> for BinOp_ {
+    fn into(self) -> ast::BinOpKind {
+        match self {
+            BiAdd => ast::BinOpKind::Add,
+            BiSub => ast::BinOpKind::Sub,
+            BiMul => ast::BinOpKind::Mul,
+            BiDiv => ast::BinOpKind::Div,
+            BiRem => ast::BinOpKind::Rem,
+            BiAnd => ast::BinOpKind::And,
+            BiOr => ast::BinOpKind::Or,
+            BiBitXor => ast::BinOpKind::BitXor,
+            BiBitAnd => ast::BinOpKind::BitAnd,
+            BiBitOr => ast::BinOpKind::BitOr,
+            BiShl => ast::BinOpKind::Shl,
+            BiShr => ast::BinOpKind::Shr,
+            BiEq => ast::BinOpKind::Eq,
+            BiLt => ast::BinOpKind::Lt,
+            BiLe => ast::BinOpKind::Le,
+            BiNe => ast::BinOpKind::Ne,
+            BiGe => ast::BinOpKind::Ge,
+            BiGt => ast::BinOpKind::Gt,
+        }
+    }
+}
+
 pub type BinOp = Spanned<BinOp_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1166,6 +1192,42 @@ pub struct Expr {
     pub hir_id: HirId,
 }
 
+impl Expr {
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprBox(_) => ExprPrecedence::Box,
+            ExprArray(_) => ExprPrecedence::Array,
+            ExprCall(..) => ExprPrecedence::Call,
+            ExprMethodCall(..) => ExprPrecedence::MethodCall,
+            ExprTup(_) => ExprPrecedence::Tup,
+            ExprBinary(op, ..) => ExprPrecedence::Binary(op.node.into()),
+            ExprUnary(..) => ExprPrecedence::Unary,
+            ExprLit(_) => ExprPrecedence::Lit,
+            ExprType(..) | ExprCast(..) => ExprPrecedence::Cast,
+            ExprIf(..) => ExprPrecedence::If,
+            ExprWhile(..) => ExprPrecedence::While,
+            ExprLoop(..) => ExprPrecedence::Loop,
+            ExprMatch(..) => ExprPrecedence::Match,
+            ExprClosure(..) => ExprPrecedence::Closure,
+            ExprBlock(..) => ExprPrecedence::Block,
+            ExprAssign(..) => ExprPrecedence::Assign,
+            ExprAssignOp(..) => ExprPrecedence::AssignOp,
+            ExprField(..) => ExprPrecedence::Field,
+            ExprTupField(..) => ExprPrecedence::TupField,
+            ExprIndex(..) => ExprPrecedence::Index,
+            ExprPath(..) => ExprPrecedence::Path,
+            ExprAddrOf(..) => ExprPrecedence::AddrOf,
+            ExprBreak(..) => ExprPrecedence::Break,
+            ExprAgain(..) => ExprPrecedence::Continue,
+            ExprRet(..) => ExprPrecedence::Ret,
+            ExprInlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprStruct(..) => ExprPrecedence::Struct,
+            ExprRepeat(..) => ExprPrecedence::Repeat,
+            ExprYield(..) => ExprPrecedence::Yield,
+        }
+    }
+}
+
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "expr({}: {})", self.id,
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index a8e55674ae5..4cfa7a470a4 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1104,7 +1104,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
@@ -2318,55 +2318,6 @@ fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
     }
 }
 
-
-fn expr_precedence(expr: &hir::Expr) -> i8 {
-    use syntax::util::parser::*;
-
-    match expr.node {
-        hir::ExprClosure(..) => PREC_CLOSURE,
-
-        hir::ExprBreak(..) |
-        hir::ExprAgain(..) |
-        hir::ExprRet(..) |
-        hir::ExprYield(..) => PREC_JUMP,
-
-        // Binop-like expr kinds, handled by `AssocOp`.
-        hir::ExprBinary(op, _, _) => bin_op_to_assoc_op(op.node).precedence() as i8,
-
-        hir::ExprCast(..) => AssocOp::As.precedence() as i8,
-        hir::ExprType(..) => AssocOp::Colon.precedence() as i8,
-
-        hir::ExprAssign(..) |
-        hir::ExprAssignOp(..) => AssocOp::Assign.precedence() as i8,
-
-        // Unary, prefix
-        hir::ExprBox(..) |
-        hir::ExprAddrOf(..) |
-        hir::ExprUnary(..) => PREC_PREFIX,
-
-        // Unary, postfix
-        hir::ExprCall(..) |
-        hir::ExprMethodCall(..) |
-        hir::ExprField(..) |
-        hir::ExprTupField(..) |
-        hir::ExprIndex(..) |
-        hir::ExprInlineAsm(..) => PREC_POSTFIX,
-
-        // Never need parens
-        hir::ExprArray(..) |
-        hir::ExprRepeat(..) |
-        hir::ExprTup(..) |
-        hir::ExprLit(..) |
-        hir::ExprPath(..) |
-        hir::ExprIf(..) |
-        hir::ExprWhile(..) |
-        hir::ExprLoop(..) |
-        hir::ExprMatch(..) |
-        hir::ExprBlock(..) |
-        hir::ExprStruct(..) => PREC_PAREN,
-    }
-}
-
 fn bin_op_to_assoc_op(op: hir::BinOp_) -> AssocOp {
     use hir::BinOp_::*;
     match op {
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 3f0f1a1a4cb..8a29155d12d 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -1621,6 +1621,59 @@ println!("const value: {}", SomeModule::PRIVATE); // ok!
 ```
 "##,
 
+E0659: r##"
+An item usage is ambiguous.
+
+Erroneous code example:
+
+```compile_fail,E0659
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); // ERROR: `foo` is ambiguous
+}
+```
+
+This error generally appears when two items with the same name are imported into
+a module. Here, the `foo` functions are imported and reexported from the
+`collider` module and therefore, when we're using `collider::foo()`, both
+functions collide.
+
+To solve this error, the best solution is generally to keep the path before the
+item when using it. Example:
+
+```
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon;
+    pub use earth;
+}
+
+fn main() {
+    collider::moon::foo(); // ok!
+    collider::earth::foo(); // ok!
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 5429dbccc58..d9ae776a4d7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3802,7 +3802,7 @@ impl<'a> Resolver<'a> {
                 self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, &msg);
             } else {
                 let mut err =
-                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
+                    struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
                 err.span_note(b1.span, &msg1);
                 match b2.def() {
                     Def::Macro(..) if b2.span == DUMMY_SP =>
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 6703bbba86b..b6b863cfea6 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -15,6 +15,7 @@ use rustc::infer::InferOk;
 use rustc::traits::ObligationCause;
 
 use syntax::ast;
+use syntax::util::parser::AssocOp;
 use syntax_pos::{self, Span};
 use rustc::hir;
 use rustc::hir::print;
@@ -137,7 +138,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 +288,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 +303,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                  format!("*{}", code)));
                                 }
                             }
-                        },
+                        }
                     }
                 }
                 None
@@ -311,4 +311,240 @@ 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";
+
+        // 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.
+        //
+        // For now, don't suggest casting with `as`.
+        let can_cast = false;
+
+        let needs_paren = expr.precedence().order() < (AssocOp::As.precedence() as i8);
+
+        if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+            let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
+            let cast_suggestion = format!("{}{}{} as {}",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" },
+                                          expected_ty);
+            let into_suggestion = format!("{}{}{}.into()",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" });
+
+            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 => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_zero_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
+                    if can_cast {
+                        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),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_zero_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
+                    if can_cast {
+                        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),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
+                    if found.bit_width() < exp.bit_width() {
+                        err.span_suggestion(expr.span,
+                                            &format!("{} in a lossless way",
+                                                     msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the closest possible value",
+                                                     msg),
+                                            cast_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)");
+                    }
+                    true
+                }
+                (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
+                    if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, rounding the float towards zero",
+                                                     msg),
+                                            cast_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(ref exp), &ty::TyUint(ref found)) => {
+                    // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => {
+                    // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                _ => false,
+            }
+        } else {
+            false
+        }
+    }
 }
diff --git a/src/libstd/sys/unix/l4re.rs b/src/libstd/sys/unix/l4re.rs
index c3e8d0b7d95..21218489679 100644
--- a/src/libstd/sys/unix/l4re.rs
+++ b/src/libstd/sys/unix/l4re.rs
@@ -437,9 +437,5 @@ pub mod net {
     pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
         unimpl!();
     }
-
-    pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
-        unimpl!();
-    }
 }
 
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index e775f857f2b..3f65975e608 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -51,6 +51,10 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 {
         return Ok(())
     }
+
+    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+    on_resolver_failure();
+
     if err == EAI_SYSTEM {
         return Err(io::Error::last_os_error())
     }
@@ -377,21 +381,22 @@ impl IntoInner<c_int> for Socket {
 // res_init unconditionally, we call it only when we detect we're linking
 // against glibc version < 2.26. (That is, when we both know its needed and
 // believe it's thread-safe).
-pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
     // If the version fails to parse, we treat it the same as "not glibc".
     if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
         if let Some(version) = parse_glibc_version(version_str) {
             if version < (2, 26) {
-                let ret = unsafe { libc::res_init() };
-                if ret != 0 {
-                    return Err(io::Error::last_os_error());
-                }
+                unsafe { libc::res_init() };
             }
         }
     }
-    Ok(())
 }
 
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
+
+#[cfg(target_env = "gnu")]
 fn glibc_version_cstr() -> Option<&'static CStr> {
     weak! {
         fn gnu_get_libc_version() -> *const libc::c_char
@@ -405,6 +410,7 @@ fn glibc_version_cstr() -> Option<&'static CStr> {
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
+#[cfg(target_env = "gnu")]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
@@ -413,7 +419,7 @@ fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
 mod test {
     use super::*;
 
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index c70b39995eb..b841afe1a51 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -166,27 +166,9 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     hints.ai_socktype = c::SOCK_STREAM;
     let mut res = ptr::null_mut();
     unsafe {
-        match cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)) {
-            Ok(_) => {
-                Ok(LookupHost { original: res, cur: res })
-            },
-            #[cfg(unix)]
-            Err(e) => {
-                // If we're running glibc prior to version 2.26, the lookup
-                // failure could be caused by caching a stale /etc/resolv.conf.
-                // We need to call libc::res_init() to clear the cache. But we
-                // shouldn't call it in on any other platform, because other
-                // res_init implementations aren't thread-safe. See
-                // https://github.com/rust-lang/rust/issues/41570 and
-                // https://github.com/rust-lang/rust/issues/43592.
-                use sys::net::res_init_if_glibc_before_2_26;
-                let _ = res_init_if_glibc_before_2_26();
-                Err(e)
-            },
-            // the cfg is needed here to avoid an "unreachable pattern" warning
-            #[cfg(not(unix))]
-            Err(e) => Err(e),
-        }
+        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| {
+            LookupHost { original: res, cur: res }
+        })
     }
 }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9c0622e7bef..a64f1e9e400 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,6 +15,7 @@ pub use self::UnsafeSource::*;
 pub use self::PathParameters::*;
 pub use symbol::{Ident, Symbol as Name};
 pub use util::ThinVec;
+pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
@@ -730,6 +731,7 @@ impl BinOpKind {
             _ => false
         }
     }
+
     pub fn is_comparison(&self) -> bool {
         use self::BinOpKind::*;
         match *self {
@@ -740,6 +742,7 @@ impl BinOpKind {
             false,
         }
     }
+
     /// Returns `true` if the binary operator takes its arguments by value
     pub fn is_by_value(&self) -> bool {
         !self.is_comparison()
@@ -966,6 +969,49 @@ impl Expr {
 
         Some(P(Ty { node, id: self.id, span: self.span }))
     }
+
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprKind::Box(_) => ExprPrecedence::Box,
+            ExprKind::InPlace(..) => ExprPrecedence::InPlace,
+            ExprKind::Array(_) => ExprPrecedence::Array,
+            ExprKind::Call(..) => ExprPrecedence::Call,
+            ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
+            ExprKind::Tup(_) => ExprPrecedence::Tup,
+            ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
+            ExprKind::Unary(..) => ExprPrecedence::Unary,
+            ExprKind::Lit(_) => ExprPrecedence::Lit,
+            ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
+            ExprKind::If(..) => ExprPrecedence::If,
+            ExprKind::IfLet(..) => ExprPrecedence::IfLet,
+            ExprKind::While(..) => ExprPrecedence::While,
+            ExprKind::WhileLet(..) => ExprPrecedence::WhileLet,
+            ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
+            ExprKind::Loop(..) => ExprPrecedence::Loop,
+            ExprKind::Match(..) => ExprPrecedence::Match,
+            ExprKind::Closure(..) => ExprPrecedence::Closure,
+            ExprKind::Block(..) => ExprPrecedence::Block,
+            ExprKind::Catch(..) => ExprPrecedence::Catch,
+            ExprKind::Assign(..) => ExprPrecedence::Assign,
+            ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
+            ExprKind::Field(..) => ExprPrecedence::Field,
+            ExprKind::TupField(..) => ExprPrecedence::TupField,
+            ExprKind::Index(..) => ExprPrecedence::Index,
+            ExprKind::Range(..) => ExprPrecedence::Range,
+            ExprKind::Path(..) => ExprPrecedence::Path,
+            ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
+            ExprKind::Break(..) => ExprPrecedence::Break,
+            ExprKind::Continue(..) => ExprPrecedence::Continue,
+            ExprKind::Ret(..) => ExprPrecedence::Ret,
+            ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::Mac(..) => ExprPrecedence::Mac,
+            ExprKind::Struct(..) => ExprPrecedence::Struct,
+            ExprKind::Repeat(..) => ExprPrecedence::Repeat,
+            ExprKind::Paren(..) => ExprPrecedence::Paren,
+            ExprKind::Try(..) => ExprPrecedence::Try,
+            ExprKind::Yield(..) => ExprPrecedence::Yield,
+        }
+    }
 }
 
 impl fmt::Debug for Expr {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5374bf180f4..ff065b57b8d 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1839,7 +1839,7 @@ impl<'a> State<'a> {
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = parser::expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index 6014ec5aa92..86963c4000b 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -9,7 +9,9 @@
 // except according to those terms.
 use parse::token::{Token, BinOpToken};
 use symbol::keywords;
-use ast::{self, BinOpKind, ExprKind};
+use ast::{self, BinOpKind};
+
+use std::cmp::Ordering;
 
 /// Associative operator with precedence.
 ///
@@ -228,66 +230,130 @@ pub const PREC_POSTFIX: i8 = 60;
 pub const PREC_PAREN: i8 = 99;
 pub const PREC_FORCE_PAREN: i8 = 100;
 
-pub fn expr_precedence(expr: &ast::Expr) -> i8 {
-    match expr.node {
-        ExprKind::Closure(..) => PREC_CLOSURE,
-
-        ExprKind::Break(..) |
-        ExprKind::Continue(..) |
-        ExprKind::Ret(..) |
-        ExprKind::Yield(..) => PREC_JUMP,
-
-        // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to parse,
-        // instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence ensures that
-        // `pprust` will add parentheses in the right places to get the desired parse.
-        ExprKind::Range(..) => PREC_RANGE,
-
-        // Binop-like expr kinds, handled by `AssocOp`.
-        ExprKind::Binary(op, _, _) =>
-            AssocOp::from_ast_binop(op.node).precedence() as i8,
-
-        ExprKind::InPlace(..) => AssocOp::Inplace.precedence() as i8,
-        ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
-        ExprKind::Type(..) => AssocOp::Colon.precedence() as i8,
-
-        ExprKind::Assign(..) |
-        ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
-
-        // Unary, prefix
-        ExprKind::Box(..) |
-        ExprKind::AddrOf(..) |
-        ExprKind::Unary(..) => PREC_PREFIX,
-
-        // Unary, postfix
-        ExprKind::Call(..) |
-        ExprKind::MethodCall(..) |
-        ExprKind::Field(..) |
-        ExprKind::TupField(..) |
-        ExprKind::Index(..) |
-        ExprKind::Try(..) |
-        ExprKind::InlineAsm(..) |
-        ExprKind::Mac(..) => PREC_POSTFIX,
-
-        // Never need parens
-        ExprKind::Array(..) |
-        ExprKind::Repeat(..) |
-        ExprKind::Tup(..) |
-        ExprKind::Lit(..) |
-        ExprKind::Path(..) |
-        ExprKind::Paren(..) |
-        ExprKind::If(..) |
-        ExprKind::IfLet(..) |
-        ExprKind::While(..) |
-        ExprKind::WhileLet(..) |
-        ExprKind::ForLoop(..) |
-        ExprKind::Loop(..) |
-        ExprKind::Match(..) |
-        ExprKind::Block(..) |
-        ExprKind::Catch(..) |
-        ExprKind::Struct(..) => PREC_PAREN,
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ExprPrecedence {
+    Closure,
+    Break,
+    Continue,
+    Ret,
+    Yield,
+
+    Range,
+
+    Binary(BinOpKind),
+
+    InPlace,
+    Cast,
+    Type,
+
+    Assign,
+    AssignOp,
+
+    Box,
+    AddrOf,
+    Unary,
+
+    Call,
+    MethodCall,
+    Field,
+    TupField,
+    Index,
+    Try,
+    InlineAsm,
+    Mac,
+
+    Array,
+    Repeat,
+    Tup,
+    Lit,
+    Path,
+    Paren,
+    If,
+    IfLet,
+    While,
+    WhileLet,
+    ForLoop,
+    Loop,
+    Match,
+    Block,
+    Catch,
+    Struct,
+}
+
+impl PartialOrd for ExprPrecedence {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.order().cmp(&other.order()))
+    }
+}
+
+impl Ord for ExprPrecedence {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.order().cmp(&other.order())
     }
 }
 
+impl ExprPrecedence {
+    pub fn order(self) -> i8 {
+        match self {
+            ExprPrecedence::Closure => PREC_CLOSURE,
+
+            ExprPrecedence::Break |
+            ExprPrecedence::Continue |
+            ExprPrecedence::Ret |
+            ExprPrecedence::Yield => PREC_JUMP,
+
+            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
+            // parse, instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence
+            // ensures that `pprust` will add parentheses in the right places to get the desired
+            // parse.
+            ExprPrecedence::Range => PREC_RANGE,
+
+            // Binop-like expr kinds, handled by `AssocOp`.
+            ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
+            ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8,
+            ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
+            ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
+
+            ExprPrecedence::Assign |
+            ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
+
+            // Unary, prefix
+            ExprPrecedence::Box |
+            ExprPrecedence::AddrOf |
+            ExprPrecedence::Unary => PREC_PREFIX,
+
+            // Unary, postfix
+            ExprPrecedence::Call |
+            ExprPrecedence::MethodCall |
+            ExprPrecedence::Field |
+            ExprPrecedence::TupField |
+            ExprPrecedence::Index |
+            ExprPrecedence::Try |
+            ExprPrecedence::InlineAsm |
+            ExprPrecedence::Mac => PREC_POSTFIX,
+
+            // Never need parens
+            ExprPrecedence::Array |
+            ExprPrecedence::Repeat |
+            ExprPrecedence::Tup |
+            ExprPrecedence::Lit |
+            ExprPrecedence::Path |
+            ExprPrecedence::Paren |
+            ExprPrecedence::If |
+            ExprPrecedence::IfLet |
+            ExprPrecedence::While |
+            ExprPrecedence::WhileLet |
+            ExprPrecedence::ForLoop |
+            ExprPrecedence::Loop |
+            ExprPrecedence::Match |
+            ExprPrecedence::Block |
+            ExprPrecedence::Catch |
+            ExprPrecedence::Struct => PREC_PAREN,
+        }
+    }
+}
+
+
 /// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
 /// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
diff --git a/src/test/compile-fail/E0659.rs b/src/test/compile-fail/E0659.rs
new file mode 100644
index 00000000000..4bd452b0aac
--- /dev/null
+++ b/src/test/compile-fail/E0659.rs
@@ -0,0 +1,26 @@
+// 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.
+
+mod moon {
+    pub fn foo() {}
+}
+
+mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); //~ ERROR E0659
+}
diff --git a/src/test/ui/imports/duplicate.stderr b/src/test/ui/imports/duplicate.stderr
index 30f2f517115..a74401314a1 100644
--- a/src/test/ui/imports/duplicate.stderr
+++ b/src/test/ui/imports/duplicate.stderr
@@ -12,7 +12,7 @@ help: You can use `as` to change the binding name of the import
 25 |     use a::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times
    |         ^^^^^^^^^^^^^^^^^^
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:56:9
    |
 56 |     use self::foo::bar; //~ ERROR `foo` is ambiguous
@@ -30,7 +30,7 @@ note: `foo` could also refer to the name imported here
    |         ^^^^^^^^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:45:5
    |
 45 |     f::foo(); //~ ERROR `foo` is ambiguous
@@ -48,7 +48,7 @@ note: `foo` could also refer to the name imported here
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:46:5
    |
 46 |     g::foo(); //~ ERROR `foo` is ambiguous
@@ -66,7 +66,7 @@ note: `foo` could also refer to the name imported here
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:59:9
    |
 59 |         foo::bar(); //~ ERROR `foo` is ambiguous
diff --git a/src/test/ui/imports/macro-paths.stderr b/src/test/ui/imports/macro-paths.stderr
index 91b0b9756da..32d78666004 100644
--- a/src/test/ui/imports/macro-paths.stderr
+++ b/src/test/ui/imports/macro-paths.stderr
@@ -1,4 +1,4 @@
-error: `bar` is ambiguous
+error[E0659]: `bar` is ambiguous
   --> $DIR/macro-paths.rs:25:5
    |
 25 |     bar::m! { //~ ERROR ambiguous
@@ -16,7 +16,7 @@ note: `bar` could also refer to the name imported here
    |         ^^^^^^
    = note: macro-expanded items do not shadow when used in a macro invocation path
 
-error: `baz` is ambiguous
+error[E0659]: `baz` is ambiguous
   --> $DIR/macro-paths.rs:35:5
    |
 35 |     baz::m! { //~ ERROR ambiguous
diff --git a/src/test/ui/imports/macros.stderr b/src/test/ui/imports/macros.stderr
index 0b67613eb14..75294f7bf12 100644
--- a/src/test/ui/imports/macros.stderr
+++ b/src/test/ui/imports/macros.stderr
@@ -15,7 +15,7 @@ note: `m` could also refer to the macro imported here
 49 |     use two_macros::m;
    |         ^^^^^^^^^^^^^
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:28:5
    |
 28 |     m! { //~ ERROR ambiguous
@@ -33,7 +33,7 @@ note: `m` could also refer to the name imported here
    |         ^^^^^^^^^^^^^
    = note: macro-expanded macro imports do not shadow
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:41:9
    |
 41 |         m! { //~ ERROR ambiguous
diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr
index 853ed98c30d..8f4325fa12c 100644
--- a/src/test/ui/imports/shadow_builtin_macros.stderr
+++ b/src/test/ui/imports/shadow_builtin_macros.stderr
@@ -9,7 +9,7 @@ error: `panic` is already in scope
    |
    = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:27:14
    |
 27 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -23,7 +23,7 @@ note: `panic` could refer to the name imported here
    = note: `panic` is also a builtin macro
    = note: consider adding an explicit import of `panic` to disambiguate
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:32:14
    |
 32 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -37,7 +37,7 @@ note: `panic` could refer to the name imported here
    = note: `panic` is also a builtin macro
    = note: macro-expanded macro imports do not shadow
 
-error: `n` is ambiguous
+error[E0659]: `n` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:61:5
    |
 61 |     n!(); //~ ERROR ambiguous
diff --git a/src/test/ui/issue-47623.rs b/src/test/ui/issue-47623.rs
new file mode 100644
index 00000000000..0c886fdb52f
--- /dev/null
+++ b/src/test/ui/issue-47623.rs
@@ -0,0 +1,13 @@
+// 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.
+
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/issue-47623.stderr b/src/test/ui/issue-47623.stderr
new file mode 100644
index 00000000000..c5a42d4d846
--- /dev/null
+++ b/src/test/ui/issue-47623.stderr
@@ -0,0 +1,8 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/issue-47623.rs:11:5
+   |
+11 | use self; //~ERROR `self` imports are only allowed within a { } list
+   |     ^^^^
+
+error: aborting due to previous error
+
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..2092b6bce37
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast-2.rs
@@ -0,0 +1,21 @@
+// 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: u16 = foo();
+    //~^ ERROR mismatched types
+    let y: i64 = x + x;
+    //~^ ERROR mismatched types
+    let z: i32 = x + x;
+    //~^ ERROR mismatched types
+}
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..90086d247d6
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast-2.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:15:18
+   |
+15 |     let x: u16 = foo();
+   |                  ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:17:18
+   |
+17 |     let y: i64 = x + x;
+   |                  ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:19:18
+   |
+19 |     let z: i32 = x + x;
+   |                  ^^^^^ expected i32, found u16
+
+error: aborting due to 3 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..6e144037ec2
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.rs
@@ -0,0 +1,315 @@
+// 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
+    foo::<usize>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<isize>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<u64>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<i64>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<u32>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<i32>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<u16>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<i16>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<u8>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    foo::<i8>(x_f32);
+    //~^ ERROR mismatched types
+
+    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
+    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..0ce3d087f35
--- /dev/null
+++ b/src/test/ui/suggestions/numeric-cast.stderr
@@ -0,0 +1,886 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:29:18
+   |
+29 |     foo::<usize>(x_u64);
+   |                  ^^^^^ expected usize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:31:18
+   |
+31 |     foo::<usize>(x_u32);
+   |                  ^^^^^ expected usize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:33:18
+   |
+33 |     foo::<usize>(x_u16);
+   |                  ^^^^^ expected usize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:35:18
+   |
+35 |     foo::<usize>(x_u8);
+   |                  ^^^^ expected usize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:37:18
+   |
+37 |     foo::<usize>(x_isize);
+   |                  ^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:39:18
+   |
+39 |     foo::<usize>(x_i64);
+   |                  ^^^^^ expected usize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:41:18
+   |
+41 |     foo::<usize>(x_i32);
+   |                  ^^^^^ expected usize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:43:18
+   |
+43 |     foo::<usize>(x_i16);
+   |                  ^^^^^ expected usize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:45:18
+   |
+45 |     foo::<usize>(x_i8);
+   |                  ^^^^ expected usize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:47:18
+   |
+47 |     foo::<usize>(x_f64);
+   |                  ^^^^^ expected usize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:49:18
+   |
+49 |     foo::<usize>(x_f32);
+   |                  ^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:52:18
+   |
+52 |     foo::<isize>(x_usize);
+   |                  ^^^^^^^ expected isize, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:54:18
+   |
+54 |     foo::<isize>(x_u64);
+   |                  ^^^^^ expected isize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:56:18
+   |
+56 |     foo::<isize>(x_u32);
+   |                  ^^^^^ expected isize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:58:18
+   |
+58 |     foo::<isize>(x_u16);
+   |                  ^^^^^ expected isize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:60:18
+   |
+60 |     foo::<isize>(x_u8);
+   |                  ^^^^ expected isize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:63:18
+   |
+63 |     foo::<isize>(x_i64);
+   |                  ^^^^^ expected isize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:65:18
+   |
+65 |     foo::<isize>(x_i32);
+   |                  ^^^^^ expected isize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:67:18
+   |
+67 |     foo::<isize>(x_i16);
+   |                  ^^^^^ expected isize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:69:18
+   |
+69 |     foo::<isize>(x_i8);
+   |                  ^^^^ expected isize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:71:18
+   |
+71 |     foo::<isize>(x_f64);
+   |                  ^^^^^ expected isize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:73:18
+   |
+73 |     foo::<isize>(x_f32);
+   |                  ^^^^^ expected isize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:76:16
+   |
+76 |     foo::<u64>(x_usize);
+   |                ^^^^^^^ expected u64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:79:16
+   |
+79 |     foo::<u64>(x_u32);
+   |                ^^^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+79 |     foo::<u64>(x_u32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:81:16
+   |
+81 |     foo::<u64>(x_u16);
+   |                ^^^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+81 |     foo::<u64>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:83:16
+   |
+83 |     foo::<u64>(x_u8);
+   |                ^^^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+83 |     foo::<u64>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:85:16
+   |
+85 |     foo::<u64>(x_isize);
+   |                ^^^^^^^ expected u64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:87:16
+   |
+87 |     foo::<u64>(x_i64);
+   |                ^^^^^ expected u64, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:89:16
+   |
+89 |     foo::<u64>(x_i32);
+   |                ^^^^^ expected u64, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:91:16
+   |
+91 |     foo::<u64>(x_i16);
+   |                ^^^^^ expected u64, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:93:16
+   |
+93 |     foo::<u64>(x_i8);
+   |                ^^^^ expected u64, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:95:16
+   |
+95 |     foo::<u64>(x_f64);
+   |                ^^^^^ expected u64, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:97:16
+   |
+97 |     foo::<u64>(x_f32);
+   |                ^^^^^ expected u64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:100:16
+    |
+100 |     foo::<i64>(x_usize);
+    |                ^^^^^^^ expected i64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:102:16
+    |
+102 |     foo::<i64>(x_u64);
+    |                ^^^^^ expected i64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:104:16
+    |
+104 |     foo::<i64>(x_u32);
+    |                ^^^^^ expected i64, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:106:16
+    |
+106 |     foo::<i64>(x_u16);
+    |                ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:108:16
+    |
+108 |     foo::<i64>(x_u8);
+    |                ^^^^ expected i64, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:110:16
+    |
+110 |     foo::<i64>(x_isize);
+    |                ^^^^^^^ expected i64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:113:16
+    |
+113 |     foo::<i64>(x_i32);
+    |                ^^^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+    |
+113 |     foo::<i64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:115:16
+    |
+115 |     foo::<i64>(x_i16);
+    |                ^^^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+    |
+115 |     foo::<i64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:117:16
+    |
+117 |     foo::<i64>(x_i8);
+    |                ^^^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+    |
+117 |     foo::<i64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:119:16
+    |
+119 |     foo::<i64>(x_f64);
+    |                ^^^^^ expected i64, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:121:16
+    |
+121 |     foo::<i64>(x_f32);
+    |                ^^^^^ expected i64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:124:16
+    |
+124 |     foo::<u32>(x_usize);
+    |                ^^^^^^^ expected u32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:126:16
+    |
+126 |     foo::<u32>(x_u64);
+    |                ^^^^^ expected u32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:129:16
+    |
+129 |     foo::<u32>(x_u16);
+    |                ^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+    |
+129 |     foo::<u32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:131:16
+    |
+131 |     foo::<u32>(x_u8);
+    |                ^^^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+    |
+131 |     foo::<u32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:133:16
+    |
+133 |     foo::<u32>(x_isize);
+    |                ^^^^^^^ expected u32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:135:16
+    |
+135 |     foo::<u32>(x_i64);
+    |                ^^^^^ expected u32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:137:16
+    |
+137 |     foo::<u32>(x_i32);
+    |                ^^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:139:16
+    |
+139 |     foo::<u32>(x_i16);
+    |                ^^^^^ expected u32, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:141:16
+    |
+141 |     foo::<u32>(x_i8);
+    |                ^^^^ expected u32, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:143:16
+    |
+143 |     foo::<u32>(x_f64);
+    |                ^^^^^ expected u32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:145:16
+    |
+145 |     foo::<u32>(x_f32);
+    |                ^^^^^ expected u32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:148:16
+    |
+148 |     foo::<i32>(x_usize);
+    |                ^^^^^^^ expected i32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:150:16
+    |
+150 |     foo::<i32>(x_u64);
+    |                ^^^^^ expected i32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:152:16
+    |
+152 |     foo::<i32>(x_u32);
+    |                ^^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:154:16
+    |
+154 |     foo::<i32>(x_u16);
+    |                ^^^^^ expected i32, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:156:16
+    |
+156 |     foo::<i32>(x_u8);
+    |                ^^^^ expected i32, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:158:16
+    |
+158 |     foo::<i32>(x_isize);
+    |                ^^^^^^^ expected i32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:160:16
+    |
+160 |     foo::<i32>(x_i64);
+    |                ^^^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:163:16
+    |
+163 |     foo::<i32>(x_i16);
+    |                ^^^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+    |
+163 |     foo::<i32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:165:16
+    |
+165 |     foo::<i32>(x_i8);
+    |                ^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+    |
+165 |     foo::<i32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:167:16
+    |
+167 |     foo::<i32>(x_f64);
+    |                ^^^^^ expected i32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:169:16
+    |
+169 |     foo::<i32>(x_f32);
+    |                ^^^^^ expected i32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:172:16
+    |
+172 |     foo::<u16>(x_usize);
+    |                ^^^^^^^ expected u16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:174:16
+    |
+174 |     foo::<u16>(x_u64);
+    |                ^^^^^ expected u16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:176:16
+    |
+176 |     foo::<u16>(x_u32);
+    |                ^^^^^ expected u16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:179:16
+    |
+179 |     foo::<u16>(x_u8);
+    |                ^^^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+    |
+179 |     foo::<u16>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:181:16
+    |
+181 |     foo::<u16>(x_isize);
+    |                ^^^^^^^ expected u16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:183:16
+    |
+183 |     foo::<u16>(x_i64);
+    |                ^^^^^ expected u16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:185:16
+    |
+185 |     foo::<u16>(x_i32);
+    |                ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:187:16
+    |
+187 |     foo::<u16>(x_i16);
+    |                ^^^^^ expected u16, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:189:16
+    |
+189 |     foo::<u16>(x_i8);
+    |                ^^^^ expected u16, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:191:16
+    |
+191 |     foo::<u16>(x_f64);
+    |                ^^^^^ expected u16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:193:16
+    |
+193 |     foo::<u16>(x_f32);
+    |                ^^^^^ expected u16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:196:16
+    |
+196 |     foo::<i16>(x_usize);
+    |                ^^^^^^^ expected i16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:198:16
+    |
+198 |     foo::<i16>(x_u64);
+    |                ^^^^^ expected i16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:200:16
+    |
+200 |     foo::<i16>(x_u32);
+    |                ^^^^^ expected i16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:202:16
+    |
+202 |     foo::<i16>(x_u16);
+    |                ^^^^^ expected i16, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:204:16
+    |
+204 |     foo::<i16>(x_u8);
+    |                ^^^^ expected i16, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:206:16
+    |
+206 |     foo::<i16>(x_isize);
+    |                ^^^^^^^ expected i16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:208:16
+    |
+208 |     foo::<i16>(x_i64);
+    |                ^^^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:210:16
+    |
+210 |     foo::<i16>(x_i32);
+    |                ^^^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:213:16
+    |
+213 |     foo::<i16>(x_i8);
+    |                ^^^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+    |
+213 |     foo::<i16>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:215:16
+    |
+215 |     foo::<i16>(x_f64);
+    |                ^^^^^ expected i16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:217:16
+    |
+217 |     foo::<i16>(x_f32);
+    |                ^^^^^ expected i16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:220:15
+    |
+220 |     foo::<u8>(x_usize);
+    |               ^^^^^^^ expected u8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:222:15
+    |
+222 |     foo::<u8>(x_u64);
+    |               ^^^^^ expected u8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:224:15
+    |
+224 |     foo::<u8>(x_u32);
+    |               ^^^^^ expected u8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:226:15
+    |
+226 |     foo::<u8>(x_u16);
+    |               ^^^^^ expected u8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:229:15
+    |
+229 |     foo::<u8>(x_isize);
+    |               ^^^^^^^ expected u8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:231:15
+    |
+231 |     foo::<u8>(x_i64);
+    |               ^^^^^ expected u8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:233:15
+    |
+233 |     foo::<u8>(x_i32);
+    |               ^^^^^ expected u8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:235:15
+    |
+235 |     foo::<u8>(x_i16);
+    |               ^^^^^ expected u8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:237:15
+    |
+237 |     foo::<u8>(x_i8);
+    |               ^^^^ expected u8, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:239:15
+    |
+239 |     foo::<u8>(x_f64);
+    |               ^^^^^ expected u8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:241:15
+    |
+241 |     foo::<u8>(x_f32);
+    |               ^^^^^ expected u8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:244:15
+    |
+244 |     foo::<i8>(x_usize);
+    |               ^^^^^^^ expected i8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:246:15
+    |
+246 |     foo::<i8>(x_u64);
+    |               ^^^^^ expected i8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:248:15
+    |
+248 |     foo::<i8>(x_u32);
+    |               ^^^^^ expected i8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:250:15
+    |
+250 |     foo::<i8>(x_u16);
+    |               ^^^^^ expected i8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:252:15
+    |
+252 |     foo::<i8>(x_u8);
+    |               ^^^^ expected i8, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:254:15
+    |
+254 |     foo::<i8>(x_isize);
+    |               ^^^^^^^ expected i8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:256:15
+    |
+256 |     foo::<i8>(x_i64);
+    |               ^^^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:258:15
+    |
+258 |     foo::<i8>(x_i32);
+    |               ^^^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:260:15
+    |
+260 |     foo::<i8>(x_i16);
+    |               ^^^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:263:15
+    |
+263 |     foo::<i8>(x_f64);
+    |               ^^^^^ expected i8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:265:15
+    |
+265 |     foo::<i8>(x_f32);
+    |               ^^^^^ expected i8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:268:16
+    |
+268 |     foo::<f64>(x_usize);
+    |                ^^^^^^^ expected f64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:270:16
+    |
+270 |     foo::<f64>(x_u64);
+    |                ^^^^^ expected f64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:272:16
+    |
+272 |     foo::<f64>(x_u32);
+    |                ^^^^^ expected f64, found u32
+help: you can cast an `u32` to `f64`, producing the floating point representation of the integer
+    |
+272 |     foo::<f64>(x_u32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:274:16
+    |
+274 |     foo::<f64>(x_u16);
+    |                ^^^^^ expected f64, found u16
+help: you can cast an `u16` to `f64`, producing the floating point representation of the integer
+    |
+274 |     foo::<f64>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:276:16
+    |
+276 |     foo::<f64>(x_u8);
+    |                ^^^^ expected f64, found u8
+help: you can cast an `u8` to `f64`, producing the floating point representation of the integer
+    |
+276 |     foo::<f64>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:278:16
+    |
+278 |     foo::<f64>(x_isize);
+    |                ^^^^^^^ expected f64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:280:16
+    |
+280 |     foo::<f64>(x_i64);
+    |                ^^^^^ expected f64, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:282:16
+    |
+282 |     foo::<f64>(x_i32);
+    |                ^^^^^ expected f64, found i32
+help: you can cast an `i32` to `f64`, producing the floating point representation of the integer
+    |
+282 |     foo::<f64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:284:16
+    |
+284 |     foo::<f64>(x_i16);
+    |                ^^^^^ expected f64, found i16
+help: you can cast an `i16` to `f64`, producing the floating point representation of the integer
+    |
+284 |     foo::<f64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:286:16
+    |
+286 |     foo::<f64>(x_i8);
+    |                ^^^^ expected f64, found i8
+help: you can cast an `i8` to `f64`, producing the floating point representation of the integer
+    |
+286 |     foo::<f64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:289:16
+    |
+289 |     foo::<f64>(x_f32);
+    |                ^^^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+    |
+289 |     foo::<f64>(x_f32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:292:16
+    |
+292 |     foo::<f32>(x_usize);
+    |                ^^^^^^^ expected f32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:294:16
+    |
+294 |     foo::<f32>(x_u64);
+    |                ^^^^^ expected f32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:296:16
+    |
+296 |     foo::<f32>(x_u32);
+    |                ^^^^^ expected f32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:298:16
+    |
+298 |     foo::<f32>(x_u16);
+    |                ^^^^^ expected f32, found u16
+help: you can cast an `u16` to `f32`, producing the floating point representation of the integer
+    |
+298 |     foo::<f32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:300:16
+    |
+300 |     foo::<f32>(x_u8);
+    |                ^^^^ expected f32, found u8
+help: you can cast an `u8` to `f32`, producing the floating point representation of the integer
+    |
+300 |     foo::<f32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:302:16
+    |
+302 |     foo::<f32>(x_isize);
+    |                ^^^^^^^ expected f32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:304:16
+    |
+304 |     foo::<f32>(x_i64);
+    |                ^^^^^ expected f32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:306:16
+    |
+306 |     foo::<f32>(x_i32);
+    |                ^^^^^ expected f32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:308:16
+    |
+308 |     foo::<f32>(x_i16);
+    |                ^^^^^ expected f32, found i16
+help: you can cast an `i16` to `f32`, producing the floating point representation of the integer
+    |
+308 |     foo::<f32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:310:16
+    |
+310 |     foo::<f32>(x_i8);
+    |                ^^^^ expected f32, found i8
+help: you can cast an `i8` to `f32`, producing the floating point representation of the integer
+    |
+310 |     foo::<f32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:312:16
+    |
+312 |     foo::<f32>(x_f64);
+    |                ^^^^^ expected f32, found f64
+
+error: aborting due to 132 previous errors
+