about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-24 01:24:13 +0000
committerbors <bors@rust-lang.org>2019-01-24 01:24:13 +0000
commitcd3d580d59e8af62fb8fc25b996900dd5ccd5ad9 (patch)
treebdd151640dbbe35520823f2a649f56b24d8336e2
parent19f8958f827e379be9b0ffc93fca580ec8ffac77 (diff)
parente90cdfd50768feb612dcea84ea25a725c72df39a (diff)
downloadrust-cd3d580d59e8af62fb8fc25b996900dd5ccd5ad9.tar.gz
rust-cd3d580d59e8af62fb8fc25b996900dd5ccd5ad9.zip
Auto merge of #57869 - Centril:rollup, r=Centril
Rollup of 11 pull requests

Successful merges:

 - #57179 (Update std/lib.rs docs to reflect Rust 2018 usage)
 - #57730 (Merge visitors in AST validation)
 - #57779 (Recover from parse errors in literal struct fields and incorrect float literals)
 - #57793 (Explain type mismatch cause pointing to return type when it is `impl Trait`)
 - #57795 (Use structured suggestion in stead of notes)
 - #57817 (Add error for trailing angle brackets.)
 - #57834 (Stabilize Any::get_type_id and rename to type_id)
 - #57836 (Fix some cross crate existential type ICEs)
 - #57840 (Fix issue 57762)
 - #57844 (use port 80 for retrieving GPG key)
 - #57858 (Ignore line ending on older git versions)

Failed merges:

r? @ghost
-rw-r--r--.gitattributes4
-rwxr-xr-xsrc/ci/docker/dist-various-1/install-x86_64-redox.sh2
-rw-r--r--src/libcore/any.rs16
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs5
-rw-r--r--src/librustc_metadata/decoder.rs3
-rw-r--r--src/librustc_passes/ast_validation.rs250
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs1
-rw-r--r--src/librustc_typeck/check/coercion.rs117
-rw-r--r--src/librustc_typeck/check/method/suggest.rs14
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/libstd/lib.rs8
-rw-r--r--src/libsyntax/ast.rs14
-rw-r--r--src/libsyntax/parse/parser.rs241
-rw-r--r--src/test/ui/auto-ref-slice-plus-ref.stderr3
-rw-r--r--src/test/ui/block-result/issue-3563.stderr4
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr10
-rw-r--r--src/test/ui/existential_types/auxiliary/cross_crate_ice.rs12
-rw-r--r--src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs21
-rw-r--r--src/test/ui/existential_types/cross_crate_ice.rs16
-rw-r--r--src/test/ui/existential_types/cross_crate_ice2.rs11
-rw-r--r--src/test/ui/impl-trait/equality.stderr5
-rw-r--r--src/test/ui/issues/issue-23217.stderr5
-rw-r--r--src/test/ui/issues/issue-28344.stderr6
-rw-r--r--src/test/ui/issues/issue-28971.stderr7
-rw-r--r--src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr3
-rw-r--r--src/test/ui/issues/issue-52496.rs12
-rw-r--r--src/test/ui/issues/issue-52496.stderr37
-rw-r--r--src/test/ui/issues/issue-54521-1.rs16
-rw-r--r--src/test/ui/issues/issue-54521-2.fixed22
-rw-r--r--src/test/ui/issues/issue-54521-2.rs22
-rw-r--r--src/test/ui/issues/issue-54521-2.stderr26
-rw-r--r--src/test/ui/issues/issue-54521.fixed22
-rw-r--r--src/test/ui/issues/issue-54521.rs22
-rw-r--r--src/test/ui/issues/issue-54521.stderr26
-rw-r--r--src/test/ui/parser/issue-17718-const-mut.rs2
-rw-r--r--src/test/ui/parser/issue-17718-const-mut.stderr6
-rw-r--r--src/test/ui/parser/removed-syntax-with-1.rs3
-rw-r--r--src/test/ui/parser/removed-syntax-with-1.stderr15
-rw-r--r--src/test/ui/parser/removed-syntax-with-2.rs3
-rw-r--r--src/test/ui/parser/removed-syntax-with-2.stderr23
-rw-r--r--src/test/ui/parser/struct-field-numeric-shorthand.rs7
-rw-r--r--src/test/ui/parser/struct-field-numeric-shorthand.stderr22
-rw-r--r--src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr14
-rw-r--r--src/test/ui/suggestions/recover-invalid-float.rs11
-rw-r--r--src/test/ui/suggestions/recover-invalid-float.stderr42
-rw-r--r--src/test/ui/suggestions/suggest-methods.stderr12
-rw-r--r--src/test/ui/traits/trait-privacy.rs3
47 files changed, 840 insertions, 310 deletions
diff --git a/.gitattributes b/.gitattributes
index b223c8ac5fb..f0b1c67bd0f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9,3 +9,7 @@ src/etc/installer/gfx/* binary
 *.woff binary
 src/vendor/** -text
 Cargo.lock -merge linguist-generated=false
+
+# Older git versions try to fix line endings on images, this prevents it.
+*.png binary
+*.ico binary
diff --git a/src/ci/docker/dist-various-1/install-x86_64-redox.sh b/src/ci/docker/dist-various-1/install-x86_64-redox.sh
index 29222ff60f2..c39be14941c 100755
--- a/src/ci/docker/dist-various-1/install-x86_64-redox.sh
+++ b/src/ci/docker/dist-various-1/install-x86_64-redox.sh
@@ -6,7 +6,7 @@ set -ex
 apt-get update
 apt-get install -y --no-install-recommends software-properties-common apt-transport-https
 
-apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F
+apt-key adv --batch --yes --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys AA12E97F0881517F
 add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /'
 
 apt-get update
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 6a863ff369a..2afd9e0c072 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -81,12 +81,10 @@ pub trait Any: 'static {
     /// # Examples
     ///
     /// ```
-    /// #![feature(get_type_id)]
-    ///
     /// use std::any::{Any, TypeId};
     ///
     /// fn is_string(s: &dyn Any) -> bool {
-    ///     TypeId::of::<String>() == s.get_type_id()
+    ///     TypeId::of::<String>() == s.type_id()
     /// }
     ///
     /// fn main() {
@@ -94,15 +92,13 @@ pub trait Any: 'static {
     ///     assert_eq!(is_string(&"cookie monster".to_string()), true);
     /// }
     /// ```
-    #[unstable(feature = "get_type_id",
-               reason = "this method will likely be replaced by an associated static",
-               issue = "27745")]
-    fn get_type_id(&self) -> TypeId;
+    #[stable(feature = "get_type_id", since = "1.34.0")]
+    fn type_id(&self) -> TypeId;
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: 'static + ?Sized > Any for T {
-    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
+    fn type_id(&self) -> TypeId { TypeId::of::<T>() }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -161,10 +157,10 @@ impl dyn Any {
         let t = TypeId::of::<T>();
 
         // Get TypeId of the type in the trait object
-        let boxed = self.get_type_id();
+        let concrete = self.type_id();
 
         // Compare both TypeIds on equality
-        t == boxed
+        t == concrete
     }
 
     /// Returns some reference to the boxed value if it is of type `T`, or
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 6deedd0b5ea..9f63038c362 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -1164,7 +1164,10 @@ fn use_enum_fallback(cx: &CodegenCx) -> bool {
     // On MSVC we have to use the fallback mode, because LLVM doesn't
     // lower variant parts to PDB.
     return cx.sess().target.target.options.is_like_msvc
-        || llvm_util::get_major_version() < 7;
+        // LLVM version 7 did not release with an important bug fix;
+        // but the required patch is in the LLVM 8.  Rust LLVM reports
+        // 8 as well.
+        || llvm_util::get_major_version() < 8;
 }
 
 // Describes the members of an enum value: An enum is described as a union of
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 1f07e8f478b..ad6296e1a3b 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -893,6 +893,9 @@ impl<'a, 'tcx> CrateMetadata {
             EntryKind::AssociatedType(container) => {
                 (ty::AssociatedKind::Type, container, false)
             }
+            EntryKind::AssociatedExistential(container) => {
+                (ty::AssociatedKind::Existential, container, false)
+            }
             _ => bug!("cannot get associated-item of `{:?}`", def_key)
         };
 
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 3d0e46d9986..d1a3d7c1f81 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -6,6 +6,7 @@
 // This pass is supposed to perform only simple checks not requiring name resolution
 // or type checking or some other kind of complex analysis.
 
+use std::mem;
 use rustc::lint;
 use rustc::session::Session;
 use syntax::ast::*;
@@ -20,9 +21,73 @@ use errors::Applicability;
 
 struct AstValidator<'a> {
     session: &'a Session,
+
+    // Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
+    // Nested `impl Trait` _is_ allowed in associated type position,
+    // e.g `impl Iterator<Item=impl Debug>`
+    outer_impl_trait: Option<Span>,
+
+    // Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
+    // or `Foo::Bar<impl Trait>`
+    is_impl_trait_banned: bool,
 }
 
 impl<'a> AstValidator<'a> {
+    fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.is_impl_trait_banned, true);
+        f(self);
+        self.is_impl_trait_banned = old;
+    }
+
+    fn with_impl_trait(&mut self, outer_impl_trait: Option<Span>, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.outer_impl_trait, outer_impl_trait);
+        f(self);
+        self.outer_impl_trait = old;
+    }
+
+    // Mirrors visit::walk_ty, but tracks relevant state
+    fn walk_ty(&mut self, t: &'a Ty) {
+        match t.node {
+            TyKind::ImplTrait(..) => {
+                self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
+            }
+            TyKind::Path(ref qself, ref path) => {
+                // We allow these:
+                //  - `Option<impl Trait>`
+                //  - `option::Option<impl Trait>`
+                //  - `option::Option<T>::Foo<impl Trait>
+                //
+                // But not these:
+                //  - `<impl Trait>::Foo`
+                //  - `option::Option<impl Trait>::Foo`.
+                //
+                // To implement this, we disallow `impl Trait` from `qself`
+                // (for cases like `<impl Trait>::Foo>`)
+                // but we allow `impl Trait` in `GenericArgs`
+                // iff there are no more PathSegments.
+                if let Some(ref qself) = *qself {
+                    // `impl Trait` in `qself` is always illegal
+                    self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
+                }
+
+                // Note that there should be a call to visit_path here,
+                // so if any logic is added to process `Path`s a call to it should be
+                // added both in visit_path and here. This code mirrors visit::walk_path.
+                for (i, segment) in path.segments.iter().enumerate() {
+                    // Allow `impl Trait` iff we're on the final path segment
+                    if i == path.segments.len() - 1 {
+                        self.visit_path_segment(path.span, segment);
+                    } else {
+                        self.with_banned_impl_trait(|this| {
+                            this.visit_path_segment(path.span, segment)
+                        });
+                    }
+                }
+            }
+            _ => visit::walk_ty(self, t),
+        }
+    }
+
     fn err_handler(&self) -> &errors::Handler {
         &self.session.diagnostic()
     }
@@ -267,6 +332,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.no_questions_in_bounds(bounds, "trait object types", false);
             }
             TyKind::ImplTrait(_, ref bounds) => {
+                if self.is_impl_trait_banned {
+                    struct_span_err!(self.session, ty.span, E0667,
+                        "`impl Trait` is not allowed in path parameters").emit();
+                }
+
+                if let Some(outer_impl_trait) = self.outer_impl_trait {
+                    struct_span_err!(self.session, ty.span, E0666,
+                                    "nested `impl Trait` is not allowed")
+                        .span_label(outer_impl_trait, "outer `impl Trait`")
+                        .span_label(ty.span, "nested `impl Trait` here")
+                        .emit();
+
+                }
                 if !bounds.iter()
                           .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
@@ -275,7 +353,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             _ => {}
         }
 
-        visit::walk_ty(self, ty)
+        self.walk_ty(ty)
     }
 
     fn visit_label(&mut self, label: &'a Label) {
@@ -414,6 +492,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         visit::walk_foreign_item(self, fi)
     }
 
+    // Mirrors visit::walk_generic_args, but tracks relevant state
+    fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
+        match *generic_args {
+            GenericArgs::AngleBracketed(ref data) => {
+                walk_list!(self, visit_generic_arg, &data.args);
+                // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
+                // are allowed to contain nested `impl Trait`.
+                self.with_impl_trait(None, |this| {
+                    walk_list!(this, visit_assoc_type_binding, &data.bindings);
+                });
+            }
+            GenericArgs::Parenthesized(ref data) => {
+                walk_list!(self, visit_ty, &data.inputs);
+                if let Some(ref type_) = data.output {
+                    // `-> Foo` syntax is essentially an associated type binding,
+                    // so it is also allowed to contain nested `impl Trait`.
+                    self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
+                }
+            }
+        }
+    }
+
     fn visit_generics(&mut self, generics: &'a Generics) {
         let mut seen_non_lifetime_param = false;
         let mut seen_default = None;
@@ -490,148 +590,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 }
 
-// Bans nested `impl Trait`, e.g., `impl Into<impl Debug>`.
-// Nested `impl Trait` _is_ allowed in associated type position,
-// e.g `impl Iterator<Item=impl Debug>`
-struct NestedImplTraitVisitor<'a> {
-    session: &'a Session,
-    outer_impl_trait: Option<Span>,
-}
-
-impl<'a> NestedImplTraitVisitor<'a> {
-    fn with_impl_trait<F>(&mut self, outer_impl_trait: Option<Span>, f: F)
-        where F: FnOnce(&mut NestedImplTraitVisitor<'a>)
-    {
-        let old_outer_impl_trait = self.outer_impl_trait;
-        self.outer_impl_trait = outer_impl_trait;
-        f(self);
-        self.outer_impl_trait = old_outer_impl_trait;
-    }
-}
-
-
-impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> {
-    fn visit_ty(&mut self, t: &'a Ty) {
-        if let TyKind::ImplTrait(..) = t.node {
-            if let Some(outer_impl_trait) = self.outer_impl_trait {
-                struct_span_err!(self.session, t.span, E0666,
-                                 "nested `impl Trait` is not allowed")
-                    .span_label(outer_impl_trait, "outer `impl Trait`")
-                    .span_label(t.span, "nested `impl Trait` here")
-                    .emit();
-
-            }
-            self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t));
-        } else {
-            visit::walk_ty(self, t);
-        }
-    }
-    fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
-        match *generic_args {
-            GenericArgs::AngleBracketed(ref data) => {
-                for arg in &data.args {
-                    self.visit_generic_arg(arg)
-                }
-                for type_binding in &data.bindings {
-                    // Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
-                    // are allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty));
-                }
-            }
-            GenericArgs::Parenthesized(ref data) => {
-                for type_ in &data.inputs {
-                    self.visit_ty(type_);
-                }
-                if let Some(ref type_) = data.output {
-                    // `-> Foo` syntax is essentially an associated type binding,
-                    // so it is also allowed to contain nested `impl Trait`.
-                    self.with_impl_trait(None, |this| visit::walk_ty(this, type_));
-                }
-            }
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
-        // covered in AstValidator
-    }
-}
-
-// Bans `impl Trait` in path projections like `<impl Iterator>::Item` or `Foo::Bar<impl Trait>`.
-struct ImplTraitProjectionVisitor<'a> {
-    session: &'a Session,
-    is_banned: bool,
-}
-
-impl<'a> ImplTraitProjectionVisitor<'a> {
-    fn with_ban<F>(&mut self, f: F)
-        where F: FnOnce(&mut ImplTraitProjectionVisitor<'a>)
-    {
-        let old_is_banned = self.is_banned;
-        self.is_banned = true;
-        f(self);
-        self.is_banned = old_is_banned;
-    }
-}
-
-impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> {
-    fn visit_ty(&mut self, t: &'a Ty) {
-        match t.node {
-            TyKind::ImplTrait(..) => {
-                if self.is_banned {
-                    struct_span_err!(self.session, t.span, E0667,
-                        "`impl Trait` is not allowed in path parameters").emit();
-                }
-            }
-            TyKind::Path(ref qself, ref path) => {
-                // We allow these:
-                //  - `Option<impl Trait>`
-                //  - `option::Option<impl Trait>`
-                //  - `option::Option<T>::Foo<impl Trait>
-                //
-                // But not these:
-                //  - `<impl Trait>::Foo`
-                //  - `option::Option<impl Trait>::Foo`.
-                //
-                // To implement this, we disallow `impl Trait` from `qself`
-                // (for cases like `<impl Trait>::Foo>`)
-                // but we allow `impl Trait` in `GenericArgs`
-                // iff there are no more PathSegments.
-                if let Some(ref qself) = *qself {
-                    // `impl Trait` in `qself` is always illegal
-                    self.with_ban(|this| this.visit_ty(&qself.ty));
-                }
-
-                for (i, segment) in path.segments.iter().enumerate() {
-                    // Allow `impl Trait` iff we're on the final path segment
-                    if i == path.segments.len() - 1 {
-                        visit::walk_path_segment(self, path.span, segment);
-                    } else {
-                        self.with_ban(|this|
-                            visit::walk_path_segment(this, path.span, segment));
-                    }
-                }
-            }
-            _ => visit::walk_ty(self, t),
-        }
-    }
-
-    fn visit_mac(&mut self, _mac: &Spanned<Mac_>) {
-        // covered in AstValidator
-    }
-}
-
 pub fn check_crate(session: &Session, krate: &Crate) {
-    visit::walk_crate(
-        &mut NestedImplTraitVisitor {
-            session,
-            outer_impl_trait: None,
-        }, krate);
-
-    visit::walk_crate(
-        &mut ImplTraitProjectionVisitor {
-            session,
-            is_banned: false,
-        }, krate);
-
-    visit::walk_crate(&mut AstValidator { session }, krate)
+    visit::walk_crate(&mut AstValidator {
+        session,
+        outer_impl_trait: None,
+        is_impl_trait_banned: false,
+    }, krate)
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 35616cc03a9..3db73800d64 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -680,6 +680,7 @@ impl<'a> Resolver<'a> {
                 }
                 module.populated.set(true);
             }
+            Def::Existential(..) |
             Def::TraitAlias(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index dd63b4f20fa..d1dfe9469fb 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1199,7 +1199,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
-                let reason_label = "expected because of this statement";
                 let mut db;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
@@ -1209,63 +1208,20 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                         db.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id) => {
-                        db = fcx.report_mismatched_types(cause, expected, found, err);
-
-                        let expr = expression.unwrap_or_else(|| {
-                            span_bug!(cause.span,
-                                      "supposed to be part of a block tail expression, but the \
-                                       expression is empty");
-                        });
-                        let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
-                            &mut db,
-                            expr,
+                        let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
+                        db = self.report_return_mismatched_types(
+                            cause,
                             expected,
                             found,
-                            cause.span,
-                            blk_id,
+                            err,
+                            fcx,
+                            parent_id,
+                            expression.map(|expr| (expr, blk_id)),
                         );
-                        // FIXME: replace with navigating up the chain until hitting an fn or
-                        // bailing if no "pass-through" Node is found, in order to provide a
-                        // suggestion when encountering something like:
-                        // ```
-                        // fn foo(a: bool) -> impl Debug {
-                        //     if a {
-                        //         bar()?;
-                        //     }
-                        //     {
-                        //         let x = unsafe { bar() };
-                        //         x
-                        //     }
-                        // }
-                        // ```
-                        //
-                        // Verify that this is a tail expression of a function, otherwise the
-                        // label pointing out the cause for the type coercion will be wrong
-                        // as prior return coercions would not be relevant (#57664).
-                        let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
-                        let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
-                        if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
-                            if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
-                                db.span_label(*sp, reason_label);
-                            }
-                        }
                     }
-                    ObligationCauseCode::ReturnType(_id) => {
-                        db = fcx.report_mismatched_types(cause, expected, found, err);
-                        let _id = fcx.tcx.hir().get_parent_node(_id);
-                        let mut pointing_at_return_type = false;
-                        if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
-                            pointing_at_return_type = fcx.suggest_missing_return_type(
-                                &mut db, &fn_decl, expected, found, can_suggest);
-                        }
-                        if let (Some(sp), false) = (
-                            fcx.ret_coercion_span.borrow().as_ref(),
-                            pointing_at_return_type,
-                        ) {
-                            if !sp.overlaps(cause.span) {
-                                db.span_label(*sp, reason_label);
-                            }
-                        }
+                    ObligationCauseCode::ReturnType(id) => {
+                        db = self.report_return_mismatched_types(
+                            cause, expected, found, err, fcx, id, None);
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
@@ -1283,6 +1239,59 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
         }
     }
 
+    fn report_return_mismatched_types<'a>(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+        err: TypeError<'tcx>,
+        fcx: &FnCtxt<'a, 'gcx, 'tcx>,
+        id: syntax::ast::NodeId,
+        expression: Option<(&'gcx hir::Expr, syntax::ast::NodeId)>,
+    ) -> DiagnosticBuilder<'a> {
+        let mut db = fcx.report_mismatched_types(cause, expected, found, err);
+
+        let mut pointing_at_return_type = false;
+        let mut return_sp = None;
+
+        // Verify that this is a tail expression of a function, otherwise the
+        // label pointing out the cause for the type coercion will be wrong
+        // as prior return coercions would not be relevant (#57664).
+        let parent_id = fcx.tcx.hir().get_parent_node(id);
+        let fn_decl = if let Some((expr, blk_id)) = expression {
+            pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
+                &mut db,
+                expr,
+                expected,
+                found,
+                cause.span,
+                blk_id,
+            );
+            let parent = fcx.tcx.hir().get(parent_id);
+            fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
+        } else {
+            fcx.get_fn_decl(parent_id)
+        };
+
+        if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
+            if expression.is_none() {
+                pointing_at_return_type |= fcx.suggest_missing_return_type(
+                    &mut db, &fn_decl, expected, found, can_suggest);
+            }
+            if !pointing_at_return_type {
+                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+            }
+        }
+        if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
+            db.span_label(return_sp, "expected because this return type...");
+            db.span_label( *sp, format!(
+                "...is found to be `{}` here",
+                fcx.resolve_type_vars_with_obligations(expected),
+            ));
+        }
+        db
+    }
+
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         if let Some(final_ty) = self.final_ty {
             final_ty
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 23bcd88d6af..f71a163cee2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -304,7 +304,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         );
                         if let Some(suggestion) = suggestion {
                             // enum variant
-                            err.help(&format!("did you mean `{}`?", suggestion));
+                            err.span_suggestion_with_applicability(
+                                item_name.span,
+                                "did you mean",
+                                suggestion.to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                         err
                     }
@@ -440,7 +445,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
 
                 if let Some(lev_candidate) = lev_candidate {
-                    err.help(&format!("did you mean `{}`?", lev_candidate.ident));
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "did you mean",
+                        lev_candidate.ident.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
                 err.emit();
             }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 53e44d53e6a..6cae8d6fc5b 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -608,8 +608,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
             if let ty::Opaque(def_id, substs) = ty.sty {
                 trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
-                // only check named existential types
-                if generics.parent.is_none() {
+                // only check named existential types defined in this crate
+                if generics.parent.is_none() && def_id.is_local() {
                     let opaque_node_id = tcx.hir().as_local_node_id(def_id).unwrap();
                     if may_define_existential_type(tcx, fn_def_id, opaque_node_id) {
                         trace!("check_existential_types may define. Generics: {:#?}", generics);
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 83db3f347a7..82f3463dba0 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -7,11 +7,9 @@
 //! primitives](#primitives), [standard macros](#macros), [I/O] and
 //! [multithreading], among [many other things][other].
 //!
-//! `std` is available to all Rust crates by default, just as if each one
-//! contained an `extern crate std;` import at the [crate root]. Therefore the
+//! `std` is available to all Rust crates by default. Therefore the
 //! standard library can be accessed in [`use`] statements through the path
-//! `std`, as in [`use std::env`], or in expressions through the absolute path
-//! `::std`, as in [`::std::env::args`].
+//! `std`, as in [`use std::env`].
 //!
 //! # How to read this documentation
 //!
@@ -157,7 +155,6 @@
 //! [TCP]: net/struct.TcpStream.html
 //! [The Rust Prelude]: prelude/index.html
 //! [UDP]: net/struct.UdpSocket.html
-//! [`::std::env::args`]: env/fn.args.html
 //! [`Arc`]: sync/struct.Arc.html
 //! [owned slice]: boxed/index.html
 //! [`Cell`]: cell/struct.Cell.html
@@ -191,7 +188,6 @@
 //! [`thread`]: thread/index.html
 //! [`use std::env`]: env/index.html
 //! [`use`]: ../book/ch07-02-modules-and-use-to-control-scope-and-privacy.html#the-use-keyword-to-bring-paths-into-a-scope
-//! [crate root]: ../book/ch07-01-packages-and-crates-for-making-libraries-and-executables.html
 //! [crates.io]: https://crates.io
 //! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
 //! [files]: fs/struct.File.html
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 798f14dcba9..af521848e90 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -140,6 +140,20 @@ pub enum GenericArgs {
 }
 
 impl GenericArgs {
+    pub fn is_parenthesized(&self) -> bool {
+        match *self {
+            Parenthesized(..) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_angle_bracketed(&self) -> bool {
+        match *self {
+            AngleBracketed(..) => true,
+            _ => false,
+        }
+    }
+
     pub fn span(&self) -> Span {
         match *self {
             AngleBracketed(ref data) => data.span,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 09ea0995253..c7e33a16564 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -100,6 +100,7 @@ pub enum PathStyle {
 enum SemiColonMode {
     Break,
     Ignore,
+    Comma,
 }
 
 #[derive(Clone, Copy, PartialEq, Debug)]
@@ -1988,6 +1989,44 @@ impl<'a> Parser<'a> {
 
                 result.unwrap()
             }
+            token::Dot if self.look_ahead(1, |t| match t {
+                token::Literal(parse::token::Lit::Integer(_) , _) => true,
+                _ => false,
+            }) => { // recover from `let x = .4;`
+                let lo = self.span;
+                self.bump();
+                if let token::Literal(
+                    parse::token::Lit::Integer(val),
+                    suffix,
+                ) = self.token {
+                    let suffix = suffix.and_then(|s| {
+                        let s = s.as_str().get();
+                        if ["f32", "f64"].contains(&s) {
+                            Some(s)
+                        } else {
+                            None
+                        }
+                    }).unwrap_or("");
+                    self.bump();
+                    let sp = lo.to(self.prev_span);
+                    let mut err = self.diagnostic()
+                        .struct_span_err(sp, "float literals must have an integer part");
+                    err.span_suggestion_with_applicability(
+                        sp,
+                        "must have an integer part",
+                        format!("0.{}{}", val, suffix),
+                        Applicability::MachineApplicable,
+                    );
+                    err.emit();
+                    return Ok(match suffix {
+                        "f32" => ast::LitKind::Float(val, ast::FloatTy::F32),
+                        "f64" => ast::LitKind::Float(val, ast::FloatTy::F64),
+                        _ => ast::LitKind::FloatUnsuffixed(val),
+                    });
+                } else {
+                    unreachable!();
+                };
+            }
             _ => { return self.unexpected_last(&self.token); }
         };
 
@@ -2149,7 +2188,27 @@ impl<'a> Parser<'a> {
                            enable_warning: bool)
                            -> PResult<'a, ()> {
         loop {
-            segments.push(self.parse_path_segment(style, enable_warning)?);
+            let segment = self.parse_path_segment(style, enable_warning)?;
+            if style == PathStyle::Expr {
+                // In order to check for trailing angle brackets, we must have finished
+                // recursing (`parse_path_segment` can indirectly call this function),
+                // that is, the next token must be the highlighted part of the below example:
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                      ^ here
+                //
+                // As opposed to the below highlight (if we had only finished the first
+                // recursion):
+                //
+                // `Foo::<Bar as Baz<T>>::Qux`
+                //                     ^ here
+                //
+                // `PathStyle::Expr` is only provided at the root invocation and never in
+                // `parse_path_segment` to recurse and therefore can be checked to maintain
+                // this invariant.
+                self.check_trailing_angle_brackets(&segment, token::ModSep);
+            }
+            segments.push(segment);
 
             if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
@@ -2656,8 +2715,24 @@ impl<'a> Parser<'a> {
                 break;
             }
 
+            let mut recovery_field = None;
+            if let token::Ident(ident, _) = self.token {
+                if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) {
+                    // Use in case of error after field-looking code: `S { foo: () with a }`
+                    let mut ident = ident.clone();
+                    ident.span = self.span;
+                    recovery_field = Some(ast::Field {
+                        ident,
+                        span: self.span,
+                        expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()),
+                        is_shorthand: false,
+                        attrs: ThinVec::new(),
+                    });
+                }
+            }
+            let mut parsed_field = None;
             match self.parse_field() {
-                Ok(f) => fields.push(f),
+                Ok(f) => parsed_field = Some(f),
                 Err(mut e) => {
                     e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
@@ -2666,19 +2741,28 @@ impl<'a> Parser<'a> {
                     // what comes next as additional fields, rather than
                     // bailing out until next `}`.
                     if self.token != token::Comma {
-                        self.recover_stmt();
-                        break;
+                        self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+                        if self.token != token::Comma {
+                            break;
+                        }
                     }
                 }
             }
 
             match self.expect_one_of(&[token::Comma],
                                      &[token::CloseDelim(token::Brace)]) {
-                Ok(()) => {}
+                Ok(()) => if let Some(f) = parsed_field.or(recovery_field) {
+                    // only include the field if there's no parse error for the field name
+                    fields.push(f);
+                }
                 Err(mut e) => {
+                    if let Some(f) = recovery_field {
+                        fields.push(f);
+                    }
+                    e.span_label(struct_sp, "while parsing this struct");
                     e.emit();
-                    self.recover_stmt();
-                    break;
+                    self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
+                    self.eat(&token::Comma);
                 }
             }
         }
@@ -2757,6 +2841,8 @@ impl<'a> Parser<'a> {
     // Assuming we have just parsed `.`, continue parsing into an expression.
     fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let segment = self.parse_path_segment(PathStyle::Expr, true)?;
+        self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
+
         Ok(match self.token {
             token::OpenDelim(token::Paren) => {
                 // Method call `expr.f()`
@@ -2784,6 +2870,116 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// This function checks if there are trailing angle brackets and produces
+    /// a diagnostic to suggest removing them.
+    ///
+    /// ```ignore (diagnostic)
+    /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    ///                                                        ^^ help: remove extra angle brackets
+    /// ```
+    fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
+        // This function is intended to be invoked after parsing a path segment where there are two
+        // cases:
+        //
+        // 1. A specific token is expected after the path segment.
+        //    eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
+        //        `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
+        // 2. No specific token is expected after the path segment.
+        //    eg. `x.foo` (field access)
+        //
+        // This function is called after parsing `.foo` and before parsing the token `end` (if
+        // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
+        // `Foo::<Bar>`.
+
+        // We only care about trailing angle brackets if we previously parsed angle bracket
+        // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
+        // removed in this case:
+        //
+        // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
+        //
+        // This case is particularly tricky as we won't notice it just looking at the tokens -
+        // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
+        // have already been parsed):
+        //
+        // `x.foo::<u32>>>(3)`
+        let parsed_angle_bracket_args = segment.args
+            .as_ref()
+            .map(|args| args.is_angle_bracketed())
+            .unwrap_or(false);
+
+        debug!(
+            "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
+            parsed_angle_bracket_args,
+        );
+        if !parsed_angle_bracket_args {
+            return;
+        }
+
+        // Keep the span at the start so we can highlight the sequence of `>` characters to be
+        // removed.
+        let lo = self.span;
+
+        // We need to look-ahead to see if we have `>` characters without moving the cursor forward
+        // (since we might have the field access case and the characters we're eating are
+        // actual operators and not trailing characters - ie `x.foo >> 3`).
+        let mut position = 0;
+
+        // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
+        // many of each (so we can correctly pluralize our error messages) and continue to
+        // advance.
+        let mut number_of_shr = 0;
+        let mut number_of_gt = 0;
+        while self.look_ahead(position, |t| {
+            trace!("check_trailing_angle_brackets: t={:?}", t);
+            if *t == token::BinOp(token::BinOpToken::Shr) {
+                number_of_shr += 1;
+                true
+            } else if *t == token::Gt {
+                number_of_gt += 1;
+                true
+            } else {
+                false
+            }
+        }) {
+            position += 1;
+        }
+
+        // If we didn't find any trailing `>` characters, then we have nothing to error about.
+        debug!(
+            "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
+            number_of_gt, number_of_shr,
+        );
+        if number_of_gt < 1 && number_of_shr < 1 {
+            return;
+        }
+
+        // Finally, double check that we have our end token as otherwise this is the
+        // second case.
+        if self.look_ahead(position, |t| {
+            trace!("check_trailing_angle_brackets: t={:?}", t);
+            *t == end
+        }) {
+            // Eat from where we started until the end token so that parsing can continue
+            // as if we didn't have those extra angle brackets.
+            self.eat_to_tokens(&[&end]);
+            let span = lo.until(self.span);
+
+            let plural = number_of_gt > 1 || number_of_shr >= 1;
+            self.diagnostic()
+                .struct_span_err(
+                    span,
+                    &format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
+                )
+                .span_suggestion_with_applicability(
+                    span,
+                    &format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
+                    String::new(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+        }
+    }
+
     fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
         let mut e = e0;
         let mut hi;
@@ -4542,13 +4738,13 @@ impl<'a> Parser<'a> {
                 token::CloseDelim(token::DelimToken::Brace) => {
                     if brace_depth == 0 {
                         debug!("recover_stmt_ return - close delim {:?}", self.token);
-                        return;
+                        break;
                     }
                     brace_depth -= 1;
                     self.bump();
                     if in_block && bracket_depth == 0 && brace_depth == 0 {
                         debug!("recover_stmt_ return - block end {:?}", self.token);
-                        return;
+                        break;
                     }
                 }
                 token::CloseDelim(token::DelimToken::Bracket) => {
@@ -4560,7 +4756,7 @@ impl<'a> Parser<'a> {
                 }
                 token::Eof => {
                     debug!("recover_stmt_ return - Eof");
-                    return;
+                    break;
                 }
                 token::Semi => {
                     self.bump();
@@ -4568,7 +4764,17 @@ impl<'a> Parser<'a> {
                        brace_depth == 0 &&
                        bracket_depth == 0 {
                         debug!("recover_stmt_ return - Semi");
-                        return;
+                        break;
+                    }
+                }
+                token::Comma => {
+                    if break_on_semi == SemiColonMode::Comma &&
+                       brace_depth == 0 &&
+                       bracket_depth == 0 {
+                        debug!("recover_stmt_ return - Semi");
+                        break;
+                    } else {
+                        self.bump();
                     }
                 }
                 _ => {
@@ -7275,9 +7481,16 @@ impl<'a> Parser<'a> {
             // CONST ITEM
             if self.eat_keyword(keywords::Mut) {
                 let prev_span = self.prev_span;
-                self.diagnostic().struct_span_err(prev_span, "const globals cannot be mutable")
-                                 .help("did you mean to declare a static?")
-                                 .emit();
+                let mut err = self.diagnostic()
+                    .struct_span_err(prev_span, "const globals cannot be mutable");
+                err.span_label(prev_span, "cannot be mutable");
+                err.span_suggestion_with_applicability(
+                    const_span,
+                    "you might want to declare a static instead",
+                    "static".to_owned(),
+                    Applicability::MaybeIncorrect,
+                );
+                err.emit();
             }
             let (ident, item_, extra_attrs) = self.parse_item_const(None)?;
             let prev_span = self.prev_span;
diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr
index ab57fec0e73..356e24d18a7 100644
--- a/src/test/ui/auto-ref-slice-plus-ref.stderr
+++ b/src/test/ui/auto-ref-slice-plus-ref.stderr
@@ -2,12 +2,11 @@ error[E0599]: no method named `test_mut` found for type `std::vec::Vec<{integer}
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut(); //~ ERROR no method named `test_mut` found
-   |       ^^^^^^^^
+   |       ^^^^^^^^ help: did you mean: `get_mut`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `test_mut`, perhaps you need to implement it:
            candidate #1: `MyIter`
-   = help: did you mean `get_mut`?
 
 error[E0599]: no method named `test` found for type `std::vec::Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
index 7f386630de5..a6346a5233f 100644
--- a/src/test/ui/block-result/issue-3563.stderr
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -2,9 +2,7 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^
-   |
-   = help: did you mean `a`?
+   |                 ^ help: did you mean: `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index e595e0ccb92..19844503a48 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -51,20 +51,18 @@ error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the
    |
 LL |     let xe3 = XE::Empty3; //~ ERROR no variant named `Empty3` found for type
    |               ----^^^^^^
-   |               |
+   |               |   |
+   |               |   help: did you mean: `XEmpty3`
    |               variant not found in `empty_struct::XE`
-   |
-   = help: did you mean `XEmpty3`?
 
 error[E0599]: no variant named `Empty3` found for type `empty_struct::XE` in the current scope
   --> $DIR/empty-struct-braces-expr.rs:23:19
    |
 LL |     let xe3 = XE::Empty3(); //~ ERROR no variant named `Empty3` found for type
    |               ----^^^^^^
-   |               |
+   |               |   |
+   |               |   help: did you mean: `XEmpty3`
    |               variant not found in `empty_struct::XE`
-   |
-   = help: did you mean `XEmpty3`?
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
new file mode 100644
index 00000000000..af2d209826e
--- /dev/null
+++ b/src/test/ui/existential_types/auxiliary/cross_crate_ice.rs
@@ -0,0 +1,12 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub existential type Foo: std::fmt::Debug;
+
+pub fn foo() -> Foo {
+    5
+}
+
diff --git a/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs b/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
new file mode 100644
index 00000000000..39ec5394feb
--- /dev/null
+++ b/src/test/ui/existential_types/auxiliary/cross_crate_ice2.rs
@@ -0,0 +1,21 @@
+// Crate that exports an existential type. Used for testing cross-crate.
+
+#![crate_type="rlib"]
+
+#![feature(existential_type)]
+
+pub trait View {
+    type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp;
+}
+
+pub struct X;
+
+impl View for X {
+    existential type Tmp: Iterator<Item = u32>;
+
+    fn test(&self) -> Self::Tmp {
+        vec![1,2,3].into_iter()
+    }
+}
diff --git a/src/test/ui/existential_types/cross_crate_ice.rs b/src/test/ui/existential_types/cross_crate_ice.rs
new file mode 100644
index 00000000000..c5d5ca916a4
--- /dev/null
+++ b/src/test/ui/existential_types/cross_crate_ice.rs
@@ -0,0 +1,16 @@
+// aux-build:cross_crate_ice.rs
+// compile-pass
+
+extern crate cross_crate_ice;
+
+struct Bar(cross_crate_ice::Foo);
+
+impl Bar {
+    fn zero(&self) -> &cross_crate_ice::Foo {
+        &self.0
+    }
+}
+
+fn main() {
+    let _ = cross_crate_ice::foo();
+}
diff --git a/src/test/ui/existential_types/cross_crate_ice2.rs b/src/test/ui/existential_types/cross_crate_ice2.rs
new file mode 100644
index 00000000000..a0f3933ce33
--- /dev/null
+++ b/src/test/ui/existential_types/cross_crate_ice2.rs
@@ -0,0 +1,11 @@
+// aux-build:cross_crate_ice2.rs
+// compile-pass
+
+extern crate cross_crate_ice2;
+
+use cross_crate_ice2::View;
+
+fn main() {
+    let v = cross_crate_ice2::X;
+    v.test();
+}
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 57bd70de7c6..6cd9d07748c 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,8 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
+LL | fn two(x: bool) -> impl Foo {
+   |                    -------- expected because this return type...
+LL |     if x {
 LL |         return 1_i32;
-   |                ----- expected because of this statement
+   |                ----- ...is found to be `i32` here
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected i32, found u32
diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr
index 208d0cc499a..9cad002036f 100644
--- a/src/test/ui/issues/issue-23217.stderr
+++ b/src/test/ui/issues/issue-23217.stderr
@@ -5,10 +5,9 @@ LL | pub enum SomeEnum {
    | ----------------- variant `A` not found here
 LL |     B = SomeEnum::A,
    |         ----------^
-   |         |
+   |         |         |
+   |         |         help: did you mean: `B`
    |         variant not found in `SomeEnum`
-   |
-   = help: did you mean `B`?
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index 146ebad6ce1..b6f520c644b 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -11,8 +11,7 @@ LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
    |                 --------^^^^^
    |                 |
    |                 function or associated item not found in `dyn std::ops::BitXor<_>`
-   |
-   = help: did you mean `bitxor`?
+   |                 help: did you mean: `bitxor`
 
 error[E0191]: the value of the associated type `Output` (from the trait `std::ops::BitXor`) must be specified
   --> $DIR/issue-28344.rs:8:13
@@ -27,8 +26,7 @@ LL |     let g = BitXor::bitor;
    |             --------^^^^^
    |             |
    |             function or associated item not found in `dyn std::ops::BitXor<_>`
-   |
-   = help: did you mean `bitxor`?
+   |             help: did you mean: `bitxor`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr
index d5dbd5f6488..77d0b53ad21 100644
--- a/src/test/ui/issues/issue-28971.stderr
+++ b/src/test/ui/issues/issue-28971.stderr
@@ -5,9 +5,10 @@ LL | enum Foo {
    | -------- variant `Baz` not found here
 ...
 LL |             Foo::Baz(..) => (),
-   |             -----^^^---- variant not found in `Foo`
-   |
-   = help: did you mean `Bar`?
+   |             -----^^^----
+   |             |    |
+   |             |    help: did you mean: `Bar`
+   |             variant not found in `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
index 99c4a5b03b3..96d6814b0fe 100644
--- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
+++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr
@@ -2,11 +2,10 @@ error[E0599]: no method named `deref_err` found for type `std::result::Result<_,
   --> $DIR/result-deref-err.rs:4:28
    |
 LL |     let _result = &Err(41).deref_err();
-   |                            ^^^^^^^^^
+   |                            ^^^^^^^^^ help: did you mean: `deref_ok`
    |
    = note: the method `deref_err` exists but the following trait bounds were not satisfied:
            `{integer} : std::ops::Deref`
-   = help: did you mean `deref_ok`?
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-52496.rs b/src/test/ui/issues/issue-52496.rs
new file mode 100644
index 00000000000..4e945365373
--- /dev/null
+++ b/src/test/ui/issues/issue-52496.rs
@@ -0,0 +1,12 @@
+struct Foo { bar: f64, baz: i64, bat: i64 }
+
+fn main() {
+    let _ = Foo { bar: .5, baz: 42 };
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR missing field `bat` in initializer of `Foo`
+    let bar = 1.5f32;
+    let _ = Foo { bar.into(), bat: -1, . };
+    //~^ ERROR expected one of
+    //~| ERROR missing fields `bar`, `baz` in initializer of `Foo`
+    //~| ERROR expected identifier, found `.`
+}
diff --git a/src/test/ui/issues/issue-52496.stderr b/src/test/ui/issues/issue-52496.stderr
new file mode 100644
index 00000000000..43009a15bd4
--- /dev/null
+++ b/src/test/ui/issues/issue-52496.stderr
@@ -0,0 +1,37 @@
+error: float literals must have an integer part
+  --> $DIR/issue-52496.rs:4:24
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |                        ^^ help: must have an integer part: `0.5`
+
+error: expected one of `,` or `}`, found `.`
+  --> $DIR/issue-52496.rs:8:22
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---      ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `.`
+  --> $DIR/issue-52496.rs:8:40
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ---                        ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error[E0063]: missing field `bat` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:4:13
+   |
+LL |     let _ = Foo { bar: .5, baz: 42 };
+   |             ^^^ missing `bat`
+
+error[E0063]: missing fields `bar`, `baz` in initializer of `Foo`
+  --> $DIR/issue-52496.rs:8:13
+   |
+LL |     let _ = Foo { bar.into(), bat: -1, . };
+   |             ^^^ missing `bar`, `baz`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/issues/issue-54521-1.rs b/src/test/ui/issues/issue-54521-1.rs
new file mode 100644
index 00000000000..d6a14a6e11f
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-1.rs
@@ -0,0 +1,16 @@
+// compile-pass
+
+// This test checks that the `remove extra angle brackets` error doesn't happen for some
+// potential edge-cases..
+
+struct X {
+    len: u32,
+}
+
+fn main() {
+    let x = X { len: 3 };
+
+    let _ = x.len > (3);
+
+    let _ = x.len >> (3);
+}
diff --git a/src/test/ui/issues/issue-54521-2.fixed b/src/test/ui/issues/issue-54521-2.fixed
new file mode 100644
index 00000000000..a91c4fe43ea
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.rs b/src/test/ui/issues/issue-54521-2.rs
new file mode 100644
index 00000000000..3639aac87ee
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = Vec::<usize>>>::new();
+//                     ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = Vec::<usize>>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>>::new();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = Vec::<usize>>::new();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521-2.stderr b/src/test/ui/issues/issue-54521-2.stderr
new file mode 100644
index 00000000000..9556b83b730
--- /dev/null
+++ b/src/test/ui/issues/issue-54521-2.stderr
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:11:25
+   |
+LL |     let _ = Vec::<usize>>>>>::new();
+   |                         ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:14:25
+   |
+LL |     let _ = Vec::<usize>>>>::new();
+   |                         ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521-2.rs:17:25
+   |
+LL |     let _ = Vec::<usize>>>::new();
+   |                         ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521-2.rs:20:25
+   |
+LL |     let _ = Vec::<usize>>::new();
+   |                         ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/issues/issue-54521.fixed b/src/test/ui/issues/issue-54521.fixed
new file mode 100644
index 00000000000..84ab6866cf1
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.fixed
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.rs b/src/test/ui/issues/issue-54521.rs
new file mode 100644
index 00000000000..f1d68504178
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.rs
@@ -0,0 +1,22 @@
+// run-rustfix
+
+// This test checks that the following error is emitted and the suggestion works:
+//
+// ```
+// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+//                                                        ^^ help: remove extra angle brackets
+// ```
+
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+    //~^ ERROR unmatched angle bracket
+
+    let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+    //~^ ERROR unmatched angle bracket
+}
diff --git a/src/test/ui/issues/issue-54521.stderr b/src/test/ui/issues/issue-54521.stderr
new file mode 100644
index 00000000000..ffefbfd0348
--- /dev/null
+++ b/src/test/ui/issues/issue-54521.stderr
@@ -0,0 +1,26 @@
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:11:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>>();
+   |                                                            ^^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:14:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>>();
+   |                                                            ^^^ help: remove extra angle brackets
+
+error: unmatched angle brackets
+  --> $DIR/issue-54521.rs:17:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
+   |                                                            ^^ help: remove extra angle brackets
+
+error: unmatched angle bracket
+  --> $DIR/issue-54521.rs:20:60
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>();
+   |                                                            ^ help: remove extra angle bracket
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/issue-17718-const-mut.rs b/src/test/ui/parser/issue-17718-const-mut.rs
index 4e74516d6b6..795a8c7631d 100644
--- a/src/test/ui/parser/issue-17718-const-mut.rs
+++ b/src/test/ui/parser/issue-17718-const-mut.rs
@@ -1,6 +1,6 @@
 const
 mut //~ ERROR: const globals cannot be mutable
-//~^ HELP did you mean to declare a static?
+//~^^ HELP you might want to declare a static instead
 FOO: usize = 3;
 
 fn main() {
diff --git a/src/test/ui/parser/issue-17718-const-mut.stderr b/src/test/ui/parser/issue-17718-const-mut.stderr
index 29a65ebe418..19f9fe19ef5 100644
--- a/src/test/ui/parser/issue-17718-const-mut.stderr
+++ b/src/test/ui/parser/issue-17718-const-mut.stderr
@@ -1,10 +1,10 @@
 error: const globals cannot be mutable
   --> $DIR/issue-17718-const-mut.rs:2:1
    |
+LL | const
+   | ----- help: you might want to declare a static instead: `static`
 LL | mut //~ ERROR: const globals cannot be mutable
-   | ^^^
-   |
-   = help: did you mean to declare a static?
+   | ^^^ cannot be mutable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/removed-syntax-with-1.rs b/src/test/ui/parser/removed-syntax-with-1.rs
index 57cbe8d5be6..2c1e152dcee 100644
--- a/src/test/ui/parser/removed-syntax-with-1.rs
+++ b/src/test/ui/parser/removed-syntax-with-1.rs
@@ -5,7 +5,6 @@ fn main() {
     }
 
     let a = S { foo: (), bar: () };
-    let b = S { foo: () with a };
+    let b = S { foo: () with a, bar: () };
     //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
-    //~| ERROR missing field `bar` in initializer of `main::S`
 }
diff --git a/src/test/ui/parser/removed-syntax-with-1.stderr b/src/test/ui/parser/removed-syntax-with-1.stderr
index 77ed4fcea51..a157873916a 100644
--- a/src/test/ui/parser/removed-syntax-with-1.stderr
+++ b/src/test/ui/parser/removed-syntax-with-1.stderr
@@ -1,15 +1,10 @@
 error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with`
   --> $DIR/removed-syntax-with-1.rs:8:25
    |
-LL |     let b = S { foo: () with a };
-   |                         ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+LL |     let b = S { foo: () with a, bar: () };
+   |             -           ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator here
+   |             |
+   |             while parsing this struct
 
-error[E0063]: missing field `bar` in initializer of `main::S`
-  --> $DIR/removed-syntax-with-1.rs:8:13
-   |
-LL |     let b = S { foo: () with a };
-   |             ^ missing `bar`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/removed-syntax-with-2.rs b/src/test/ui/parser/removed-syntax-with-2.rs
index 11db391c548..f666da49696 100644
--- a/src/test/ui/parser/removed-syntax-with-2.rs
+++ b/src/test/ui/parser/removed-syntax-with-2.rs
@@ -7,6 +7,5 @@ fn main() {
     let a = S { foo: (), bar: () };
     let b = S { foo: (), with a };
     //~^ ERROR expected one of `,` or `}`, found `a`
-    //~| ERROR cannot find value `with` in this scope
-    //~| ERROR struct `main::S` has no field named `with`
+    //~| ERROR missing field `bar` in initializer of `main::S`
 }
diff --git a/src/test/ui/parser/removed-syntax-with-2.stderr b/src/test/ui/parser/removed-syntax-with-2.stderr
index 5642d2f45ff..7717b49d3a2 100644
--- a/src/test/ui/parser/removed-syntax-with-2.stderr
+++ b/src/test/ui/parser/removed-syntax-with-2.stderr
@@ -2,23 +2,16 @@ error: expected one of `,` or `}`, found `a`
   --> $DIR/removed-syntax-with-2.rs:8:31
    |
 LL |     let b = S { foo: (), with a };
-   |                               ^ expected one of `,` or `}` here
+   |             -                 ^ expected one of `,` or `}` here
+   |             |
+   |             while parsing this struct
 
-error[E0425]: cannot find value `with` in this scope
-  --> $DIR/removed-syntax-with-2.rs:8:26
+error[E0063]: missing field `bar` in initializer of `main::S`
+  --> $DIR/removed-syntax-with-2.rs:8:13
    |
 LL |     let b = S { foo: (), with a };
-   |                          ^^^^ not found in this scope
+   |             ^ missing `bar`
 
-error[E0560]: struct `main::S` has no field named `with`
-  --> $DIR/removed-syntax-with-2.rs:8:26
-   |
-LL |     let b = S { foo: (), with a };
-   |                          ^^^^ `main::S` does not have this field
-   |
-   = note: available fields are: `foo`, `bar`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0425, E0560.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.rs b/src/test/ui/parser/struct-field-numeric-shorthand.rs
index 914588f51e1..58c40b3d96a 100644
--- a/src/test/ui/parser/struct-field-numeric-shorthand.rs
+++ b/src/test/ui/parser/struct-field-numeric-shorthand.rs
@@ -1,6 +1,9 @@
 struct Rgb(u8, u8, u8);
 
 fn main() {
-    let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
-                             //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
+    let _ = Rgb { 0, 1, 2 };
+    //~^ ERROR expected identifier, found `0`
+    //~| ERROR expected identifier, found `1`
+    //~| ERROR expected identifier, found `2`
+    //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb`
 }
diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.stderr b/src/test/ui/parser/struct-field-numeric-shorthand.stderr
index f5dc226934e..cfb1f820147 100644
--- a/src/test/ui/parser/struct-field-numeric-shorthand.stderr
+++ b/src/test/ui/parser/struct-field-numeric-shorthand.stderr
@@ -1,17 +1,33 @@
 error: expected identifier, found `0`
   --> $DIR/struct-field-numeric-shorthand.rs:4:19
    |
-LL |     let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL |     let _ = Rgb { 0, 1, 2 };
    |             ---   ^ expected identifier
    |             |
    |             while parsing this struct
 
+error: expected identifier, found `1`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:22
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---      ^ expected identifier
+   |             |
+   |             while parsing this struct
+
+error: expected identifier, found `2`
+  --> $DIR/struct-field-numeric-shorthand.rs:4:25
+   |
+LL |     let _ = Rgb { 0, 1, 2 };
+   |             ---         ^ expected identifier
+   |             |
+   |             while parsing this struct
+
 error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb`
   --> $DIR/struct-field-numeric-shorthand.rs:4:13
    |
-LL |     let _ = Rgb { 0, 1, 2 }; //~ ERROR expected identifier, found `0`
+LL |     let _ = Rgb { 0, 1, 2 };
    |             ^^^ missing `0`, `1`, `2`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
index 62da0787b02..5ebe00e624f 100644
--- a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -1,8 +1,11 @@
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
    |
+LL | fn foo() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
 LL |         return 0i32;
-   |                ---- expected because of this statement
+   |                ---- ...is found to be `i32` here
 LL |     }
 LL |     1u32
    |     ^^^^ expected i32, found u32
@@ -13,8 +16,11 @@ LL |     1u32
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
    |
+LL | fn bar() -> impl std::fmt::Display {
+   |             ---------------------- expected because this return type...
+LL |     if false {
 LL |         return 0i32;
-   |                ---- expected because of this statement
+   |                ---- ...is found to be `i32` here
 LL |     } else {
 LL |         return 1u32;
    |                ^^^^ expected i32, found u32
@@ -25,10 +31,12 @@ LL |         return 1u32;
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
    |
+LL |   fn baz() -> impl std::fmt::Display {
+   |               ---------------------- expected because this return type...
 LL | /     if false {
 LL | |     //~^ ERROR mismatched types
 LL | |         return 0i32;
-   | |                ---- expected because of this statement
+   | |                ---- ...is found to be `i32` here
 LL | |     } else {
 LL | |         1u32
 LL | |     }
diff --git a/src/test/ui/suggestions/recover-invalid-float.rs b/src/test/ui/suggestions/recover-invalid-float.rs
new file mode 100644
index 00000000000..506ef8900b8
--- /dev/null
+++ b/src/test/ui/suggestions/recover-invalid-float.rs
@@ -0,0 +1,11 @@
+fn main() {
+    let _: usize = .3;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .42f32;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+    let _: usize = .5f64;
+    //~^ ERROR float literals must have an integer part
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/recover-invalid-float.stderr b/src/test/ui/suggestions/recover-invalid-float.stderr
new file mode 100644
index 00000000000..c464676b444
--- /dev/null
+++ b/src/test/ui/suggestions/recover-invalid-float.stderr
@@ -0,0 +1,42 @@
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ help: must have an integer part: `0.3`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ help: must have an integer part: `0.42f32`
+
+error: float literals must have an integer part
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ help: must have an integer part: `0.5f64`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:2:20
+   |
+LL |     let _: usize = .3;
+   |                    ^^ expected usize, found floating-point number
+   |
+   = note: expected type `usize`
+              found type `{float}`
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:5:20
+   |
+LL |     let _: usize = .42f32;
+   |                    ^^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/recover-invalid-float.rs:8:20
+   |
+LL |     let _: usize = .5f64;
+   |                    ^^^^^ expected usize, found f64
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr
index 39d96a943a1..b7727cf03a4 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggestions/suggest-methods.stderr
@@ -5,25 +5,19 @@ LL | struct Foo;
    | ----------- method `bat` not found for this
 ...
 LL |     f.bat(1.0); //~ ERROR no method named
-   |       ^^^
-   |
-   = help: did you mean `bar`?
+   |       ^^^ help: did you mean: `bar`
 
 error[E0599]: no method named `is_emtpy` found for type `std::string::String` in the current scope
   --> $DIR/suggest-methods.rs:21:15
    |
 LL |     let _ = s.is_emtpy(); //~ ERROR no method named
-   |               ^^^^^^^^
-   |
-   = help: did you mean `is_empty`?
+   |               ^^^^^^^^ help: did you mean: `is_empty`
 
 error[E0599]: no method named `count_eos` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:25:19
    |
 LL |     let _ = 63u32.count_eos(); //~ ERROR no method named
-   |                   ^^^^^^^^^
-   |
-   = help: did you mean `count_zeros`?
+   |                   ^^^^^^^^^ help: did you mean: `count_zeros`
 
 error[E0599]: no method named `count_o` found for type `u32` in the current scope
   --> $DIR/suggest-methods.rs:28:19
diff --git a/src/test/ui/traits/trait-privacy.rs b/src/test/ui/traits/trait-privacy.rs
index 523211fea93..6254157e25d 100644
--- a/src/test/ui/traits/trait-privacy.rs
+++ b/src/test/ui/traits/trait-privacy.rs
@@ -1,5 +1,4 @@
 // compile-pass
-#![feature(get_type_id)]
 #![allow(dead_code)]
 mod foo {
     pub use self::bar::T;
@@ -18,7 +17,7 @@ fn g() {
 
 fn f() {
     let error = ::std::thread::spawn(|| {}).join().unwrap_err();
-    error.get_type_id(); // Regression test for #21670
+    error.type_id(); // Regression test for #21670
 }