about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-05 12:11:05 +0000
committerbors <bors@rust-lang.org>2021-02-05 12:11:05 +0000
commitf9435f4c92651d67d5dbaba13c5606c4c4fc1327 (patch)
treed6b3c5182c722eef20e17d3a76f84ce13977bf27
parent730d6dfdddc0f55d9cbeedb29a14b342f74e2a9d (diff)
parent2383cd4b2d820f968a57f9750bf4b4471a655835 (diff)
downloadrust-f9435f4c92651d67d5dbaba13c5606c4c4fc1327.tar.gz
rust-f9435f4c92651d67d5dbaba13c5606c4c4fc1327.zip
Auto merge of #81784 - m-ou-se:rollup-s23fow7, r=m-ou-se
Rollup of 15 pull requests

Successful merges:

 - #79554 (Generic associated types in trait paths)
 - #80726 (relax adt unsizing requirements)
 - #81307 (Handle `Span`s for byte and raw strings and add more detail )
 - #81318 (rustdoc-json: Fix has_body)
 - #81456 (Make remote-test-server easier to use with new targets)
 - #81497 (rustdoc: Move `display_fn` struct inside `display_fn`)
 - #81500 (Remove struct_type from union output)
 - #81542 (Expose correct symlink API on WASI)
 - #81676 (Add more information to the error code for 'crate not found')
 - #81682 (Add additional bitset benchmarks)
 - #81730 (Make `Allocator` object-safe)
 - #81763 (Cleanup rustdoc pass descriptions a bit)
 - #81767 (Update LayoutError/LayoutErr stability attributes)
 - #81771 (Indicate change in RSS from start to end of pass in time-passes output)
 - #81781 (Fix `install-awscli.sh` error in CI)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs39
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs7
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs25
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0463.md21
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_hir/src/hir.rs1
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs1
-rw-r--r--compiler/rustc_index/src/bit_set.rs12
-rw-r--r--compiler/rustc_index/src/bit_set/tests.rs34
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs10
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs30
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs186
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs62
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs166
-rw-r--r--library/core/src/alloc/layout.rs4
-rw-r--r--library/core/src/alloc/mod.rs9
-rw-r--r--library/std/src/sys/wasi/ext/fs.rs8
-rw-r--r--src/bootstrap/test.rs3
-rwxr-xr-xsrc/ci/scripts/install-awscli.sh2
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/format.rs22
-rw-r--r--src/librustdoc/json/conversions.rs27
-rw-r--r--src/librustdoc/json/mod.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs4
-rw-r--r--src/librustdoc/passes/non_autolinks.rs2
-rw-r--r--src/librustdoc/passes/strip_hidden.rs2
-rw-r--r--src/rustdoc-json-types/lib.rs10
-rw-r--r--src/test/rustdoc-json/traits/has_body.rs21
-rw-r--r--src/test/rustdoc-json/unions/union.rs7
-rw-r--r--src/test/ui/allocator/object-safe.rs13
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.rs2
-rw-r--r--src/test/ui/attributes/key-value-non-ascii.stderr5
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs10
-rw-r--r--src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr14
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs12
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr29
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.rs30
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.stderr11
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs16
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr32
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs18
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr44
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs15
-rw-r--r--src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr68
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.rs12
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-67510.rs13
-rw-r--r--src/test/ui/generic-associated-types/issue-67510.stderr32
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-1.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-1.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-2.rs24
-rw-r--r--src/test/ui/generic-associated-types/issue-68648-2.stderr23
-rw-r--r--src/test/ui/generic-associated-types/issue-68649-pass.rs25
-rw-r--r--src/test/ui/generic-associated-types/issue-68649-pass.stderr11
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-1.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-1.stderr27
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-2.rs26
-rw-r--r--src/test/ui/generic-associated-types/issue-74684-2.stderr21
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.rs41
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.stderr63
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.rs47
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.stderr54
-rw-r--r--src/test/ui/generic-associated-types/issue-80433-reduced.rs24
-rw-r--r--src/test/ui/generic-associated-types/issue-80433.rs35
-rw-r--r--src/test/ui/generic-associated-types/issue-80433.stderr19
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs6
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr51
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs17
-rw-r--r--src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr14
-rw-r--r--src/test/ui/parser/ascii-only-character-escape.rs6
-rw-r--r--src/test/ui/parser/ascii-only-character-escape.stderr12
-rw-r--r--src/test/ui/parser/bad-char-literals.rs8
-rw-r--r--src/test/ui/parser/bad-char-literals.stderr16
-rw-r--r--src/test/ui/parser/byte-literals.rs4
-rw-r--r--src/test/ui/parser/byte-literals.stderr25
-rw-r--r--src/test/ui/parser/byte-string-literals.rs5
-rw-r--r--src/test/ui/parser/byte-string-literals.stderr27
-rw-r--r--src/test/ui/parser/issue-23620-invalid-escapes.rs14
-rw-r--r--src/test/ui/parser/issue-23620-invalid-escapes.stderr34
-rw-r--r--src/test/ui/parser/issue-43692.stderr4
-rw-r--r--src/test/ui/parser/issue-62913.stderr2
-rw-r--r--src/test/ui/parser/issue-64732.stderr6
-rw-r--r--src/test/ui/parser/lex-bad-char-literals-1.stderr8
-rw-r--r--src/test/ui/parser/lex-bad-char-literals-7.rs2
-rw-r--r--src/test/ui/parser/lex-bad-char-literals-7.stderr6
-rw-r--r--src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs2
-rw-r--r--src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr6
-rw-r--r--src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr4
-rw-r--r--src/test/ui/parser/new-unicode-escapes-1.rs2
-rw-r--r--src/test/ui/parser/new-unicode-escapes-1.stderr9
-rw-r--r--src/test/ui/parser/new-unicode-escapes-2.rs2
-rw-r--r--src/test/ui/parser/new-unicode-escapes-2.stderr4
-rw-r--r--src/test/ui/parser/new-unicode-escapes-3.stderr4
-rw-r--r--src/test/ui/parser/new-unicode-escapes-4.rs2
-rw-r--r--src/test/ui/parser/new-unicode-escapes-4.stderr4
-rw-r--r--src/test/ui/parser/raw/raw-byte-string-literals.stderr2
-rw-r--r--src/test/ui/parser/trailing-carriage-return-in-string.rs4
-rw-r--r--src/test/ui/parser/trailing-carriage-return-in-string.stderr2
-rw-r--r--src/test/ui/parser/wrong-escape-of-curly-braces.rs8
-rw-r--r--src/test/ui/parser/wrong-escape-of-curly-braces.stderr4
-rw-r--r--src/test/ui/unsized/unchanged-param.rs12
-rw-r--r--src/tools/remote-test-server/src/main.rs24
106 files changed, 1599 insertions, 385 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index b7f227da73e..f076dca5cf5 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1076,16 +1076,40 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_assoc_ty_constraint(
         &mut self,
         constraint: &AssocTyConstraint,
-        itctx: ImplTraitContext<'_, 'hir>,
+        mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::TypeBinding<'hir> {
         debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
 
-        if let Some(ref gen_args) = constraint.gen_args {
-            self.sess.span_fatal(
-                gen_args.span(),
-                "generic associated types in trait paths are currently not implemented",
-            );
-        }
+        // lower generic arguments of identifier in constraint
+        let gen_args = if let Some(ref gen_args) = constraint.gen_args {
+            let gen_args_ctor = match gen_args {
+                GenericArgs::AngleBracketed(ref data) => {
+                    self.lower_angle_bracketed_parameter_data(
+                        data,
+                        ParamMode::Explicit,
+                        itctx.reborrow(),
+                    )
+                    .0
+                }
+                GenericArgs::Parenthesized(ref data) => {
+                    let mut err = self.sess.struct_span_err(
+                        gen_args.span(),
+                        "parenthesized generic arguments cannot be used in associated type constraints"
+                    );
+                    // FIXME: try to write a suggestion here
+                    err.emit();
+                    self.lower_angle_bracketed_parameter_data(
+                        &data.as_angle_bracketed_args(),
+                        ParamMode::Explicit,
+                        itctx.reborrow(),
+                    )
+                    .0
+                }
+            };
+            self.arena.alloc(gen_args_ctor.into_generic_args(&self.arena))
+        } else {
+            self.arena.alloc(hir::GenericArgs::none())
+        };
 
         let kind = match constraint.kind {
             AssocTyConstraintKind::Equality { ref ty } => {
@@ -1182,6 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::TypeBinding {
             hir_id: self.lower_node_id(constraint.id),
             ident: constraint.ident,
+            gen_args,
             kind,
             span: constraint.span,
         }
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 9079e26eb50..cb4d5ea6ee6 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -362,7 +362,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
     }
 
-    fn lower_angle_bracketed_parameter_data(
+    pub(crate) fn lower_angle_bracketed_parameter_data(
         &mut self,
         data: &AngleBracketedArgs,
         param_mode: ParamMode,
@@ -426,6 +426,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> hir::TypeBinding<'hir> {
         let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME);
         let kind = hir::TypeBindingKind::Equality { ty };
-        hir::TypeBinding { hir_id: self.next_id(), span, ident, kind }
+        let args = arena_vec![self;];
+        let bindings = arena_vec![self;];
+        let gen_args = self.arena.alloc(hir::GenericArgs { args, bindings, parenthesized: false });
+        hir::TypeBinding { hir_id: self.next_id(), gen_args, span, ident, kind }
     }
 }
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 9a85b9d02c9..f0b413c795e 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -590,24 +590,21 @@ pub fn print_time_passes_entry(
     end_rss: Option<usize>,
 ) {
     let rss_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as usize;
+    let rss_change_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as i128;
 
     let mem_string = match (start_rss, end_rss) {
         (Some(start_rss), Some(end_rss)) => {
-            // It's tempting to add the change in RSS from start to end, but its somewhat confusing
-            // and misleading when looking at time-passes output. Consider two adjacent entries:
-            //
-            // time:  10.000; rss start:  1000MB, end:  1000MB, change:     0MB     pass1
-            // time:   5.000; rss start:  2000MB, end:  2000MB, change:     0MB     pass2
-            //
-            // If you're looking for jumps in RSS based on the change column, you miss the fact
-            // that a 1GB jump happened between pass1 and pass2 (supposing pass1 and pass2 actually
-            // occur sequentially and pass1 isn't just nested within pass2). It's easy to imagine
-            // someone missing this or being confused by the fact that the change is zero.
-
-            format!("; rss: {:>5}MB -> {:>5}MB", rss_to_mb(start_rss), rss_to_mb(end_rss))
+            let change_rss = end_rss as i128 - start_rss as i128;
+
+            format!(
+                "; rss: {:>4}MB -> {:>4}MB ({:>+5}MB)",
+                rss_to_mb(start_rss),
+                rss_to_mb(end_rss),
+                rss_change_to_mb(change_rss),
+            )
         }
-        (Some(start_rss), None) => format!("; rss start: {:>5}MB", rss_to_mb(start_rss)),
-        (None, Some(end_rss)) => format!("; rss end: {:5>}MB", rss_to_mb(end_rss)),
+        (Some(start_rss), None) => format!("; rss start: {:>4}MB", rss_to_mb(start_rss)),
+        (None, Some(end_rss)) => format!("; rss end: {:>4}MB", rss_to_mb(end_rss)),
         (None, None) => String::new(),
     };
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0463.md b/compiler/rustc_error_codes/src/error_codes/E0463.md
index e46938c607d..d0cd1b1dcb7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0463.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0463.md
@@ -11,3 +11,24 @@ extern crate cake_is_a_lie; // error: can't find crate for `cake_is_a_lie`
 You need to link your code to the relevant crate in order to be able to use it
 (through Cargo or the `-L` option of rustc example). Plugins are crates as
 well, and you link to them the same way.
+
+## Common causes
+
+- The crate is not present at all. If using Cargo, add it to `[dependencies]`
+  in Cargo.toml.
+- The crate is present, but under a different name. If using Cargo, look for
+  `package = ` under `[dependencies]` in Cargo.toml.
+
+## Common causes for missing `std` or `core`
+
+- You are cross-compiling for a target which doesn't have `std` prepackaged.
+  Consider one of the following:
+  + Adding a pre-compiled version of std with `rustup target add`
+  + Building std from source with `cargo build -Z build-std`
+  + Using `#![no_std]` at the crate root, so you won't need `std` in the first
+    place.
+- You are developing the compiler itself and haven't built libstd from source.
+  You can usually build it with `x.py build library/std`. More information
+  about x.py is available in the [rustc-dev-guide].
+
+[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#building-the-compiler
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 818f6c70de0..4f38e060023 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -631,6 +631,9 @@ declare_features! (
 
     /// Allows `extern "C-cmse-nonsecure-call" fn()`.
     (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
+
+    /// Lessens the requirements for structs to implement `Unsize`.
+    (active, relaxed_struct_unsize, "1.51.0", Some(1), None),
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 6487b23a6a6..67a15418ea4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2015,6 +2015,7 @@ pub struct TypeBinding<'hir> {
     pub hir_id: HirId,
     #[stable_hasher(project(name))]
     pub ident: Ident,
+    pub gen_args: &'hir GenericArgs<'hir>,
     pub kind: TypeBindingKind<'hir>,
     pub span: Span,
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 6c1bee2335a..f8b3f0d9b6e 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -781,6 +781,7 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
 ) {
     visitor.visit_id(type_binding.hir_id);
     visitor.visit_ident(type_binding.ident);
+    visitor.visit_generic_args(type_binding.span, type_binding.gen_args);
     match type_binding.kind {
         TypeBindingKind::Equality { ref ty } => {
             visitor.visit_ty(ty);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index f1c2a6b7e6e..4595855309f 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1840,6 +1840,7 @@ impl<'a> State<'a> {
             for binding in generic_args.bindings.iter() {
                 start_or_comma(self);
                 self.print_ident(binding.ident);
+                self.print_generic_args(binding.gen_args, false, false);
                 self.s.space();
                 match generic_args.bindings[0].kind {
                     hir::TypeBindingKind::Equality { ref ty } => {
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 0b501da7cd9..100824f4b94 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -707,6 +707,18 @@ impl<T: Idx> GrowableBitSet<T> {
         self.bit_set.insert(elem)
     }
 
+    /// Returns `true` if the set has changed.
+    #[inline]
+    pub fn remove(&mut self, elem: T) -> bool {
+        self.ensure(elem.index() + 1);
+        self.bit_set.remove(elem)
+    }
+
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.bit_set.is_empty()
+    }
+
     #[inline]
     pub fn contains(&self, elem: T) -> bool {
         let (word_index, mask) = word_index_and_mask(elem);
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index 6cc3e9427d1..c11b98e77aa 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -1,6 +1,7 @@
 use super::*;
 
 extern crate test;
+use std::hint::black_box;
 use test::Bencher;
 
 #[test]
@@ -364,3 +365,36 @@ fn union_hybrid_sparse_full_small_domain(b: &mut Bencher) {
         sparse.union(&dense);
     })
 }
+
+#[bench]
+fn bench_insert(b: &mut Bencher) {
+    let mut bs = BitSet::new_filled(99999usize);
+    b.iter(|| {
+        black_box(bs.insert(black_box(100u32)));
+    });
+}
+
+#[bench]
+fn bench_remove(b: &mut Bencher) {
+    let mut bs = BitSet::new_filled(99999usize);
+    b.iter(|| {
+        black_box(bs.remove(black_box(100u32)));
+    });
+}
+
+#[bench]
+fn bench_iter(b: &mut Bencher) {
+    let bs = BitSet::new_filled(99999usize);
+    b.iter(|| {
+        bs.iter().map(|b: usize| black_box(b)).for_each(drop);
+    });
+}
+
+#[bench]
+fn bench_intersect(b: &mut Bencher) {
+    let mut ba: BitSet<u32> = BitSet::new_filled(99999usize);
+    let bb = BitSet::new_filled(99999usize);
+    b.iter(|| {
+        ba.intersect(black_box(&bb));
+    });
+}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 6b4f08d9f93..c1fa84dcb25 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1132,8 +1132,16 @@ impl<'tcx> ProjectionTy<'tcx> {
     /// For example, if this is a projection of `<T as Iterator>::Item`,
     /// then this function would return a `T: Iterator` trait reference.
     pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
+        // FIXME: This method probably shouldn't exist at all, since it's not
+        // clear what this method really intends to do. Be careful when
+        // using this method since the resulting TraitRef additionally
+        // contains the substs for the assoc_item, which strictly speaking
+        // is not correct
         let def_id = tcx.associated_item(self.item_def_id).container.id();
-        ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, tcx.generics_of(def_id)) }
+        // Include substitutions for generic arguments of associated types
+        let assoc_item = tcx.associated_item(self.item_def_id);
+        let substs_assoc_item = self.substs.truncate_to(tcx, tcx.generics_of(assoc_item.def_id));
+        ty::TraitRef { def_id, substs: substs_assoc_item }
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index b5b34c7338d..4a638ec3f80 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -14,7 +14,7 @@ mod tokentrees;
 mod unescape_error_reporting;
 mod unicode_chars;
 
-use unescape_error_reporting::{emit_unescape_error, push_escaped_char};
+use unescape_error_reporting::{emit_unescape_error, escaped_char};
 
 #[derive(Clone, Debug)]
 pub struct UnmatchedBrace {
@@ -122,11 +122,9 @@ impl<'a> StringReader<'a> {
         m: &str,
         c: char,
     ) -> DiagnosticBuilder<'a> {
-        let mut m = m.to_string();
-        m.push_str(": ");
-        push_escaped_char(&mut m, c);
-
-        self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
+        self.sess
+            .span_diagnostic
+            .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
     }
 
     /// Turns simple `rustc_lexer::TokenKind` enum into a rich
@@ -421,7 +419,7 @@ impl<'a> StringReader<'a> {
         let content_start = start + BytePos(prefix_len);
         let content_end = suffix_start - BytePos(postfix_len);
         let id = self.symbol_from_to(content_start, content_end);
-        self.validate_literal_escape(mode, content_start, content_end);
+        self.validate_literal_escape(mode, content_start, content_end, prefix_len, postfix_len);
         (lit_kind, id)
     }
 
@@ -525,17 +523,29 @@ impl<'a> StringReader<'a> {
         .raise();
     }
 
-    fn validate_literal_escape(&self, mode: Mode, content_start: BytePos, content_end: BytePos) {
+    fn validate_literal_escape(
+        &self,
+        mode: Mode,
+        content_start: BytePos,
+        content_end: BytePos,
+        prefix_len: u32,
+        postfix_len: u32,
+    ) {
         let lit_content = self.str_from_to(content_start, content_end);
         unescape::unescape_literal(lit_content, mode, &mut |range, result| {
             // Here we only check for errors. The actual unescaping is done later.
             if let Err(err) = result {
-                let span_with_quotes =
-                    self.mk_sp(content_start - BytePos(1), content_end + BytePos(1));
+                let span_with_quotes = self
+                    .mk_sp(content_start - BytePos(prefix_len), content_end + BytePos(postfix_len));
+                let (start, end) = (range.start as u32, range.end as u32);
+                let lo = content_start + BytePos(start);
+                let hi = lo + BytePos(end - start);
+                let span = self.mk_sp(lo, hi);
                 emit_unescape_error(
                     &self.sess.span_diagnostic,
                     lit_content,
                     span_with_quotes,
+                    span,
                     mode,
                     range,
                     err,
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 47d317f9188..a580f0c55d0 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -13,6 +13,8 @@ pub(crate) fn emit_unescape_error(
     lit: &str,
     // full span of the literal, including quotes
     span_with_quotes: Span,
+    // interior span of the literal, without quotes
+    span: Span,
     mode: Mode,
     // range of the error inside `lit`
     range: Range<usize>,
@@ -26,13 +28,6 @@ pub(crate) fn emit_unescape_error(
         range,
         error
     );
-    let span = {
-        let Range { start, end } = range;
-        let (start, end) = (start as u32, end as u32);
-        let lo = span_with_quotes.lo() + BytePos(start + 1);
-        let hi = lo + BytePos(end - start);
-        span_with_quotes.with_lo(lo).with_hi(hi)
-    };
     let last_char = || {
         let c = lit[range.clone()].chars().rev().next().unwrap();
         let span = span.with_lo(span.hi() - BytePos(c.len_utf8() as u32));
@@ -42,20 +37,22 @@ pub(crate) fn emit_unescape_error(
         EscapeError::LoneSurrogateUnicodeEscape => {
             handler
                 .struct_span_err(span, "invalid unicode character escape")
+                .span_label(span, "invalid escape")
                 .help("unicode escape must not be a surrogate")
                 .emit();
         }
         EscapeError::OutOfRangeUnicodeEscape => {
             handler
                 .struct_span_err(span, "invalid unicode character escape")
+                .span_label(span, "invalid escape")
                 .help("unicode escape must be at most 10FFFF")
                 .emit();
         }
         EscapeError::MoreThanOneChar => {
-            let msg = if mode.is_bytes() {
-                "if you meant to write a byte string literal, use double quotes"
+            let (prefix, msg) = if mode.is_bytes() {
+                ("b", "if you meant to write a byte string literal, use double quotes")
             } else {
-                "if you meant to write a `str` literal, use double quotes"
+                ("", "if you meant to write a `str` literal, use double quotes")
             };
 
             handler
@@ -66,31 +63,44 @@ pub(crate) fn emit_unescape_error(
                 .span_suggestion(
                     span_with_quotes,
                     msg,
-                    format!("\"{}\"", lit),
+                    format!("{}\"{}\"", prefix, lit),
                     Applicability::MachineApplicable,
                 )
                 .emit();
         }
         EscapeError::EscapeOnlyChar => {
-            let (c, _span) = last_char();
+            let (c, char_span) = last_char();
 
-            let mut msg = if mode.is_bytes() {
-                "byte constant must be escaped: "
+            let msg = if mode.is_bytes() {
+                "byte constant must be escaped"
             } else {
-                "character constant must be escaped: "
-            }
-            .to_string();
-            push_escaped_char(&mut msg, c);
-
-            handler.span_err(span, msg.as_str())
+                "character constant must be escaped"
+            };
+            handler
+                .struct_span_err(span, &format!("{}: `{}`", msg, escaped_char(c)))
+                .span_suggestion(
+                    char_span,
+                    "escape the character",
+                    c.escape_default().to_string(),
+                    Applicability::MachineApplicable,
+                )
+                .emit()
         }
         EscapeError::BareCarriageReturn => {
             let msg = if mode.in_double_quotes() {
-                "bare CR not allowed in string, use \\r instead"
+                "bare CR not allowed in string, use `\\r` instead"
             } else {
-                "character constant must be escaped: \\r"
+                "character constant must be escaped: `\\r`"
             };
-            handler.span_err(span, msg);
+            handler
+                .struct_span_err(span, msg)
+                .span_suggestion(
+                    span,
+                    "escape the character",
+                    "\\r".to_string(),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
         }
         EscapeError::BareCarriageReturnInRawString => {
             assert!(mode.in_double_quotes());
@@ -102,21 +112,22 @@ pub(crate) fn emit_unescape_error(
 
             let label =
                 if mode.is_bytes() { "unknown byte escape" } else { "unknown character escape" };
-            let mut msg = label.to_string();
-            msg.push_str(": ");
-            push_escaped_char(&mut msg, c);
-
-            let mut diag = handler.struct_span_err(span, msg.as_str());
+            let ec = escaped_char(c);
+            let mut diag = handler.struct_span_err(span, &format!("{}: `{}`", label, ec));
             diag.span_label(span, label);
             if c == '{' || c == '}' && !mode.is_bytes() {
                 diag.help(
-                    "if used in a formatting string, \
-                           curly braces are escaped with `{{` and `}}`",
+                    "if used in a formatting string, curly braces are escaped with `{{` and `}}`",
                 );
             } else if c == '\r' {
                 diag.help(
-                    "this is an isolated carriage return; \
-                           consider checking your editor and version control settings",
+                    "this is an isolated carriage return; consider checking your editor and \
+                     version control settings",
+                );
+            } else {
+                diag.help(
+                    "for more information, visit \
+                     <https://static.rust-lang.org/doc/master/reference.html#literals>",
                 );
             }
             diag.emit();
@@ -127,45 +138,70 @@ pub(crate) fn emit_unescape_error(
         EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => {
             let (c, span) = last_char();
 
-            let mut msg = if error == EscapeError::InvalidCharInHexEscape {
-                "invalid character in numeric character escape: "
+            let msg = if error == EscapeError::InvalidCharInHexEscape {
+                "invalid character in numeric character escape"
             } else {
-                "invalid character in unicode escape: "
-            }
-            .to_string();
-            push_escaped_char(&mut msg, c);
+                "invalid character in unicode escape"
+            };
+            let c = escaped_char(c);
 
-            handler.span_err(span, msg.as_str())
+            handler
+                .struct_span_err(span, &format!("{}: `{}`", msg, c))
+                .span_label(span, msg)
+                .emit();
         }
         EscapeError::NonAsciiCharInByte => {
             assert!(mode.is_bytes());
-            let (_c, span) = last_char();
-            handler.span_err(
-                span,
-                "byte constant must be ASCII. \
-                                    Use a \\xHH escape for a non-ASCII byte",
-            )
+            let (c, span) = last_char();
+            handler
+                .struct_span_err(span, "non-ASCII character in byte constant")
+                .span_label(span, "byte constant must be ASCII")
+                .span_suggestion(
+                    span,
+                    "use a \\xHH escape for a non-ASCII byte",
+                    format!("\\x{:X}", c as u32),
+                    Applicability::MachineApplicable,
+                )
+                .emit();
         }
         EscapeError::NonAsciiCharInByteString => {
             assert!(mode.is_bytes());
             let (_c, span) = last_char();
-            handler.span_err(span, "raw byte string must be ASCII")
+            handler
+                .struct_span_err(span, "raw byte string must be ASCII")
+                .span_label(span, "must be ASCII")
+                .emit();
+        }
+        EscapeError::OutOfRangeHexEscape => {
+            handler
+                .struct_span_err(span, "out of range hex escape")
+                .span_label(span, "must be a character in the range [\\x00-\\x7f]")
+                .emit();
         }
-        EscapeError::OutOfRangeHexEscape => handler.span_err(
-            span,
-            "this form of character escape may only be used \
-                                    with characters in the range [\\x00-\\x7f]",
-        ),
         EscapeError::LeadingUnderscoreUnicodeEscape => {
-            let (_c, span) = last_char();
-            handler.span_err(span, "invalid start of unicode escape")
+            let (c, span) = last_char();
+            let msg = "invalid start of unicode escape";
+            handler
+                .struct_span_err(span, &format!("{}: `{}`", msg, c))
+                .span_label(span, msg)
+                .emit();
         }
         EscapeError::OverlongUnicodeEscape => {
-            handler.span_err(span, "overlong unicode escape (must have at most 6 hex digits)")
-        }
-        EscapeError::UnclosedUnicodeEscape => {
-            handler.span_err(span, "unterminated unicode escape (needed a `}`)")
+            handler
+                .struct_span_err(span, "overlong unicode escape")
+                .span_label(span, "must have at most 6 hex digits")
+                .emit();
         }
+        EscapeError::UnclosedUnicodeEscape => handler
+            .struct_span_err(span, "unterminated unicode escape")
+            .span_label(span, "missing a closing `}`")
+            .span_suggestion_verbose(
+                span.shrink_to_hi(),
+                "terminate the unicode escape",
+                "}".to_string(),
+                Applicability::MaybeIncorrect,
+            )
+            .emit(),
         EscapeError::NoBraceInUnicodeEscape => {
             let msg = "incorrect unicode escape sequence";
             let mut diag = handler.struct_span_err(span, msg);
@@ -195,28 +231,38 @@ pub(crate) fn emit_unescape_error(
 
             diag.emit();
         }
-        EscapeError::UnicodeEscapeInByte => handler.span_err(
-            span,
-            "unicode escape sequences cannot be used \
-                                    as a byte or in a byte string",
-        ),
+        EscapeError::UnicodeEscapeInByte => {
+            let msg = "unicode escape in byte string";
+            handler
+                .struct_span_err(span, msg)
+                .span_label(span, msg)
+                .help("unicode escape sequences cannot be used as a byte or in a byte string")
+                .emit();
+        }
         EscapeError::EmptyUnicodeEscape => {
-            handler.span_err(span, "empty unicode escape (must have at least 1 hex digit)")
+            handler
+                .struct_span_err(span, "empty unicode escape")
+                .span_label(span, "this escape must have at least 1 hex digit")
+                .emit();
+        }
+        EscapeError::ZeroChars => {
+            let msg = "empty character literal";
+            handler.struct_span_err(span, msg).span_label(span, msg).emit()
+        }
+        EscapeError::LoneSlash => {
+            let msg = "invalid trailing slash in literal";
+            handler.struct_span_err(span, msg).span_label(span, msg).emit();
         }
-        EscapeError::ZeroChars => handler.span_err(span, "empty character literal"),
-        EscapeError::LoneSlash => handler.span_err(span, "invalid trailing slash in literal"),
     }
 }
 
 /// Pushes a character to a message string for error reporting
-pub(crate) fn push_escaped_char(msg: &mut String, c: char) {
+pub(crate) fn escaped_char(c: char) -> String {
     match c {
         '\u{20}'..='\u{7e}' => {
             // Don't escape \, ' or " for user-facing messages
-            msg.push(c);
-        }
-        _ => {
-            msg.extend(c.escape_default());
+            c.to_string()
         }
+        _ => c.escape_default().to_string(),
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index df23b4006b3..86f8061a24a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -907,6 +907,7 @@ symbols! {
         register_attr,
         register_tool,
         relaxed_adts,
+        relaxed_struct_unsize,
         rem,
         rem_assign,
         repr,
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 3852005ee3f..e155f0366e1 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -257,13 +257,11 @@ fn predicates_reference_self(
 }
 
 fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
     tcx.associated_items(trait_def_id)
         .in_definition_order()
         .filter(|item| item.kind == ty::AssocKind::Type)
         .flat_map(|item| tcx.explicit_item_bounds(item.def_id))
-        .map(|&(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp))
-        .filter_map(|predicate| predicate_references_self(tcx, predicate))
+        .filter_map(|pred_span| predicate_references_self(tcx, *pred_span))
         .collect()
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 3015188fd44..ed3e117fcfa 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -823,33 +823,59 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     },
                 };
 
+                // FIXME(eddyb) cache this (including computing `unsizing_params`)
+                // by putting it in a query; it would only need the `DefId` as it
+                // looks at declared field types, not anything substituted.
+
                 // The last field of the structure has to exist and contain type/const parameters.
                 let (tail_field, prefix_fields) =
                     def.non_enum_variant().fields.split_last().ok_or(Unimplemented)?;
                 let tail_field_ty = tcx.type_of(tail_field.did);
 
                 let mut unsizing_params = GrowableBitSet::new_empty();
-                let mut found = false;
-                for arg in tail_field_ty.walk() {
-                    if let Some(i) = maybe_unsizing_param_idx(arg) {
-                        unsizing_params.insert(i);
-                        found = true;
+                if tcx.features().relaxed_struct_unsize {
+                    for arg in tail_field_ty.walk() {
+                        if let Some(i) = maybe_unsizing_param_idx(arg) {
+                            unsizing_params.insert(i);
+                        }
                     }
-                }
-                if !found {
-                    return Err(Unimplemented);
-                }
 
-                // Ensure none of the other fields mention the parameters used
-                // in unsizing.
-                // FIXME(eddyb) cache this (including computing `unsizing_params`)
-                // by putting it in a query; it would only need the `DefId` as it
-                // looks at declared field types, not anything substituted.
-                for field in prefix_fields {
-                    for arg in tcx.type_of(field.did).walk() {
+                    // Ensure none of the other fields mention the parameters used
+                    // in unsizing.
+                    for field in prefix_fields {
+                        for arg in tcx.type_of(field.did).walk() {
+                            if let Some(i) = maybe_unsizing_param_idx(arg) {
+                                unsizing_params.remove(i);
+                            }
+                        }
+                    }
+
+                    if unsizing_params.is_empty() {
+                        return Err(Unimplemented);
+                    }
+                } else {
+                    let mut found = false;
+                    for arg in tail_field_ty.walk() {
                         if let Some(i) = maybe_unsizing_param_idx(arg) {
-                            if unsizing_params.contains(i) {
-                                return Err(Unimplemented);
+                            unsizing_params.insert(i);
+                            found = true;
+                        }
+                    }
+                    if !found {
+                        return Err(Unimplemented);
+                    }
+
+                    // Ensure none of the other fields mention the parameters used
+                    // in unsizing.
+                    // FIXME(eddyb) cache this (including computing `unsizing_params`)
+                    // by putting it in a query; it would only need the `DefId` as it
+                    // looks at declared field types, not anything substituted.
+                    for field in prefix_fields {
+                        for arg in tcx.type_of(field.did).walk() {
+                            if let Some(i) = maybe_unsizing_param_idx(arg) {
+                                if unsizing_params.contains(i) {
+                                    return Err(Unimplemented);
+                                }
                             }
                         }
                     }
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 437813ea41b..5659345f0ff 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -112,12 +112,15 @@ pub enum SizedByDefault {
     No,
 }
 
+#[derive(Debug)]
 struct ConvertedBinding<'a, 'tcx> {
     item_name: Ident,
     kind: ConvertedBindingKind<'a, 'tcx>,
+    gen_args: &'a GenericArgs<'a>,
     span: Span,
 }
 
+#[derive(Debug)]
 enum ConvertedBindingKind<'a, 'tcx> {
     Equality(Ty<'tcx>),
     Constraint(&'a [hir::GenericBound<'a>]),
@@ -323,6 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let tcx = self.tcx();
         let generics = tcx.generics_of(def_id);
+        debug!("generics: {:?}", generics);
 
         if generics.has_self {
             if generics.parent.is_some() {
@@ -557,7 +561,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         ConvertedBindingKind::Constraint(bounds)
                     }
                 };
-                ConvertedBinding { item_name: binding.ident, kind, span: binding.span }
+                ConvertedBinding {
+                    item_name: binding.ident,
+                    kind,
+                    gen_args: binding.gen_args,
+                    span: binding.span,
+                }
             })
             .collect();
 
@@ -918,60 +927,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         dup_bindings: &mut FxHashMap<DefId, Span>,
         path_span: Span,
     ) -> Result<(), ErrorReported> {
-        let tcx = self.tcx();
-
-        if !speculative {
-            // Given something like `U: SomeTrait<T = X>`, we want to produce a
-            // predicate like `<U as SomeTrait>::T = X`. This is somewhat
-            // subtle in the event that `T` is defined in a supertrait of
-            // `SomeTrait`, because in that case we need to upcast.
-            //
-            // That is, consider this case:
-            //
-            // ```
-            // trait SubTrait: SuperTrait<i32> { }
-            // trait SuperTrait<A> { type T; }
-            //
-            // ... B: SubTrait<T = foo> ...
-            // ```
-            //
-            // We want to produce `<B as SuperTrait<i32>>::T == foo`.
-
-            // Find any late-bound regions declared in `ty` that are not
-            // declared in the trait-ref. These are not well-formed.
-            //
-            // Example:
-            //
-            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
-            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
-            if let ConvertedBindingKind::Equality(ty) = binding.kind {
-                let late_bound_in_trait_ref =
-                    tcx.collect_constrained_late_bound_regions(&trait_ref);
-                let late_bound_in_ty =
-                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
-                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
-                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+        // Given something like `U: SomeTrait<T = X>`, we want to produce a
+        // predicate like `<U as SomeTrait>::T = X`. This is somewhat
+        // subtle in the event that `T` is defined in a supertrait of
+        // `SomeTrait`, because in that case we need to upcast.
+        //
+        // That is, consider this case:
+        //
+        // ```
+        // trait SubTrait: SuperTrait<i32> { }
+        // trait SuperTrait<A> { type T; }
+        //
+        // ... B: SubTrait<T = foo> ...
+        // ```
+        //
+        // We want to produce `<B as SuperTrait<i32>>::T == foo`.
 
-                // FIXME: point at the type params that don't have appropriate lifetimes:
-                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
-                //                         ----  ----     ^^^^^^^
-                self.validate_late_bound_regions(
-                    late_bound_in_trait_ref,
-                    late_bound_in_ty,
-                    |br_name| {
-                        struct_span_err!(
-                            tcx.sess,
-                            binding.span,
-                            E0582,
-                            "binding for associated type `{}` references {}, \
-                             which does not appear in the trait input types",
-                            binding.item_name,
-                            br_name
-                        )
-                    },
-                );
-            }
-        }
+        debug!(
+            "add_predicates_for_ast_type_binding(hir_ref_id {:?}, trait_ref {:?}, binding {:?}, bounds {:?}",
+            hir_ref_id, trait_ref, binding, bounds
+        );
+        let tcx = self.tcx();
 
         let candidate =
             if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
@@ -1030,6 +1006,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .or_insert(binding.span);
         }
 
+        // Include substitutions for generic parameters of associated types
+        let projection_ty = candidate.map_bound(|trait_ref| {
+            let item_segment = hir::PathSegment {
+                ident: assoc_ty.ident,
+                hir_id: None,
+                res: None,
+                args: Some(binding.gen_args),
+                infer_args: false,
+            };
+
+            let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
+                tcx,
+                path_span,
+                assoc_ty.def_id,
+                &item_segment,
+                trait_ref.substs,
+            );
+
+            debug!(
+                "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
+                substs_trait_ref_and_assoc_item
+            );
+
+            ty::ProjectionTy {
+                item_def_id: assoc_ty.def_id,
+                substs: substs_trait_ref_and_assoc_item,
+            }
+        });
+
+        if !speculative {
+            // Find any late-bound regions declared in `ty` that are not
+            // declared in the trait-ref or assoc_ty. These are not well-formed.
+            //
+            // Example:
+            //
+            //     for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad
+            //     for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok
+            if let ConvertedBindingKind::Equality(ty) = binding.kind {
+                let late_bound_in_trait_ref =
+                    tcx.collect_constrained_late_bound_regions(&projection_ty);
+                let late_bound_in_ty =
+                    tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty));
+                debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
+                debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+
+                // FIXME: point at the type params that don't have appropriate lifetimes:
+                // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
+                //                         ----  ----     ^^^^^^^
+                self.validate_late_bound_regions(
+                    late_bound_in_trait_ref,
+                    late_bound_in_ty,
+                    |br_name| {
+                        struct_span_err!(
+                            tcx.sess,
+                            binding.span,
+                            E0582,
+                            "binding for associated type `{}` references {}, \
+                             which does not appear in the trait input types",
+                            binding.item_name,
+                            br_name
+                        )
+                    },
+                );
+            }
+        }
+
         match binding.kind {
             ConvertedBindingKind::Equality(ref ty) => {
                 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to
@@ -1037,13 +1079,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // `<T as Iterator>::Item = u32`
                 bounds.projection_bounds.push((
-                    candidate.map_bound(|trait_ref| ty::ProjectionPredicate {
-                        projection_ty: ty::ProjectionTy::from_ref_and_name(
-                            tcx,
-                            trait_ref,
-                            binding.item_name,
-                        ),
-                        ty,
+                    projection_ty.map_bound(|projection_ty| {
+                        debug!(
+                            "add_predicates_for_ast_type_binding: projection_ty {:?}, substs: {:?}",
+                            projection_ty, projection_ty.substs
+                        );
+                        ty::ProjectionPredicate { projection_ty, ty }
                     }),
                     binding.span,
                 ));
@@ -1055,7 +1096,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs);
+                let param_ty =
+                    tcx.mk_projection(assoc_ty.def_id, projection_ty.skip_binder().substs);
                 self.add_bounds(param_ty, ast_bounds, bounds);
             }
         }
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index c572c66ce32..9dc3f05dae5 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -400,7 +400,7 @@ impl Layout {
 
 #[stable(feature = "alloc_layout", since = "1.28.0")]
 #[rustc_deprecated(
-    since = "1.51.0",
+    since = "1.52.0",
     reason = "Name does not follow std convention, use LayoutError",
     suggestion = "LayoutError"
 )]
@@ -409,7 +409,7 @@ pub type LayoutErr = LayoutError;
 /// The parameters given to `Layout::from_size_align`
 /// or some other `Layout` constructor
 /// do not satisfy its documented constraints.
-#[stable(feature = "alloc_layout_error", since = "1.49.0")]
+#[stable(feature = "alloc_layout_error", since = "1.50.0")]
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct LayoutError {
     private: (),
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 045eb58d013..06a761531b6 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -11,14 +11,14 @@ pub use self::global::GlobalAlloc;
 pub use self::layout::Layout;
 #[stable(feature = "alloc_layout", since = "1.28.0")]
 #[rustc_deprecated(
-    since = "1.51.0",
+    since = "1.52.0",
     reason = "Name does not follow std convention, use LayoutError",
     suggestion = "LayoutError"
 )]
 #[allow(deprecated, deprecated_in_future)]
 pub use self::layout::LayoutErr;
 
-#[stable(feature = "alloc_layout_error", since = "1.49.0")]
+#[stable(feature = "alloc_layout_error", since = "1.50.0")]
 pub use self::layout::LayoutError;
 
 use crate::fmt;
@@ -342,7 +342,10 @@ pub unsafe trait Allocator {
     ///
     /// The returned adaptor also implements `Allocator` and will simply borrow this.
     #[inline(always)]
-    fn by_ref(&self) -> &Self {
+    fn by_ref(&self) -> &Self
+    where
+        Self: Sized,
+    {
         self
     }
 }
diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs
index 4f7cf6018d9..a8da003d550 100644
--- a/library/std/src/sys/wasi/ext/fs.rs
+++ b/library/std/src/sys/wasi/ext/fs.rs
@@ -514,3 +514,11 @@ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
         .fd()
         .symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
 }
+
+/// Create a symbolic link.
+///
+/// This is a convenience API similar to [`std::os::unix::fs::symlink`] and
+/// [`std::os::windows::fs::symlink_file`] and [`symlink_dir`](std::os::windows::fs::symlink_dir).
+pub fn symlink_path<P: AsRef<Path>, U: AsRef<Path>>(old_path: P, new_path: U) -> io::Result<()> {
+    crate::sys::fs::symlink(old_path.as_ref(), new_path.as_ref())
+}
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index f0e33be757d..d9132f20d85 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1880,8 +1880,7 @@ impl Step for RemoteCopyLibs {
         builder.info(&format!("REMOTE copy libs to emulator ({})", target));
         t!(fs::create_dir_all(builder.out.join("tmp")));
 
-        let server =
-            builder.ensure(tool::RemoteTestServer { compiler: compiler.with_stage(0), target });
+        let server = builder.ensure(tool::RemoteTestServer { compiler, target });
 
         // Spawn the emulator and wait for it to come online
         let tool = builder.tool_exe(Tool::RemoteTestClient);
diff --git a/src/ci/scripts/install-awscli.sh b/src/ci/scripts/install-awscli.sh
index f9b759fe343..3d8f0de7a39 100755
--- a/src/ci/scripts/install-awscli.sh
+++ b/src/ci/scripts/install-awscli.sh
@@ -27,7 +27,7 @@ if isLinux; then
     pip="pip3"
     pipflags="--user"
 
-    sudo apt-get install -y python3-setuptools
+    sudo apt-get install -y python3-setuptools python3-wheel
     ciCommandAddPath "${HOME}/.local/bin"
 fi
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index aa18684aea1..a20e9dec33b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -435,7 +435,7 @@ crate fn create_resolver<'a>(
 
     // Before we actually clone it, let's force all the extern'd crates to
     // actually be loaded, just in case they're only referred to inside
-    // intra-doc-links
+    // intra-doc links
     resolver.borrow_mut().access(|resolver| {
         sess.time("load_extern_crates", || {
             for extern_name in &extern_names {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 74b61f1555c..d7951961223 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1331,16 +1331,16 @@ impl clean::GenericArg {
 }
 
 crate fn display_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display {
-    WithFormatter(Cell::new(Some(f)))
-}
-
-struct WithFormatter<F>(Cell<Option<F>>);
-
-impl<F> fmt::Display for WithFormatter<F>
-where
-    F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        (self.0.take()).unwrap()(f)
+    struct WithFormatter<F>(Cell<Option<F>>);
+
+    impl<F> fmt::Display for WithFormatter<F>
+    where
+        F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+    {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            (self.0.take()).unwrap()(f)
+        }
     }
+
+    WithFormatter(Cell::new(Some(f)))
 }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b2e5c8834b8..026d8f96dee 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -154,7 +154,7 @@ impl From<clean::ItemKind> for ItemEnum {
             }
             ImportItem(i) => ItemEnum::ImportItem(i.into()),
             StructItem(s) => ItemEnum::StructItem(s.into()),
-            UnionItem(u) => ItemEnum::StructItem(u.into()),
+            UnionItem(u) => ItemEnum::UnionItem(u.into()),
             StructFieldItem(f) => ItemEnum::StructFieldItem(f.into()),
             EnumItem(e) => ItemEnum::EnumItem(e.into()),
             VariantItem(v) => ItemEnum::VariantItem(v.into()),
@@ -162,8 +162,8 @@ impl From<clean::ItemKind> for ItemEnum {
             ForeignFunctionItem(f) => ItemEnum::FunctionItem(f.into()),
             TraitItem(t) => ItemEnum::TraitItem(t.into()),
             TraitAliasItem(t) => ItemEnum::TraitAliasItem(t.into()),
-            MethodItem(m, _) => ItemEnum::MethodItem(m.into()),
-            TyMethodItem(m) => ItemEnum::MethodItem(m.into()),
+            MethodItem(m, _) => ItemEnum::MethodItem(from_function_method(m, true)),
+            TyMethodItem(m) => ItemEnum::MethodItem(from_function_method(m, false)),
             ImplItem(i) => ItemEnum::ImplItem(i.into()),
             StaticItem(s) => ItemEnum::StaticItem(s.into()),
             ForeignStaticItem(s) => ItemEnum::StaticItem(s.into()),
@@ -205,11 +205,10 @@ impl From<clean::Struct> for Struct {
     }
 }
 
-impl From<clean::Union> for Struct {
+impl From<clean::Union> for Union {
     fn from(struct_: clean::Union) -> Self {
         let clean::Union { generics, fields, fields_stripped } = struct_;
-        Struct {
-            struct_type: StructType::Union,
+        Union {
             generics: generics.into(),
             fields_stripped,
             fields: ids(fields),
@@ -435,15 +434,13 @@ impl From<clean::Impl> for Impl {
     }
 }
 
-impl From<clean::Function> for Method {
-    fn from(function: clean::Function) -> Self {
-        let clean::Function { header, decl, generics, all_types: _, ret_types: _ } = function;
-        Method {
-            decl: decl.into(),
-            generics: generics.into(),
-            header: stringify_header(&header),
-            has_body: true,
-        }
+crate fn from_function_method(function: clean::Function, has_body: bool) -> Method {
+    let clean::Function { header, decl, generics, all_types: _, ret_types: _ } = function;
+    Method {
+        decl: decl.into(),
+        generics: generics.into(),
+        header: stringify_header(&header),
+        has_body,
     }
 }
 
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index a7c875fb748..876b1b56dee 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -243,7 +243,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                     )
                 })
                 .collect(),
-            format_version: 2,
+            format_version: 3,
         };
         let mut p = self.out_path.clone();
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 002d8938f69..532a0cf9329 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -44,7 +44,7 @@ use super::span_of_attrs;
 crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
     name: "collect-intra-doc-links",
     run: collect_intra_doc_links,
-    description: "reads a crate's documentation to resolve intra-doc-links",
+    description: "resolves intra-doc links",
 };
 
 crate fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
@@ -981,7 +981,7 @@ impl LinkCollector<'_, '_> {
         let link_text =
             disambiguator.map(|d| d.display_for(path_str)).unwrap_or_else(|| path_str.to_owned());
 
-        // In order to correctly resolve intra-doc-links we need to
+        // In order to correctly resolve intra-doc links we need to
         // pick a base AST node to work from.  If the documentation for
         // this module came from an inner comment (//!) then we anchor
         // our name resolution *inside* the module.  If, on the other
diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs
index a513c2abc87..11f572560d6 100644
--- a/src/librustdoc/passes/doc_test_lints.rs
+++ b/src/librustdoc/passes/doc_test_lints.rs
@@ -1,7 +1,7 @@
 //! This pass is overloaded and runs two different lints.
 //!
-//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doc-tests
-//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doc-tests.
+//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests
+//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests.
 
 use super::{span_of_attrs, Pass};
 use crate::clean;
diff --git a/src/librustdoc/passes/non_autolinks.rs b/src/librustdoc/passes/non_autolinks.rs
index 1f411b997f8..efb5df08caf 100644
--- a/src/librustdoc/passes/non_autolinks.rs
+++ b/src/librustdoc/passes/non_autolinks.rs
@@ -12,7 +12,7 @@ use rustc_session::lint;
 crate const CHECK_NON_AUTOLINKS: Pass = Pass {
     name: "check-non-autolinks",
     run: check_non_autolinks,
-    description: "detects URLS that could be written using angle brackets",
+    description: "detects URLs that could be linkified",
 };
 
 const URL_REGEX: &str = concat!(
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index a276b7a6337..79f8562c472 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -11,7 +11,7 @@ use crate::passes::{ImplStripper, Pass};
 crate const STRIP_HIDDEN: Pass = Pass {
     name: "strip-hidden",
     run: strip_hidden,
-    description: "strips all doc(hidden) items from the output",
+    description: "strips all `#[doc(hidden)]` items from the output",
 };
 
 /// Strip items marked `#[doc(hidden)]`
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 3fb2a32d5a0..083f99e4a68 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -194,6 +194,7 @@ pub enum ItemEnum {
     },
     ImportItem(Import),
 
+    UnionItem(Union),
     StructItem(Struct),
     StructFieldItem(Type),
     EnumItem(Enum),
@@ -239,6 +240,14 @@ pub struct Module {
 }
 
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+pub struct Union {
+    pub generics: Generics,
+    pub fields_stripped: bool,
+    pub fields: Vec<Id>,
+    pub impls: Vec<Id>,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Struct {
     pub struct_type: StructType,
     pub generics: Generics,
@@ -270,7 +279,6 @@ pub enum StructType {
     Plain,
     Tuple,
     Unit,
-    Union,
 }
 
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
diff --git a/src/test/rustdoc-json/traits/has_body.rs b/src/test/rustdoc-json/traits/has_body.rs
new file mode 100644
index 00000000000..44dacb1ee75
--- /dev/null
+++ b/src/test/rustdoc-json/traits/has_body.rs
@@ -0,0 +1,21 @@
+// @has has_body.json "$.index[*][?(@.name=='Foo')]"
+pub trait Foo {
+    // @has - "$.index[*][?(@.name=='no_self')].inner.has_body" false
+    fn no_self();
+    // @has - "$.index[*][?(@.name=='move_self')].inner.has_body" false
+    fn move_self(self);
+    // @has - "$.index[*][?(@.name=='ref_self')].inner.has_body" false
+    fn ref_self(&self);
+
+    // @has - "$.index[*][?(@.name=='no_self_def')].inner.has_body" true
+    fn no_self_def() {}
+    // @has - "$.index[*][?(@.name=='move_self_def')].inner.has_body" true
+    fn move_self_def(self) {}
+    // @has - "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true
+    fn ref_self_def(&self) {}
+}
+
+pub trait Bar: Clone {
+    // @has - "$.index[*][?(@.name=='method')].inner.has_body" false
+    fn method(&self, param: usize);
+}
diff --git a/src/test/rustdoc-json/unions/union.rs b/src/test/rustdoc-json/unions/union.rs
new file mode 100644
index 00000000000..ac2eb797791
--- /dev/null
+++ b/src/test/rustdoc-json/unions/union.rs
@@ -0,0 +1,7 @@
+// @has union.json "$.index[*][?(@.name=='Union')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='Union')].kind" \"union\"
+// @!has - "$.index[*][?(@.name=='Union')].inner.struct_type"
+pub union Union {
+    int: i32,
+    float: f32,
+}
diff --git a/src/test/ui/allocator/object-safe.rs b/src/test/ui/allocator/object-safe.rs
new file mode 100644
index 00000000000..fae7ab7fe33
--- /dev/null
+++ b/src/test/ui/allocator/object-safe.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+// Check that `Allocator` is object safe, this allows for polymorphic allocators
+
+#![feature(allocator_api)]
+
+use std::alloc::{Allocator, System};
+
+fn ensure_object_safe(_: &dyn Allocator) {}
+
+fn main() {
+    ensure_object_safe(&System);
+}
diff --git a/src/test/ui/attributes/key-value-non-ascii.rs b/src/test/ui/attributes/key-value-non-ascii.rs
index 91c917e7db5..12942eabdf7 100644
--- a/src/test/ui/attributes/key-value-non-ascii.rs
+++ b/src/test/ui/attributes/key-value-non-ascii.rs
@@ -1,4 +1,4 @@
 #![feature(rustc_attrs)]
 
-#[rustc_dummy = b"ffi.rs"] //~ ERROR byte constant must be ASCII
+#[rustc_dummy = b"ffi.rs"] //~ ERROR non-ASCII character in byte constant
 fn main() {}
diff --git a/src/test/ui/attributes/key-value-non-ascii.stderr b/src/test/ui/attributes/key-value-non-ascii.stderr
index 3e082139f89..1d4b0d5b2b1 100644
--- a/src/test/ui/attributes/key-value-non-ascii.stderr
+++ b/src/test/ui/attributes/key-value-non-ascii.stderr
@@ -1,8 +1,11 @@
-error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
+error: non-ASCII character in byte constant
   --> $DIR/key-value-non-ascii.rs:3:19
    |
 LL | #[rustc_dummy = b"ffi.rs"]
    |                   ^
+   |                   |
+   |                   byte constant must be ASCII
+   |                   help: use a \xHH escape for a non-ASCII byte: `\xFB03`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
new file mode 100644
index 00000000000..0cfd0a0b978
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.rs
@@ -0,0 +1,10 @@
+// Test that we allow unsizing even if there is an unchanged param in the
+// field getting unsized.
+struct A<T, U: ?Sized + 'static>(T, B<T, U>);
+struct B<T, U: ?Sized>(T, U);
+
+fn main() {
+    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
+    let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
+    assert_eq!(y.1.1.len(), 1);
+}
diff --git a/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
new file mode 100644
index 00000000000..f62def47726
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-relaxed_struct_unsize.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
+   |
+LL |     let y: &A<[u32; 1], [u32]> = &x;
+   |            -------------------   ^^ expected slice `[u32]`, found array `[u32; 1]`
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&A<[u32; 1], [u32]>`
+              found reference `&A<[u32; 1], [u32; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs
new file mode 100644
index 00000000000..2c543455b6e
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs
@@ -0,0 +1,12 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'x>;
+}
+
+fn main() {
+  fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+    //~^ ERROR: use of undeclared lifetime name `'x`
+    //~| ERROR: binding for associated type `Y` references lifetime
+}
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
new file mode 100644
index 00000000000..1c7c107d783
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr
@@ -0,0 +1,29 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0261]: use of undeclared lifetime name `'x`
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:35
+   |
+LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+   |        -                          ^^ undeclared lifetime
+   |        |
+   |        help: consider introducing lifetime `'x` here: `<'x>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0582]: binding for associated type `Y` references lifetime `'a`, which does not appear in the trait input types
+  --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:9:33
+   |
+LL |   fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {}
+   |                                 ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0261, E0582.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
new file mode 100644
index 00000000000..2dbd1840dec
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+#![feature(associated_type_defaults)]
+
+trait Foo {
+    type A<'a> where Self: 'a;
+}
+
+struct Fooy;
+
+impl Foo for Fooy {
+    type A<'a> = &'a ();
+}
+
+#[derive(Clone)]
+struct Fooer<T>(T);
+
+impl<T> Foo for Fooer<T> {
+    type A<'x> where T: 'x = &'x ();
+}
+
+fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
+
+
+fn main() {
+  let foo = Fooer(5);
+  f(Box::new(foo));
+}
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
new file mode 100644
index 00000000000..f3769827f04
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-in-trait-path.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs
new file mode 100644
index 00000000000..cff5a21052f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.rs
@@ -0,0 +1,16 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Foo {
+    type F<'a>;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T, T1> Foo for T {
+    type F<T1> = &[u8];
+      //~^ ERROR: the name `T1` is already used for
+      //~| ERROR: missing lifetime specifier
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
new file mode 100644
index 00000000000..e83af1d0c73
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr
@@ -0,0 +1,32 @@
+error[E0403]: the name `T1` is already used for a generic parameter in this item's generic parameters
+  --> $DIR/gat-trait-path-generic-type-arg.rs:11:12
+   |
+LL | impl <T, T1> Foo for T {
+   |          -- first use of `T1`
+LL |     type F<T1> = &[u8];
+   |            ^^ already used
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-generic-type-arg.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/gat-trait-path-generic-type-arg.rs:11:18
+   |
+LL |     type F<T1> = &[u8];
+   |                  ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     type F<'a, T1> = &'a [u8];
+   |            ^^^       ^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0106, E0403.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
new file mode 100644
index 00000000000..e69e355ba48
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
@@ -0,0 +1,18 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'a>;
+    //~^ ERROR missing generics for
+    //~| ERROR missing generics for
+
+  fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t }
+}
+
+impl<T> X for T {
+  fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
+    t
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
new file mode 100644
index 00000000000..9c6e2ce3e17
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -0,0 +1,44 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-missing-lifetime.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: missing generics for associated type `X::Y`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |   type Y<'a><'a>;
+   |         ^^^^
+
+error[E0107]: missing generics for associated type `X::Y`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-missing-lifetime.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |   type Y<'a><'a>;
+   |         ^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
new file mode 100644
index 00000000000..bb1f27a17ca
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs
@@ -0,0 +1,15 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+  type Y<'a>;
+    //~^ ERROR this associated type
+    //~| ERROR this associated type
+}
+
+fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+  //~^ ERROR: lifetime in trait object type must be followed by `+`
+  //~| ERROR: parenthesized generic arguments cannot be used
+  //~| WARNING: trait objects without an explicit `dyn` are deprecated
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
new file mode 100644
index 00000000000..20cb6d88287
--- /dev/null
+++ b/src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
@@ -0,0 +1,68 @@
+error: lifetime in trait object type must be followed by `+`
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:29
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                             ^^
+
+error: parenthesized generic arguments cannot be used in associated type constraints
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:27
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                           ^^^^^
+
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gat-trait-path-parenthesised-args.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/gat-trait-path-parenthesised-args.rs:10:29
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   |                             ^^ help: use `dyn`: `dyn 'a`
+   |
+   = note: `#[warn(bare_trait_objects)]` on by default
+
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^ --
+help: add missing lifetime argument
+   |
+LL | fn foo<'a>(arg: Box<dyn X<Y('a'a) = &'a ()>>) {}
+   |                             ^^
+
+error[E0107]: this associated type takes 0 type arguments but 1 type argument was supplied
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |     type Y<'a>;
+   |  ________^-
+   | |        |
+   | |        expected 0 type arguments
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
+   | |_________________________________________- help: remove these generics
+   |
+note: associated type defined here, with 0 type parameters
+  --> $DIR/gat-trait-path-parenthesised-args.rs:5:8
+   |
+LL |   type Y<'a>;
+   |        ^
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs
new file mode 100644
index 00000000000..ff38b3e93eb
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
new file mode 100644
index 00000000000..0fbf704df76
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-67510-pass.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-67510.rs b/src/test/ui/generic-associated-types/issue-67510.rs
new file mode 100644
index 00000000000..62b22089f91
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510.rs
@@ -0,0 +1,13 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait X {
+    type Y<'a>;
+}
+
+fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+  //~^ ERROR: use of undeclared lifetime name `'a`
+  //~| ERROR: use of undeclared lifetime name `'a`
+
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67510.stderr b/src/test/ui/generic-associated-types/issue-67510.stderr
new file mode 100644
index 00000000000..12755c56974
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-67510.stderr
@@ -0,0 +1,32 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-67510.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-67510.rs:8:21
+   |
+LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |     -               ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-67510.rs:8:26
+   |
+LL | fn f(x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |     -                    ^^ undeclared lifetime
+   |     |
+   |     help: consider introducing lifetime `'a` here: `<'a>`
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/generic-associated-types/issue-68648-1.rs b/src/test/ui/generic-associated-types/issue-68648-1.rs
new file mode 100644
index 00000000000..f294b22f73c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-1.rs
@@ -0,0 +1,26 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: for<'b> Fun<F<'b> = T>>(t: T) -> T::F<'a> {
+    T::identity(t)
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68648-1.stderr b/src/test/ui/generic-associated-types/issue-68648-1.stderr
new file mode 100644
index 00000000000..322a8f9e13f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-1.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68648-1.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-68648-2.rs b/src/test/ui/generic-associated-types/issue-68648-2.rs
new file mode 100644
index 00000000000..e55bfcd4ba2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-2.rs
@@ -0,0 +1,24 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+    T::identity(())
+      //~^ ERROR: mismatched types
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68648-2.stderr b/src/test/ui/generic-associated-types/issue-68648-2.stderr
new file mode 100644
index 00000000000..b51e0bca9f7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68648-2.stderr
@@ -0,0 +1,23 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68648-2.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0308]: mismatched types
+  --> $DIR/issue-68648-2.rs:15:17
+   |
+LL | fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+   |            - this type parameter
+LL |     T::identity(())
+   |                 ^^ expected type parameter `T`, found `()`
+   |
+   = note: expected type parameter `T`
+                   found unit type `()`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.rs b/src/test/ui/generic-associated-types/issue-68649-pass.rs
new file mode 100644
index 00000000000..396315302f7
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68649-pass.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>;
+
+    fn identity<'a>(t: Self::F<'a>) -> Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = Self;
+}
+
+fn bug<'a, T: Fun<F<'a> = T>>(t: T) -> T::F<'a> {
+    T::identity(t)
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(x);
+}
diff --git a/src/test/ui/generic-associated-types/issue-68649-pass.stderr b/src/test/ui/generic-associated-types/issue-68649-pass.stderr
new file mode 100644
index 00000000000..e4a2f8d2a64
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-68649-pass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-68649-pass.rs:3:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/generic-associated-types/issue-74684-1.rs b/src/test/ui/generic-associated-types/issue-74684-1.rs
new file mode 100644
index 00000000000..a483da863ff
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-1.rs
@@ -0,0 +1,26 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>: ?Sized;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = [u8];
+}
+
+fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
+    let a = [0; 1];
+    let _x = T::identity(&a);
+      //~^ ERROR: `a` does not live long enough
+    todo!()
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(Box::new(x));
+}
diff --git a/src/test/ui/generic-associated-types/issue-74684-1.stderr b/src/test/ui/generic-associated-types/issue-74684-1.stderr
new file mode 100644
index 00000000000..651da696827
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-1.stderr
@@ -0,0 +1,27 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74684-1.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-74684-1.rs:16:26
+   |
+LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(_ : Box<T>) -> &'static T::F<'a> {
+   |        -- lifetime `'a` defined here
+LL |     let a = [0; 1];
+LL |     let _x = T::identity(&a);
+   |              ------------^^-
+   |              |           |
+   |              |           borrowed value does not live long enough
+   |              argument requires that `a` is borrowed for `'a`
+...
+LL | }
+   | - `a` dropped here while still borrowed
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/generic-associated-types/issue-74684-2.rs b/src/test/ui/generic-associated-types/issue-74684-2.rs
new file mode 100644
index 00000000000..0caf19cb030
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-2.rs
@@ -0,0 +1,26 @@
+#![feature(generic_associated_types)]
+  //~^ WARNING: the feature `generic_associated_types` is incomplete
+
+trait Fun {
+    type F<'a>: ?Sized;
+
+    fn identity<'a>(t: &'a Self::F<'a>) -> &'a Self::F<'a> { t }
+}
+
+impl <T> Fun for T {
+    type F<'a> = i32;
+}
+
+fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
+    let a = [0; 1];
+    let x = T::identity(&a);
+    todo!()
+}
+
+
+fn main() {
+    let x = 10;
+
+    bug(Box::new(x));
+      //~^ ERROR: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
+}
diff --git a/src/test/ui/generic-associated-types/issue-74684-2.stderr b/src/test/ui/generic-associated-types/issue-74684-2.stderr
new file mode 100644
index 00000000000..8c3484f9a73
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-74684-2.stderr
@@ -0,0 +1,21 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-74684-2.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
+  --> $DIR/issue-74684-2.rs:24:5
+   |
+LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
+   |                            ------------ required by this bound in `bug`
+...
+LL |     bug(Box::new(x));
+   |     ^^^ expected slice `[u8]`, found `i32`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs
new file mode 100644
index 00000000000..2b4757d8d15
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-76535.rs
@@ -0,0 +1,41 @@
+#![feature(generic_associated_types)]
+ //~^ WARNING the feature
+
+pub trait SubTrait {}
+
+pub trait SuperTrait {
+    type SubType<'a>: SubTrait;
+      //~^ ERROR missing generics for associated
+
+    fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+}
+
+pub struct SubStruct<'a> {
+    sup: &'a mut SuperStruct,
+}
+
+impl<'a> SubTrait for SubStruct<'a> {}
+
+pub struct SuperStruct {
+    value: u8,
+}
+
+impl SuperStruct {
+    pub fn new(value: u8) -> SuperStruct {
+        SuperStruct { value }
+    }
+}
+
+impl SuperTrait for SuperStruct {
+    type SubType<'a> = SubStruct<'a>;
+
+    fn get_sub<'a>(&'a mut self) -> Self::SubType<'a> {
+        SubStruct { sup: self }
+    }
+}
+
+fn main() {
+    let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+      //~^ ERROR the trait
+      //~| ERROR the trait
+}
diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr
new file mode 100644
index 00000000000..ce4875af9c0
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-76535.stderr
@@ -0,0 +1,63 @@
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-76535.rs:1:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: missing generics for associated type `SuperTrait::SubType`
+  --> $DIR/issue-76535.rs:7:10
+   |
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-76535.rs:7:10
+   |
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type SubType<'a><'a>: SubTrait;
+   |                 ^^^^
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:14
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `get_sub` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:10:37
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+...
+LL |     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+   |                                     ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:57
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `get_sub` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-76535.rs:10:37
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+...
+LL |     fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
+   |                                     ^^^^^^^^^^^^^^^^^ ...because method `get_sub` references the `Self` type in its return type
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
+   = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs
new file mode 100644
index 00000000000..26b38430dd9
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79422.rs
@@ -0,0 +1,47 @@
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+trait RefCont<'a, T> {
+    fn t(&'a self) -> &'a T;
+}
+
+impl<'a, T> RefCont<'a, T> for &'a T {
+    fn t(&'a self) -> &'a T {
+        self
+    }
+}
+
+impl<'a, T> RefCont<'a, T> for Box<T> {
+    fn t(&'a self) -> &'a T {
+        self.as_ref()
+    }
+}
+
+trait MapLike<K, V> {
+    type VRefCont<'a>: RefCont<'a, V>;
+      //~^ ERROR missing generics
+    fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+}
+
+impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
+    type VRefCont<'a> = &'a V;
+    fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
+        std::collections::BTreeMap::get(self, key)
+    }
+}
+
+struct Source;
+
+impl<K, V: Default> MapLike<K, V> for Source {
+    type VRefCont<'a> = Box<V>;
+    fn get<'a>(&self, _: &K) -> Option<Box<V>> {
+        Some(Box::new(V::default()))
+    }
+}
+
+fn main() {
+    let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
+        as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+      //~^ ERROR the trait
+      //~^^^ ERROR the trait
+}
diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr
new file mode 100644
index 00000000000..d2e12962715
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-79422.stderr
@@ -0,0 +1,54 @@
+error[E0107]: missing generics for associated type `MapLike::VRefCont`
+  --> $DIR/issue-79422.rs:21:10
+   |
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-79422.rs:21:10
+   |
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type VRefCont<'a><'a>: RefCont<'a, V>;
+   |                  ^^^^
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:44:12
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `get` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:23:38
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+...
+LL |     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
+
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:43:13
+   |
+LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `get` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-79422.rs:23:38
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+...
+LL |     fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `get` references the `Self` type in its return type
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
+   = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-80433-reduced.rs b/src/test/ui/generic-associated-types/issue-80433-reduced.rs
new file mode 100644
index 00000000000..7c1673edc51
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433-reduced.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(generic_associated_types)]
+
+struct E {}
+
+trait TestMut {
+    type Output<'a>;
+    fn test_mut(&mut self) -> Self::Output<'static>;
+}
+
+impl TestMut for E {
+    type Output<'a> = usize;
+    fn test_mut(&mut self) -> Self::Output<'static> {
+        todo!()
+    }
+}
+
+fn test_simpler<'a>(_: impl TestMut<Output<'a> = usize>) {}
+
+fn main() {
+    test_simpler(E {});
+}
diff --git a/src/test/ui/generic-associated-types/issue-80433.rs b/src/test/ui/generic-associated-types/issue-80433.rs
new file mode 100644
index 00000000000..ea65f05de23
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433.rs
@@ -0,0 +1,35 @@
+#![feature(generic_associated_types)]
+#![allow(incomplete_features)]
+
+#[derive(Default)]
+struct E<T> {
+    data: T,
+}
+
+trait TestMut {
+    type Output<'a>;
+      //~^ ERROR missing generics
+    fn test_mut<'a>(&'a mut self) -> Self::Output<'a>;
+}
+
+impl<T> TestMut for E<T>
+where
+    T: 'static,
+{
+    type Output<'a> = &'a mut T;
+    fn test_mut<'a>(&'a mut self) -> Self::Output<'a> {
+        &mut self.data
+    }
+}
+
+fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>)
+{
+    for n in 0i16..100 {
+        *dst.test_mut() = n.into();
+    }
+}
+
+fn main() {
+    let mut t1: E<f32> = Default::default();
+    test_simpler(&mut t1);
+}
diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr
new file mode 100644
index 00000000000..5398920fafd
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-80433.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for associated type `TestMut::Output`
+  --> $DIR/issue-80433.rs:10:10
+   |
+LL |     type Output<'a>;
+   |          ^^^^^^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/issue-80433.rs:10:10
+   |
+LL |     type Output<'a>;
+   |          ^^^^^^ --
+help: use angle brackets to add missing lifetime argument
+   |
+LL |     type Output<'a><'a>;
+   |                ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
index e203a5e0d2d..2d38770bcdf 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
+++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs
@@ -1,10 +1,14 @@
 #![feature(generic_associated_types)]
+  //~^ the feature `generic_associated_types` is incomplete
 
 trait X {
     type Y<'a>;
+      //~^ ERROR this associated type
+      //~| ERROR this associated type
 }
 
 const _: () = {
   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
-      //~^  ERROR: generic associated types in trait paths are currently not implemented
 };
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
index e59a72a99ee..60b8fb9bcaa 100644
--- a/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
+++ b/src/test/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr
@@ -1,8 +1,49 @@
-error: generic associated types in trait paths are currently not implemented
-  --> $DIR/trait-path-type-error-once-implemented.rs:8:30
+warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-path-type-error-once-implemented.rs:1:12
    |
-LL |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
-   |                              ^^^
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
+
+error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^ expected 1 lifetime argument
+   |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^ --
+help: add missing lifetime argument
+   |
+LL |   fn f2<'a>(arg : Box<dyn X<Y<'a1> = &'a ()>>) {}
+   |                               ^^
+
+error[E0107]: this associated type takes 0 const arguments but 1 const argument was supplied
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |       type Y<'a>;
+   |  __________^-
+   | |          |
+   | |          expected 0 const arguments
+LL | |
+LL | |
+LL | | }
+LL | |
+LL | | const _: () = {
+LL | |   fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {}
+   | |________________________________- help: remove these generics
+   |
+note: associated type defined here, with 0 const parameters
+  --> $DIR/trait-path-type-error-once-implemented.rs:5:10
+   |
+LL |     type Y<'a>;
+   |          ^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs
deleted file mode 100644
index 02d53d5faee..00000000000
--- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(generic_associated_types)]
-
-trait X {
-    type Y<'a>;
-}
-
-const _: () = {
-  fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
-      //~^  ERROR: generic associated types in trait paths are currently not implemented
-};
-
-const _: () = {
-  fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
-      //~^  ERROR: lifetime in trait object type must be followed by `+`
-};
-
-fn main() {}
diff --git a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr b/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr
deleted file mode 100644
index 1fba9cebd24..00000000000
--- a/src/test/ui/generic-associated-types/parse/trait-path-unimplemented.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: lifetime in trait object type must be followed by `+`
-  --> $DIR/trait-path-unimplemented.rs:13:31
-   |
-LL |   fn f1<'a>(arg : Box<dyn X<Y('a) = &'a ()>>) {}
-   |                               ^^
-
-error: generic associated types in trait paths are currently not implemented
-  --> $DIR/trait-path-unimplemented.rs:8:30
-   |
-LL |   fn f1<'a>(arg : Box<dyn X<Y<'a> = &'a ()>>) {}
-   |                              ^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/parser/ascii-only-character-escape.rs b/src/test/ui/parser/ascii-only-character-escape.rs
index 20d3edf1251..725c8ad2351 100644
--- a/src/test/ui/parser/ascii-only-character-escape.rs
+++ b/src/test/ui/parser/ascii-only-character-escape.rs
@@ -1,6 +1,6 @@
 fn main() {
-    let x = "\x80"; //~ ERROR may only be used
-    let y = "\xff"; //~ ERROR may only be used
-    let z = "\xe2"; //~ ERROR may only be used
+    let x = "\x80"; //~ ERROR out of range hex escape
+    let y = "\xff"; //~ ERROR out of range hex escape
+    let z = "\xe2"; //~ ERROR out of range hex escape
     let a = b"\x00e2";  // ok because byte literal
 }
diff --git a/src/test/ui/parser/ascii-only-character-escape.stderr b/src/test/ui/parser/ascii-only-character-escape.stderr
index cf51b00cdc3..b599b35f4b3 100644
--- a/src/test/ui/parser/ascii-only-character-escape.stderr
+++ b/src/test/ui/parser/ascii-only-character-escape.stderr
@@ -1,20 +1,20 @@
-error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+error: out of range hex escape
   --> $DIR/ascii-only-character-escape.rs:2:14
    |
 LL |     let x = "\x80";
-   |              ^^^^
+   |              ^^^^ must be a character in the range [\x00-\x7f]
 
-error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+error: out of range hex escape
   --> $DIR/ascii-only-character-escape.rs:3:14
    |
 LL |     let y = "\xff";
-   |              ^^^^
+   |              ^^^^ must be a character in the range [\x00-\x7f]
 
-error: this form of character escape may only be used with characters in the range [\x00-\x7f]
+error: out of range hex escape
   --> $DIR/ascii-only-character-escape.rs:4:14
    |
 LL |     let z = "\xe2";
-   |              ^^^^
+   |              ^^^^ must be a character in the range [\x00-\x7f]
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/bad-char-literals.rs b/src/test/ui/parser/bad-char-literals.rs
index 11696b82bc9..748b4a22253 100644
--- a/src/test/ui/parser/bad-char-literals.rs
+++ b/src/test/ui/parser/bad-char-literals.rs
@@ -4,17 +4,17 @@
 fn main() {
     // these literals are just silly.
     ''';
-    //~^ ERROR: character constant must be escaped: '
+    //~^ ERROR: character constant must be escaped: `'`
 
     // note that this is a literal "\n" byte
     '
 ';
-    //~^^ ERROR: character constant must be escaped: \n
+    //~^^ ERROR: character constant must be escaped: `\n`
 
     // note that this is a literal "\r" byte
-    '
'; //~ ERROR: character constant must be escaped: \r
+    '
'; //~ ERROR: character constant must be escaped: `\r`
 
     // note that this is a literal tab character here
     '	';
-    //~^ ERROR: character constant must be escaped: \t
+    //~^ ERROR: character constant must be escaped: `\t`
 }
diff --git a/src/test/ui/parser/bad-char-literals.stderr b/src/test/ui/parser/bad-char-literals.stderr
index 093978fd84d..a22ddbac1b9 100644
--- a/src/test/ui/parser/bad-char-literals.stderr
+++ b/src/test/ui/parser/bad-char-literals.stderr
@@ -1,28 +1,28 @@
-error: character constant must be escaped: '
+error: character constant must be escaped: `'`
   --> $DIR/bad-char-literals.rs:6:6
    |
 LL |     ''';
-   |      ^
+   |      ^ help: escape the character: `\'`
 
-error: character constant must be escaped: \n
+error: character constant must be escaped: `\n`
   --> $DIR/bad-char-literals.rs:10:6
    |
 LL |       '
    |  ______^
 LL | | ';
-   | |_
+   | |_ help: escape the character: `\n`
 
-error: character constant must be escaped: \r
+error: character constant must be escaped: `\r`
   --> $DIR/bad-char-literals.rs:15:6
    |
 LL |     '
';
-   |      ^
+   |      ^ help: escape the character: `\r`
 
-error: character constant must be escaped: \t
+error: character constant must be escaped: `\t`
   --> $DIR/bad-char-literals.rs:18:6
    |
 LL |     '    ';
-   |      ^^^^
+   |      ^^^^ help: escape the character: `\t`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/byte-literals.rs b/src/test/ui/parser/byte-literals.rs
index 9683a83e720..05a510b24a7 100644
--- a/src/test/ui/parser/byte-literals.rs
+++ b/src/test/ui/parser/byte-literals.rs
@@ -4,9 +4,9 @@ static FOO: u8 = b'\f';  //~ ERROR unknown byte escape
 
 pub fn main() {
     b'\f';  //~ ERROR unknown byte escape
-    b'\x0Z';  //~ ERROR invalid character in numeric character escape: Z
+    b'\x0Z';  //~ ERROR invalid character in numeric character escape: `Z`
     b'	';  //~ ERROR byte constant must be escaped
     b''';  //~ ERROR byte constant must be escaped
-    b'é';  //~ ERROR byte constant must be ASCII
+    b'é';  //~ ERROR non-ASCII character in byte constant
     b'a  //~ ERROR unterminated byte constant [E0763]
 }
diff --git a/src/test/ui/parser/byte-literals.stderr b/src/test/ui/parser/byte-literals.stderr
index 7bbdc07cd83..55be113e16b 100644
--- a/src/test/ui/parser/byte-literals.stderr
+++ b/src/test/ui/parser/byte-literals.stderr
@@ -1,38 +1,45 @@
-error: unknown byte escape: f
+error: unknown byte escape: `f`
   --> $DIR/byte-literals.rs:3:21
    |
 LL | static FOO: u8 = b'\f';
    |                     ^ unknown byte escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
-error: unknown byte escape: f
+error: unknown byte escape: `f`
   --> $DIR/byte-literals.rs:6:8
    |
 LL |     b'\f';
    |        ^ unknown byte escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
-error: invalid character in numeric character escape: Z
+error: invalid character in numeric character escape: `Z`
   --> $DIR/byte-literals.rs:7:10
    |
 LL |     b'\x0Z';
-   |          ^
+   |          ^ invalid character in numeric character escape
 
-error: byte constant must be escaped: \t
+error: byte constant must be escaped: `\t`
   --> $DIR/byte-literals.rs:8:7
    |
 LL |     b'    ';
-   |       ^^^^
+   |       ^^^^ help: escape the character: `\t`
 
-error: byte constant must be escaped: '
+error: byte constant must be escaped: `'`
   --> $DIR/byte-literals.rs:9:7
    |
 LL |     b''';
-   |       ^
+   |       ^ help: escape the character: `\'`
 
-error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
+error: non-ASCII character in byte constant
   --> $DIR/byte-literals.rs:10:7
    |
 LL |     b'é';
    |       ^
+   |       |
+   |       byte constant must be ASCII
+   |       help: use a \xHH escape for a non-ASCII byte: `\xE9`
 
 error[E0763]: unterminated byte constant
   --> $DIR/byte-literals.rs:11:6
diff --git a/src/test/ui/parser/byte-string-literals.rs b/src/test/ui/parser/byte-string-literals.rs
index caffd9efbed..b1f11024a7b 100644
--- a/src/test/ui/parser/byte-string-literals.rs
+++ b/src/test/ui/parser/byte-string-literals.rs
@@ -2,7 +2,8 @@ static FOO: &'static [u8] = b"\f";  //~ ERROR unknown byte escape
 
 pub fn main() {
     b"\f";  //~ ERROR unknown byte escape
-    b"\x0Z";  //~ ERROR invalid character in numeric character escape: Z
-    b"é";  //~ ERROR byte constant must be ASCII
+    b"\x0Z";  //~ ERROR invalid character in numeric character escape: `Z`
+    b"é";  //~ ERROR non-ASCII character in byte constant
+    br##"é"##;  //~ ERROR raw byte string must be ASCII
     b"a  //~ ERROR unterminated double quote byte string
 }
diff --git a/src/test/ui/parser/byte-string-literals.stderr b/src/test/ui/parser/byte-string-literals.stderr
index 9be90644147..3a5a8b331d3 100644
--- a/src/test/ui/parser/byte-string-literals.stderr
+++ b/src/test/ui/parser/byte-string-literals.stderr
@@ -1,35 +1,48 @@
-error: unknown byte escape: f
+error: unknown byte escape: `f`
   --> $DIR/byte-string-literals.rs:1:32
    |
 LL | static FOO: &'static [u8] = b"\f";
    |                                ^ unknown byte escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
-error: unknown byte escape: f
+error: unknown byte escape: `f`
   --> $DIR/byte-string-literals.rs:4:8
    |
 LL |     b"\f";
    |        ^ unknown byte escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
-error: invalid character in numeric character escape: Z
+error: invalid character in numeric character escape: `Z`
   --> $DIR/byte-string-literals.rs:5:10
    |
 LL |     b"\x0Z";
-   |          ^
+   |          ^ invalid character in numeric character escape
 
-error: byte constant must be ASCII. Use a \xHH escape for a non-ASCII byte
+error: non-ASCII character in byte constant
   --> $DIR/byte-string-literals.rs:6:7
    |
 LL |     b"é";
    |       ^
+   |       |
+   |       byte constant must be ASCII
+   |       help: use a \xHH escape for a non-ASCII byte: `\xE9`
+
+error: raw byte string must be ASCII
+  --> $DIR/byte-string-literals.rs:7:10
+   |
+LL |     br##"é"##;
+   |          ^ must be ASCII
 
 error[E0766]: unterminated double quote byte string
-  --> $DIR/byte-string-literals.rs:7:6
+  --> $DIR/byte-string-literals.rs:8:6
    |
 LL |       b"a
    |  ______^
 LL | | }
    | |__^
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0766`.
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.rs b/src/test/ui/parser/issue-23620-invalid-escapes.rs
index ab445a93294..c1355f0d6fe 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.rs
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.rs
@@ -1,9 +1,9 @@
 fn main() {
     let _ = b"\u{a66e}";
-    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+    //~^ ERROR unicode escape in byte string
 
     let _ = b'\u{a66e}';
-    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
+    //~^ ERROR unicode escape in byte string
 
     let _ = b'\u';
     //~^ ERROR incorrect unicode escape sequence
@@ -12,21 +12,21 @@ fn main() {
     //~^ ERROR numeric character escape is too short
 
     let _ = b'\xxy';
-    //~^ ERROR invalid character in numeric character escape: x
+    //~^ ERROR invalid character in numeric character escape: `x`
 
     let _ = '\x5';
     //~^ ERROR numeric character escape is too short
 
     let _ = '\xxy';
-    //~^ ERROR invalid character in numeric character escape: x
+    //~^ ERROR invalid character in numeric character escape: `x`
 
     let _ = b"\u{a4a4} \xf \u";
-    //~^ ERROR unicode escape sequences cannot be used as a byte or in a byte string
-    //~^^ ERROR invalid character in numeric character escape:
+    //~^ ERROR unicode escape in byte string
+    //~^^ ERROR invalid character in numeric character escape: ` `
     //~^^^ ERROR incorrect unicode escape sequence
 
     let _ = "\xf \u";
-    //~^ ERROR invalid character in numeric character escape:
+    //~^ ERROR invalid character in numeric character escape: ` `
     //~^^ ERROR incorrect unicode escape sequence
 
     let _ = "\u8f";
diff --git a/src/test/ui/parser/issue-23620-invalid-escapes.stderr b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
index 8c924ad0330..88d97c795fc 100644
--- a/src/test/ui/parser/issue-23620-invalid-escapes.stderr
+++ b/src/test/ui/parser/issue-23620-invalid-escapes.stderr
@@ -1,14 +1,18 @@
-error: unicode escape sequences cannot be used as a byte or in a byte string
+error: unicode escape in byte string
   --> $DIR/issue-23620-invalid-escapes.rs:2:15
    |
 LL |     let _ = b"\u{a66e}";
-   |               ^^^^^^^^
+   |               ^^^^^^^^ unicode escape in byte string
+   |
+   = help: unicode escape sequences cannot be used as a byte or in a byte string
 
-error: unicode escape sequences cannot be used as a byte or in a byte string
+error: unicode escape in byte string
   --> $DIR/issue-23620-invalid-escapes.rs:5:15
    |
 LL |     let _ = b'\u{a66e}';
-   |               ^^^^^^^^
+   |               ^^^^^^^^ unicode escape in byte string
+   |
+   = help: unicode escape sequences cannot be used as a byte or in a byte string
 
 error: incorrect unicode escape sequence
   --> $DIR/issue-23620-invalid-escapes.rs:8:15
@@ -24,11 +28,11 @@ error: numeric character escape is too short
 LL |     let _ = b'\x5';
    |               ^^^
 
-error: invalid character in numeric character escape: x
+error: invalid character in numeric character escape: `x`
   --> $DIR/issue-23620-invalid-escapes.rs:14:17
    |
 LL |     let _ = b'\xxy';
-   |                 ^
+   |                 ^ invalid character in numeric character escape
 
 error: numeric character escape is too short
   --> $DIR/issue-23620-invalid-escapes.rs:17:14
@@ -36,23 +40,25 @@ error: numeric character escape is too short
 LL |     let _ = '\x5';
    |              ^^^
 
-error: invalid character in numeric character escape: x
+error: invalid character in numeric character escape: `x`
   --> $DIR/issue-23620-invalid-escapes.rs:20:16
    |
 LL |     let _ = '\xxy';
-   |                ^
+   |                ^ invalid character in numeric character escape
 
-error: unicode escape sequences cannot be used as a byte or in a byte string
+error: unicode escape in byte string
   --> $DIR/issue-23620-invalid-escapes.rs:23:15
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
-   |               ^^^^^^^^
+   |               ^^^^^^^^ unicode escape in byte string
+   |
+   = help: unicode escape sequences cannot be used as a byte or in a byte string
 
-error: invalid character in numeric character escape:  
+error: invalid character in numeric character escape: ` `
   --> $DIR/issue-23620-invalid-escapes.rs:23:27
    |
 LL |     let _ = b"\u{a4a4} \xf \u";
-   |                           ^
+   |                           ^ invalid character in numeric character escape
 
 error: incorrect unicode escape sequence
   --> $DIR/issue-23620-invalid-escapes.rs:23:28
@@ -62,11 +68,11 @@ LL |     let _ = b"\u{a4a4} \xf \u";
    |
    = help: format of unicode escape sequences is `\u{...}`
 
-error: invalid character in numeric character escape:  
+error: invalid character in numeric character escape: ` `
   --> $DIR/issue-23620-invalid-escapes.rs:28:17
    |
 LL |     let _ = "\xf \u";
-   |                 ^
+   |                 ^ invalid character in numeric character escape
 
 error: incorrect unicode escape sequence
   --> $DIR/issue-23620-invalid-escapes.rs:28:18
diff --git a/src/test/ui/parser/issue-43692.stderr b/src/test/ui/parser/issue-43692.stderr
index 69a54af3d82..baf99803517 100644
--- a/src/test/ui/parser/issue-43692.stderr
+++ b/src/test/ui/parser/issue-43692.stderr
@@ -1,8 +1,8 @@
-error: invalid start of unicode escape
+error: invalid start of unicode escape: `_`
   --> $DIR/issue-43692.rs:2:9
    |
 LL |     '\u{_10FFFF}';
-   |         ^
+   |         ^ invalid start of unicode escape
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-62913.stderr b/src/test/ui/parser/issue-62913.stderr
index f72174f8929..6f385e8dc17 100644
--- a/src/test/ui/parser/issue-62913.stderr
+++ b/src/test/ui/parser/issue-62913.stderr
@@ -10,7 +10,7 @@ error: invalid trailing slash in literal
   --> $DIR/issue-62913.rs:1:5
    |
 LL | "\u\"
-   |     ^
+   |     ^ invalid trailing slash in literal
 
 error: expected item, found `"\u\"`
   --> $DIR/issue-62913.rs:1:1
diff --git a/src/test/ui/parser/issue-64732.stderr b/src/test/ui/parser/issue-64732.stderr
index 3b00ffc8f6c..ac042580962 100644
--- a/src/test/ui/parser/issue-64732.stderr
+++ b/src/test/ui/parser/issue-64732.stderr
@@ -1,13 +1,13 @@
 error: character literal may only contain one codepoint
-  --> $DIR/issue-64732.rs:3:17
+  --> $DIR/issue-64732.rs:3:16
    |
 LL |     let _foo = b'hello\0';
-   |                 ^^^^^^^^^
+   |                ^^^^^^^^^^
    |
 help: if you meant to write a byte string literal, use double quotes
    |
 LL |     let _foo = b"hello\0";
-   |                 ^^^^^^^^^
+   |                ^^^^^^^^^^
 
 error: character literal may only contain one codepoint
   --> $DIR/issue-64732.rs:6:16
diff --git a/src/test/ui/parser/lex-bad-char-literals-1.stderr b/src/test/ui/parser/lex-bad-char-literals-1.stderr
index fcf4802f79b..ed129a1d133 100644
--- a/src/test/ui/parser/lex-bad-char-literals-1.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-1.stderr
@@ -10,17 +10,21 @@ error: numeric character escape is too short
 LL |     "\x1"
    |      ^^^
 
-error: unknown character escape: \u{25cf}
+error: unknown character escape: `\u{25cf}`
   --> $DIR/lex-bad-char-literals-1.rs:10:7
    |
 LL |     '\●'
    |       ^ unknown character escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
-error: unknown character escape: \u{25cf}
+error: unknown character escape: `\u{25cf}`
   --> $DIR/lex-bad-char-literals-1.rs:14:7
    |
 LL |     "\●"
    |       ^ unknown character escape
+   |
+   = help: for more information, visit <https://static.rust-lang.org/doc/master/reference.html#literals>
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.rs b/src/test/ui/parser/lex-bad-char-literals-7.rs
index 1580157210e..c675df2f3cc 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-7.rs
@@ -2,7 +2,7 @@ fn main() {
     let _: char = '';
     //~^ ERROR: empty character literal
     let _: char = '\u{}';
-    //~^ ERROR: empty unicode escape (must have at least 1 hex digit)
+    //~^ ERROR: empty unicode escape
 
     // Next two are OK, but may befool error recovery
     let _ = '/';
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr
index 70ee8087b51..255b9c68999 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-7.stderr
@@ -2,13 +2,13 @@ error: empty character literal
   --> $DIR/lex-bad-char-literals-7.rs:2:20
    |
 LL |     let _: char = '';
-   |                    ^
+   |                    ^ empty character literal
 
-error: empty unicode escape (must have at least 1 hex digit)
+error: empty unicode escape
   --> $DIR/lex-bad-char-literals-7.rs:4:20
    |
 LL |     let _: char = '\u{}';
-   |                    ^^^^
+   |                    ^^^^ this escape must have at least 1 hex digit
 
 error[E0762]: unterminated character literal
   --> $DIR/lex-bad-char-literals-7.rs:11:13
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
index 9a9f9c433e1..b7752e1f0c4 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.rs
@@ -22,5 +22,5 @@ fn main() {
     let _s = r"bar
foo"; //~ ERROR: bare CR not allowed in raw string
 
     // the following string literal has a bare CR in it
-    let _s = "foo\
bar"; //~ ERROR: unknown character escape: \r
+    let _s = "foo\
bar"; //~ ERROR: unknown character escape: `\r`
 }
diff --git a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
index 598da6b9307..1a21fed63bd 100644
--- a/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
+++ b/src/test/ui/parser/lex-bare-cr-string-literal-doc-comment.stderr
@@ -22,11 +22,11 @@ error: bare CR not allowed in block doc-comment
 LL |     /*! block doc comment with bare CR: '
' */
    |                                          ^
 
-error: bare CR not allowed in string, use \r instead
+error: bare CR not allowed in string, use `\r` instead
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:19:18
    |
 LL |     let _s = "foo
bar";
-   |                  ^
+   |                  ^ help: escape the character: `\r`
 
 error: bare CR not allowed in raw string
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:22:19
@@ -34,7 +34,7 @@ error: bare CR not allowed in raw string
 LL |     let _s = r"bar
foo";
    |                   ^
 
-error: unknown character escape: \r
+error: unknown character escape: `\r`
   --> $DIR/lex-bare-cr-string-literal-doc-comment.rs:25:19
    |
 LL |     let _s = "foo\
bar";
diff --git a/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr b/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr
index d20eb0fb30a..e874f62497e 100644
--- a/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr
+++ b/src/test/ui/parser/macro/literals-are-validated-before-expansion.stderr
@@ -2,7 +2,7 @@ error: invalid unicode character escape
   --> $DIR/literals-are-validated-before-expansion.rs:6:20
    |
 LL |     black_hole! { '\u{FFFFFF}' }
-   |                    ^^^^^^^^^^
+   |                    ^^^^^^^^^^ invalid escape
    |
    = help: unicode escape must be at most 10FFFF
 
@@ -10,7 +10,7 @@ error: invalid unicode character escape
   --> $DIR/literals-are-validated-before-expansion.rs:8:39
    |
 LL |     black_hole! { "this is surrogate: \u{DAAA}" }
-   |                                       ^^^^^^^^
+   |                                       ^^^^^^^^ invalid escape
    |
    = help: unicode escape must not be a surrogate
 
diff --git a/src/test/ui/parser/new-unicode-escapes-1.rs b/src/test/ui/parser/new-unicode-escapes-1.rs
index 0e1421214d9..d6a54660ea6 100644
--- a/src/test/ui/parser/new-unicode-escapes-1.rs
+++ b/src/test/ui/parser/new-unicode-escapes-1.rs
@@ -1,3 +1,3 @@
 pub fn main() {
-    let s = "\u{2603"; //~ ERROR unterminated unicode escape (needed a `}`)
+    let s = "\u{2603"; //~ ERROR unterminated unicode escape
 }
diff --git a/src/test/ui/parser/new-unicode-escapes-1.stderr b/src/test/ui/parser/new-unicode-escapes-1.stderr
index 22d6a0981ff..1ffdc0401e5 100644
--- a/src/test/ui/parser/new-unicode-escapes-1.stderr
+++ b/src/test/ui/parser/new-unicode-escapes-1.stderr
@@ -1,8 +1,13 @@
-error: unterminated unicode escape (needed a `}`)
+error: unterminated unicode escape
   --> $DIR/new-unicode-escapes-1.rs:2:14
    |
 LL |     let s = "\u{2603";
-   |              ^^^^^^^
+   |              ^^^^^^^ missing a closing `}`
+   |
+help: terminate the unicode escape
+   |
+LL |     let s = "\u{2603}";
+   |                     ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/new-unicode-escapes-2.rs b/src/test/ui/parser/new-unicode-escapes-2.rs
index b30b3dbf903..cbb614c19c0 100644
--- a/src/test/ui/parser/new-unicode-escapes-2.rs
+++ b/src/test/ui/parser/new-unicode-escapes-2.rs
@@ -1,3 +1,3 @@
 pub fn main() {
-    let s = "\u{260311111111}"; //~ ERROR overlong unicode escape (must have at most 6 hex digits)
+    let s = "\u{260311111111}"; //~ ERROR overlong unicode escape
 }
diff --git a/src/test/ui/parser/new-unicode-escapes-2.stderr b/src/test/ui/parser/new-unicode-escapes-2.stderr
index b5148279c74..2f3f8c0f9da 100644
--- a/src/test/ui/parser/new-unicode-escapes-2.stderr
+++ b/src/test/ui/parser/new-unicode-escapes-2.stderr
@@ -1,8 +1,8 @@
-error: overlong unicode escape (must have at most 6 hex digits)
+error: overlong unicode escape
   --> $DIR/new-unicode-escapes-2.rs:2:14
    |
 LL |     let s = "\u{260311111111}";
-   |              ^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^ must have at most 6 hex digits
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/new-unicode-escapes-3.stderr b/src/test/ui/parser/new-unicode-escapes-3.stderr
index 361698467f9..f5a0f8fc785 100644
--- a/src/test/ui/parser/new-unicode-escapes-3.stderr
+++ b/src/test/ui/parser/new-unicode-escapes-3.stderr
@@ -2,7 +2,7 @@ error: invalid unicode character escape
   --> $DIR/new-unicode-escapes-3.rs:2:15
    |
 LL |     let s1 = "\u{d805}";
-   |               ^^^^^^^^
+   |               ^^^^^^^^ invalid escape
    |
    = help: unicode escape must not be a surrogate
 
@@ -10,7 +10,7 @@ error: invalid unicode character escape
   --> $DIR/new-unicode-escapes-3.rs:3:15
    |
 LL |     let s2 = "\u{ffffff}";
-   |               ^^^^^^^^^^
+   |               ^^^^^^^^^^ invalid escape
    |
    = help: unicode escape must be at most 10FFFF
 
diff --git a/src/test/ui/parser/new-unicode-escapes-4.rs b/src/test/ui/parser/new-unicode-escapes-4.rs
index 9ac03cedc3f..79882713e59 100644
--- a/src/test/ui/parser/new-unicode-escapes-4.rs
+++ b/src/test/ui/parser/new-unicode-escapes-4.rs
@@ -1,4 +1,4 @@
 pub fn main() {
     let s = "\u{lol}";
-     //~^ ERROR invalid character in unicode escape: l
+     //~^ ERROR invalid character in unicode escape: `l`
 }
diff --git a/src/test/ui/parser/new-unicode-escapes-4.stderr b/src/test/ui/parser/new-unicode-escapes-4.stderr
index a35c5f0f216..514591af17e 100644
--- a/src/test/ui/parser/new-unicode-escapes-4.stderr
+++ b/src/test/ui/parser/new-unicode-escapes-4.stderr
@@ -1,8 +1,8 @@
-error: invalid character in unicode escape: l
+error: invalid character in unicode escape: `l`
   --> $DIR/new-unicode-escapes-4.rs:2:17
    |
 LL |     let s = "\u{lol}";
-   |                 ^
+   |                 ^ invalid character in unicode escape
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/raw/raw-byte-string-literals.stderr b/src/test/ui/parser/raw/raw-byte-string-literals.stderr
index 4076fe334e6..cfc877104bd 100644
--- a/src/test/ui/parser/raw/raw-byte-string-literals.stderr
+++ b/src/test/ui/parser/raw/raw-byte-string-literals.stderr
@@ -8,7 +8,7 @@ error: raw byte string must be ASCII
   --> $DIR/raw-byte-string-literals.rs:5:8
    |
 LL |     br"é";
-   |        ^
+   |        ^ must be ASCII
 
 error: found invalid character; only `#` is allowed in raw string delimitation: ~
   --> $DIR/raw-byte-string-literals.rs:6:5
diff --git a/src/test/ui/parser/trailing-carriage-return-in-string.rs b/src/test/ui/parser/trailing-carriage-return-in-string.rs
index 8abf2624e4f..5d3c3194406 100644
--- a/src/test/ui/parser/trailing-carriage-return-in-string.rs
+++ b/src/test/ui/parser/trailing-carriage-return-in-string.rs
@@ -8,7 +8,7 @@ fn main() {
  a test";
     // \r only
     let bad = "This is \
 a test";
-    //~^ ERROR unknown character escape: \r
-    //~^^ HELP this is an isolated carriage return
+    //~^ ERROR unknown character escape: `\r`
+    //~| HELP this is an isolated carriage return
 
 }
diff --git a/src/test/ui/parser/trailing-carriage-return-in-string.stderr b/src/test/ui/parser/trailing-carriage-return-in-string.stderr
index 3687b9dd282..8a44e02707c 100644
--- a/src/test/ui/parser/trailing-carriage-return-in-string.stderr
+++ b/src/test/ui/parser/trailing-carriage-return-in-string.stderr
@@ -1,4 +1,4 @@
-error: unknown character escape: \r
+error: unknown character escape: `\r`
   --> $DIR/trailing-carriage-return-in-string.rs:10:25
    |
 LL |     let bad = "This is \
 a test";
diff --git a/src/test/ui/parser/wrong-escape-of-curly-braces.rs b/src/test/ui/parser/wrong-escape-of-curly-braces.rs
index 7a5c27afca5..8e5258acd49 100644
--- a/src/test/ui/parser/wrong-escape-of-curly-braces.rs
+++ b/src/test/ui/parser/wrong-escape-of-curly-braces.rs
@@ -1,8 +1,8 @@
 fn main() {
     let ok = "{{everything fine}}";
     let bad = "\{it is wrong\}";
-    //~^  ERROR unknown character escape: {
-    //~^^  HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
-    //~^^^ ERROR unknown character escape: }
-    //~^^^^  HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
+    //~^  ERROR unknown character escape: `{`
+    //~|  HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
+    //~| ERROR unknown character escape: `}`
+    //~| HELP if used in a formatting string, curly braces are escaped with `{{` and `}}`
 }
diff --git a/src/test/ui/parser/wrong-escape-of-curly-braces.stderr b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr
index 1406b795ba8..ff1a2fb0f3c 100644
--- a/src/test/ui/parser/wrong-escape-of-curly-braces.stderr
+++ b/src/test/ui/parser/wrong-escape-of-curly-braces.stderr
@@ -1,4 +1,4 @@
-error: unknown character escape: {
+error: unknown character escape: `{`
   --> $DIR/wrong-escape-of-curly-braces.rs:3:17
    |
 LL |     let bad = "\{it is wrong\}";
@@ -6,7 +6,7 @@ LL |     let bad = "\{it is wrong\}";
    |
    = help: if used in a formatting string, curly braces are escaped with `{{` and `}}`
 
-error: unknown character escape: }
+error: unknown character escape: `}`
   --> $DIR/wrong-escape-of-curly-braces.rs:3:30
    |
 LL |     let bad = "\{it is wrong\}";
diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs
new file mode 100644
index 00000000000..83199e8112e
--- /dev/null
+++ b/src/test/ui/unsized/unchanged-param.rs
@@ -0,0 +1,12 @@
+#![feature(relaxed_struct_unsize)]
+// run-pass
+// Test that we allow unsizing even if there is an unchanged param in the
+// field getting unsized.
+struct A<T, U: ?Sized + 'static>(T, B<T, U>);
+struct B<T, U: ?Sized>(T, U);
+
+fn main() {
+    let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
+    let y: &A<[u32; 1], [u32]> = &x;
+    assert_eq!(y.1.1.len(), 1);
+}
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index d92758eb747..cd9d5300964 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -218,25 +218,19 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
     cmd.args(args);
     cmd.envs(env);
 
+    // On windows, libraries are just searched in the executable directory,
+    // system directories, PWD, and PATH, in that order. PATH is the only one
+    // we can change for this.
+    let library_path = if cfg!(windows) { "PATH" } else { "LD_LIBRARY_PATH" };
+
     // Support libraries were uploaded to `work` earlier, so make sure that's
     // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
     // had some libs uploaded.
-    if cfg!(windows) {
-        // On windows, libraries are just searched in the executable directory,
-        // system directories, PWD, and PATH, in that order. PATH is the only one
-        // we can change for this.
-        cmd.env(
-            "PATH",
-            env::join_paths(
-                std::iter::once(work.to_owned())
-                    .chain(std::iter::once(path.clone()))
-                    .chain(env::split_paths(&env::var_os("PATH").unwrap())),
-            )
-            .unwrap(),
-        );
-    } else {
-        cmd.env("LD_LIBRARY_PATH", format!("{}:{}", work.display(), path.display()));
+    let mut paths = vec![work.to_owned(), path.clone()];
+    if let Some(library_path) = env::var_os(library_path) {
+        paths.extend(env::split_paths(&library_path));
     }
+    cmd.env(library_path, env::join_paths(paths).unwrap());
 
     // Some tests assume RUST_TEST_TMPDIR exists
     cmd.env("RUST_TEST_TMPDIR", tmp.to_owned());