diff --git a/RELEASES.md b/RELEASES.md
index aae2a66965014..a9422fa103ed8 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -156,6 +156,7 @@ Language
 - [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220]
 - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
 - [Allow panicking in constant evaluation.][89508]
+- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200]
 
 Compiler
 --------
@@ -216,6 +217,9 @@ Cargo
 Compatibility notes
 -------------------
 
+- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200]
+  This will break some builds that set `#![deny(dead_code)]`.
+
 Internal changes
 ----------------
 These changes provide no direct user facing benefits, but represent significant
@@ -224,6 +228,7 @@ and related tools.
 
 - [Added an experimental backend for codegen with `libgccjit`.][87260]
 
+[85200]: https://github.com/rust-lang/rust/pull/85200/
 [86191]: https://github.com/rust-lang/rust/pull/86191/
 [87220]: https://github.com/rust-lang/rust/pull/87220/
 [87260]: https://github.com/rust-lang/rust/pull/87260/
diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs
index 785e6886d8a38..93310dd45c575 100644
--- a/compiler/rustc_ast_pretty/src/pp/convenience.rs
+++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs
@@ -75,6 +75,10 @@ impl Printer {
     }
 
     pub fn trailing_comma(&mut self) {
+        self.scan_break(BreakToken { pre_break: Some(','), ..BreakToken::default() });
+    }
+
+    pub fn trailing_comma_or_space(&mut self) {
         self.scan_break(BreakToken {
             blank_space: 1,
             pre_break: Some(','),
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 44116fa76a0c1..6435f1b6141e3 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -142,7 +142,7 @@ impl<'a> State<'a> {
             if !field.is_last || has_rest {
                 self.word_space(",");
             } else {
-                self.trailing_comma();
+                self.trailing_comma_or_space();
             }
         }
         if has_rest {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index dac84ae9d5fc8..d7e9ef0e50dd8 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -1,5 +1,6 @@
 use crate::pp::Breaks::Inconsistent;
-use crate::pprust::state::{AnnNode, PrintState, State};
+use crate::pprust::state::delimited::IterDelimited;
+use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
 
 use rustc_ast as ast;
 use rustc_ast::GenericBound;
@@ -138,11 +139,10 @@ impl<'a> State<'a> {
                 self.end(); // end outer head-block
             }
             ast::ItemKind::Use(ref tree) => {
-                self.head(visibility_qualified(&item.vis, "use"));
+                self.print_visibility(&item.vis);
+                self.word_nbsp("use");
                 self.print_use_tree(tree);
                 self.word(";");
-                self.end(); // end inner head-block
-                self.end(); // end outer head-block
             }
             ast::ItemKind::Static(ref ty, mutbl, ref body) => {
                 let def = ast::Defaultness::Final;
@@ -615,8 +615,8 @@ impl<'a> State<'a> {
             ast::UseTreeKind::Simple(rename, ..) => {
                 self.print_path(&tree.prefix, false, 0);
                 if let Some(rename) = rename {
-                    self.space();
-                    self.word_space("as");
+                    self.nbsp();
+                    self.word_nbsp("as");
                     self.print_ident(rename);
                 }
             }
@@ -628,16 +628,36 @@ impl<'a> State<'a> {
                 self.word("*");
             }
             ast::UseTreeKind::Nested(ref items) => {
-                if tree.prefix.segments.is_empty() {
-                    self.word("{");
-                } else {
+                if !tree.prefix.segments.is_empty() {
                     self.print_path(&tree.prefix, false, 0);
-                    self.word("::{");
+                    self.word("::");
+                }
+                if items.is_empty() {
+                    self.word("{}");
+                } else if items.len() == 1 {
+                    self.print_use_tree(&items[0].0);
+                } else {
+                    self.cbox(INDENT_UNIT);
+                    self.word("{");
+                    self.zerobreak();
+                    self.ibox(0);
+                    for use_tree in items.iter().delimited() {
+                        self.print_use_tree(&use_tree.0);
+                        if !use_tree.is_last {
+                            self.word(",");
+                            if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
+                                self.hardbreak();
+                            } else {
+                                self.space();
+                            }
+                        }
+                    }
+                    self.end();
+                    self.trailing_comma();
+                    self.offset(-INDENT_UNIT);
+                    self.word("}");
+                    self.end();
                 }
-                self.commasep(Inconsistent, &items, |this, &(ref tree, _)| {
-                    this.print_use_tree(tree)
-                });
-                self.word("}");
             }
         }
     }
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index c401f65eddaed..a72681dbf4e7e 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -97,6 +97,7 @@ E0184: include_str!("./error_codes/E0184.md"),
 E0185: include_str!("./error_codes/E0185.md"),
 E0186: include_str!("./error_codes/E0186.md"),
 E0191: include_str!("./error_codes/E0191.md"),
+E0192: include_str!("./error_codes/E0192.md"),
 E0193: include_str!("./error_codes/E0193.md"),
 E0195: include_str!("./error_codes/E0195.md"),
 E0197: include_str!("./error_codes/E0197.md"),
@@ -522,7 +523,6 @@ E0787: include_str!("./error_codes/E0787.md"),
 //  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
-//  E0192, // negative impl only applicable to auto traits
 //  E0194, // merged into E0403
 //  E0196, // cannot determine a type for this closure
     E0208,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0192.md b/compiler/rustc_error_codes/src/error_codes/E0192.md
index 5fd951b2e86cb..deca042a91a50 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0192.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0192.md
@@ -1,15 +1,17 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 A negative impl was added on a trait implementation.
 
 Erroneous code example:
 
-```compile_fail,E0192
+```compile_fail
 trait Trait {
     type Bar;
 }
 
 struct Foo;
 
-impl !Trait for Foo { } //~ ERROR E0192
+impl !Trait for Foo { } //~ ERROR
 
 fn main() {}
 ```
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 9d40b3cba2952..bd5892dba38c7 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -49,6 +49,31 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         Canonicalizer::canonicalize(value, self, self.tcx, &CanonicalizeAllFreeRegions, query_state)
     }
 
+    /// Like [Self::canonicalize_query], but preserves distinct universes. For
+    /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
+    /// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
+    /// in `U2`.
+    ///
+    /// This is used for Chalk integration.
+    pub fn canonicalize_query_preserving_universes<V>(
+        &self,
+        value: V,
+        query_state: &mut OriginalQueryValues<'tcx>,
+    ) -> Canonicalized<'tcx, V>
+    where
+        V: TypeFoldable<'tcx>,
+    {
+        self.tcx.sess.perf_stats.queries_canonicalized.fetch_add(1, Ordering::Relaxed);
+
+        Canonicalizer::canonicalize(
+            value,
+            self,
+            self.tcx,
+            &CanonicalizeAllFreeRegionsPreservingUniverses,
+            query_state,
+        )
+    }
+
     /// Canonicalizes a query *response* `V`. When we canonicalize a
     /// query response, we only canonicalize unbound inference
     /// variables, and we leave other free regions alone. So,
@@ -133,7 +158,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
 /// maximally general query. But if we are canonicalizing a *query
 /// response*, then we don't typically replace free regions, as they
 /// must have been introduced from other parts of the system.
-trait CanonicalizeRegionMode {
+trait CanonicalizeMode {
     fn canonicalize_free_region<'tcx>(
         &self,
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
@@ -141,11 +166,14 @@ trait CanonicalizeRegionMode {
     ) -> ty::Region<'tcx>;
 
     fn any(&self) -> bool;
+
+    // Do we preserve universe of variables.
+    fn preserve_universes(&self) -> bool;
 }
 
 struct CanonicalizeQueryResponse;
 
-impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
+impl CanonicalizeMode for CanonicalizeQueryResponse {
     fn canonicalize_free_region<'tcx>(
         &self,
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
@@ -198,11 +226,15 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
     fn any(&self) -> bool {
         false
     }
+
+    fn preserve_universes(&self) -> bool {
+        true
+    }
 }
 
 struct CanonicalizeUserTypeAnnotation;
 
-impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
+impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
     fn canonicalize_free_region<'tcx>(
         &self,
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
@@ -221,11 +253,15 @@ impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
     fn any(&self) -> bool {
         false
     }
+
+    fn preserve_universes(&self) -> bool {
+        false
+    }
 }
 
 struct CanonicalizeAllFreeRegions;
 
-impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
+impl CanonicalizeMode for CanonicalizeAllFreeRegions {
     fn canonicalize_free_region<'tcx>(
         &self,
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
@@ -237,11 +273,39 @@ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
     fn any(&self) -> bool {
         true
     }
+
+    fn preserve_universes(&self) -> bool {
+        false
+    }
+}
+
+struct CanonicalizeAllFreeRegionsPreservingUniverses;
+
+impl CanonicalizeMode for CanonicalizeAllFreeRegionsPreservingUniverses {
+    fn canonicalize_free_region<'tcx>(
+        &self,
+        canonicalizer: &mut Canonicalizer<'_, 'tcx>,
+        r: ty::Region<'tcx>,
+    ) -> ty::Region<'tcx> {
+        let universe = canonicalizer.infcx.universe_of_region(r);
+        canonicalizer.canonical_var_for_region(
+            CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) },
+            r,
+        )
+    }
+
+    fn any(&self) -> bool {
+        true
+    }
+
+    fn preserve_universes(&self) -> bool {
+        true
+    }
 }
 
 struct CanonicalizeFreeRegionsOtherThanStatic;
 
-impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
+impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic {
     fn canonicalize_free_region<'tcx>(
         &self,
         canonicalizer: &mut Canonicalizer<'_, 'tcx>,
@@ -257,6 +321,10 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
     fn any(&self) -> bool {
         true
     }
+
+    fn preserve_universes(&self) -> bool {
+        false
+    }
 }
 
 struct Canonicalizer<'cx, 'tcx> {
@@ -267,7 +335,7 @@ struct Canonicalizer<'cx, 'tcx> {
     // Note that indices is only used once `var_values` is big enough to be
     // heap-allocated.
     indices: FxHashMap<GenericArg<'tcx>, BoundVar>,
-    canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
+    canonicalize_mode: &'cx dyn CanonicalizeMode,
     needs_canonical_flags: TypeFlags,
 
     binder_index: ty::DebruijnIndex,
@@ -311,7 +379,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
                     vid, r
                 );
                 let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
-                self.canonicalize_region_mode.canonicalize_free_region(self, r)
+                self.canonicalize_mode.canonicalize_free_region(self, r)
             }
 
             ty::ReStatic
@@ -319,7 +387,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             | ty::ReFree(_)
             | ty::ReEmpty(_)
             | ty::RePlaceholder(..)
-            | ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),
+            | ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
         }
     }
 
@@ -337,8 +405,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
                     // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
                     // result.
                     Err(mut ui) => {
-                        // FIXME: perf problem described in #55921.
-                        ui = ty::UniverseIndex::ROOT;
+                        if !self.canonicalize_mode.preserve_universes() {
+                            // FIXME: perf problem described in #55921.
+                            ui = ty::UniverseIndex::ROOT;
+                        }
                         self.canonicalize_ty_var(
                             CanonicalVarInfo {
                                 kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
@@ -422,8 +492,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
                     // `ConstVar(vid)` is unresolved, track its universe index in the
                     // canonicalized result
                     Err(mut ui) => {
-                        // FIXME: perf problem described in #55921.
-                        ui = ty::UniverseIndex::ROOT;
+                        if !self.canonicalize_mode.preserve_universes() {
+                            // FIXME: perf problem described in #55921.
+                            ui = ty::UniverseIndex::ROOT;
+                        }
                         return self.canonicalize_const_var(
                             CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty) },
                             ct,
@@ -462,7 +534,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         value: V,
         infcx: &InferCtxt<'_, 'tcx>,
         tcx: TyCtxt<'tcx>,
-        canonicalize_region_mode: &dyn CanonicalizeRegionMode,
+        canonicalize_region_mode: &dyn CanonicalizeMode,
         query_state: &mut OriginalQueryValues<'tcx>,
     ) -> Canonicalized<'tcx, V>
     where
@@ -493,7 +565,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         let mut canonicalizer = Canonicalizer {
             infcx,
             tcx,
-            canonicalize_region_mode,
+            canonicalize_mode: canonicalize_region_mode,
             needs_canonical_flags,
             variables: SmallVec::new(),
             query_state,
@@ -504,10 +576,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
 
         // Once we have canonicalized `out_value`, it should not
         // contain anything that ties it to this inference context
-        // anymore, so it should live in the global arena.
-        debug_assert!(!out_value.needs_infer());
+        // anymore.
+        debug_assert!(!out_value.needs_infer() && !out_value.has_placeholders());
 
-        let canonical_variables = tcx.intern_canonical_var_infos(&canonicalizer.variables);
+        let canonical_variables =
+            tcx.intern_canonical_var_infos(&canonicalizer.universe_canonicalized_variables());
 
         let max_universe = canonical_variables
             .iter()
@@ -527,6 +600,19 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
 
         let var_values = &mut query_state.var_values;
 
+        let universe = info.universe();
+        if universe != ty::UniverseIndex::ROOT {
+            assert!(self.canonicalize_mode.preserve_universes());
+
+            // Insert universe into the universe map. To preserve the order of the
+            // universes in the value being canonicalized, we don't update the
+            // universe in `info` until we have finished canonicalizing.
+            match query_state.universe_map.binary_search(&universe) {
+                Err(idx) => query_state.universe_map.insert(idx, universe),
+                Ok(_) => {}
+            }
+        }
+
         // This code is hot. `variables` and `var_values` are usually small
         // (fewer than 8 elements ~95% of the time). They are SmallVec's to
         // avoid allocations in those cases. We also don't use `indices` to
@@ -569,6 +655,61 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         }
     }
 
+    /// Replaces the universe indexes used in `var_values` with their index in
+    /// `query_state.universe_map`. This minimizes the maximum universe used in
+    /// the canonicalized value.
+    fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarInfo<'tcx>; 8]> {
+        if self.query_state.universe_map.len() == 1 {
+            return self.variables;
+        }
+
+        let reverse_universe_map: FxHashMap<ty::UniverseIndex, ty::UniverseIndex> = self
+            .query_state
+            .universe_map
+            .iter()
+            .enumerate()
+            .map(|(idx, universe)| (*universe, ty::UniverseIndex::from_usize(idx)))
+            .collect();
+
+        self.variables
+            .iter()
+            .map(|v| CanonicalVarInfo {
+                kind: match v.kind {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
+                        return *v;
+                    }
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
+                        CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
+                    }
+                    CanonicalVarKind::Region(u) => {
+                        CanonicalVarKind::Region(reverse_universe_map[&u])
+                    }
+                    CanonicalVarKind::Const(u, t) => {
+                        CanonicalVarKind::Const(reverse_universe_map[&u], t)
+                    }
+                    CanonicalVarKind::PlaceholderTy(placeholder) => {
+                        CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                            universe: reverse_universe_map[&placeholder.universe],
+                            ..placeholder
+                        })
+                    }
+                    CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                        CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
+                            universe: reverse_universe_map[&placeholder.universe],
+                            ..placeholder
+                        })
+                    }
+                    CanonicalVarKind::PlaceholderConst(placeholder) => {
+                        CanonicalVarKind::PlaceholderConst(ty::Placeholder {
+                            universe: reverse_universe_map[&placeholder.universe],
+                            ..placeholder
+                        })
+                    }
+                },
+            })
+            .collect()
+    }
+
     /// Shorthand helper that creates a canonical region variable for
     /// `r` (always in the root universe). The reason that we always
     /// put these variables into the root universe is because this
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 28217aeab13ee..4efe3640dfac6 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -64,9 +64,9 @@ pub struct CanonicalVarValues<'tcx> {
 /// result.
 #[derive(Clone, Debug)]
 pub struct OriginalQueryValues<'tcx> {
-    /// Map from the universes that appear in the query to the
-    /// universes in the caller context. For the time being, we only
-    /// ever put ROOT values into the query, so this map is very
+    /// Map from the universes that appear in the query to the universes in the
+    /// caller context. For all queries except `evaluate_goal` (used by Chalk),
+    /// we only ever put ROOT values into the query, so this map is very
     /// simple.
     pub universe_map: SmallVec<[ty::UniverseIndex; 4]>,
 
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 34fc4ca8fead7..93c2f202545f6 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -8,7 +8,7 @@ use crate::traits::{
     PredicateObligation, SelectionError, TraitEngine,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TypeFoldable};
 
 pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
@@ -91,7 +91,12 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                 let environment = obligation.param_env.caller_bounds();
                 let goal = ChalkEnvironmentAndGoal { environment, goal: obligation.predicate };
                 let mut orig_values = OriginalQueryValues::default();
-                let canonical_goal = infcx.canonicalize_query(goal, &mut orig_values);
+                if goal.references_error() {
+                    continue;
+                }
+
+                let canonical_goal =
+                    infcx.canonicalize_query_preserving_universes(goal, &mut orig_values);
 
                 match infcx.tcx.evaluate_goal(canonical_goal) {
                     Ok(response) => {
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 3f51442277f59..0170ab223b031 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -20,11 +20,10 @@ use rustc_span::symbol::sym;
 use std::fmt;
 use std::sync::Arc;
 
-use crate::chalk::lowering::{self, LowerInto};
+use crate::chalk::lowering::LowerInto;
 
 pub struct RustIrDatabase<'tcx> {
     pub(crate) interner: RustInterner<'tcx>,
-    pub(crate) reempty_placeholder: ty::Region<'tcx>,
 }
 
 impl fmt::Debug for RustIrDatabase<'_> {
@@ -40,12 +39,9 @@ impl<'tcx> RustIrDatabase<'tcx> {
         bound_vars: SubstsRef<'tcx>,
     ) -> Vec<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>> {
         let predicates = self.interner.tcx.predicates_defined_on(def_id).predicates;
-        let mut regions_substitutor =
-            lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
         predicates
             .iter()
             .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars))
-            .map(|wc| wc.fold_with(&mut regions_substitutor))
             .filter_map(|wc| LowerInto::<
                     Option<chalk_ir::QuantifiedWhereClause<RustInterner<'tcx>>>
                     >::lower_into(wc, self.interner)).collect()
@@ -287,9 +283,6 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
 
         let trait_ref = self.interner.tcx.impl_trait_ref(def_id).expect("not an impl");
         let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars);
-        let mut regions_substitutor =
-            lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-        let trait_ref = trait_ref.fold_with(&mut regions_substitutor);
 
         let where_clauses = self.where_clauses_for(def_id, bound_vars);
 
@@ -335,9 +328,6 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
 
             let self_ty = trait_ref.self_ty();
             let self_ty = self_ty.subst(self.interner.tcx, bound_vars);
-            let mut regions_substitutor =
-                lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder);
-            let self_ty = self_ty.fold_with(&mut regions_substitutor);
             let lowered_ty = self_ty.lower_into(self.interner);
 
             parameters[0].assert_ty_ref(self.interner).could_match(
@@ -556,11 +546,11 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
             Fn => lang_items.fn_trait(),
             FnMut => lang_items.fn_mut_trait(),
             FnOnce => lang_items.fn_once_trait(),
+            Generator => lang_items.gen_trait(),
             Unsize => lang_items.unsize_trait(),
             Unpin => lang_items.unpin_trait(),
             CoerceUnsized => lang_items.coerce_unsized_trait(),
             DiscriminantKind => lang_items.discriminant_kind_trait(),
-            Generator => lang_items.generator_return(),
         };
         def_id.map(chalk_ir::TraitId)
     }
@@ -684,28 +674,18 @@ impl<'tcx> chalk_ir::UnificationDatabase<RustInterner<'tcx>> for RustIrDatabase<
         let variances = self.interner.tcx.variances_of(def_id.0);
         chalk_ir::Variances::from_iter(
             self.interner,
-            variances.iter().map(|v| match v {
-                ty::Variance::Invariant => chalk_ir::Variance::Invariant,
-                ty::Variance::Covariant => chalk_ir::Variance::Covariant,
-                ty::Variance::Contravariant => chalk_ir::Variance::Contravariant,
-                ty::Variance::Bivariant => unimplemented!(),
-            }),
+            variances.iter().map(|v| v.lower_into(self.interner)),
         )
     }
 
     fn adt_variance(
         &self,
-        def_id: chalk_ir::AdtId<RustInterner<'tcx>>,
+        adt_id: chalk_ir::AdtId<RustInterner<'tcx>>,
     ) -> chalk_ir::Variances<RustInterner<'tcx>> {
-        let variances = self.interner.tcx.variances_of(def_id.0.did);
+        let variances = self.interner.tcx.variances_of(adt_id.0.did);
         chalk_ir::Variances::from_iter(
             self.interner,
-            variances.iter().map(|v| match v {
-                ty::Variance::Invariant => chalk_ir::Variance::Invariant,
-                ty::Variance::Covariant => chalk_ir::Variance::Covariant,
-                ty::Variance::Contravariant => chalk_ir::Variance::Contravariant,
-                ty::Variance::Bivariant => unimplemented!(),
-            }),
+            variances.iter().map(|v| v.lower_into(self.interner)),
         )
     }
 }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 67d0ba39667d3..6f143c1c607b3 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -188,12 +188,18 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
                 chalk_ir::DomainGoal::ObjectSafe(chalk_ir::TraitId(t)),
             ),
 
+            ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, a_is_expected: _ }) => {
+                chalk_ir::GoalData::SubtypeGoal(chalk_ir::SubtypeGoal {
+                    a: a.lower_into(interner),
+                    b: b.lower_into(interner),
+                })
+            }
+
             // FIXME(chalk): other predicates
             //
             // We can defer this, but ultimately we'll want to express
             // some of these in terms of chalk operations.
             ty::PredicateKind::ClosureKind(..)
-            | ty::PredicateKind::Subtype(..)
             | ty::PredicateKind::Coerce(..)
             | ty::PredicateKind::ConstEvaluatable(..)
             | ty::PredicateKind::ConstEquate(..) => {
@@ -464,9 +470,11 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
                 })
                 .intern(interner)
             }
-            ReEmpty(_) => unimplemented!(),
-            // FIXME(chalk): need to handle ReErased
-            ReErased => unimplemented!(),
+            ReEmpty(ui) => {
+                chalk_ir::LifetimeData::Empty(chalk_ir::UniverseIndex { counter: ui.index() })
+                    .intern(interner)
+            }
+            ReErased => chalk_ir::LifetimeData::Erased.intern(interner),
         }
     }
 }
@@ -488,12 +496,12 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                     name: ty::BoundRegionKind::BrAnon(p.idx as u32),
                 })
             }
-            chalk_ir::LifetimeData::Static => ty::RegionKind::ReStatic,
-            chalk_ir::LifetimeData::Phantom(_, _) => unimplemented!(),
+            chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
             chalk_ir::LifetimeData::Empty(ui) => {
-                ty::RegionKind::ReEmpty(ty::UniverseIndex::from_usize(ui.counter))
+                ty::ReEmpty(ty::UniverseIndex::from_usize(ui.counter))
             }
-            chalk_ir::LifetimeData::Erased => ty::RegionKind::ReErased,
+            chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
+            chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
         };
         interner.tcx.mk_region(kind)
     }
@@ -788,6 +796,16 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity
         }
     }
 }
+impl<'tcx> LowerInto<'tcx, chalk_ir::Variance> for ty::Variance {
+    fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_ir::Variance {
+        match self {
+            ty::Variance::Covariant => chalk_ir::Variance::Covariant,
+            ty::Variance::Invariant => chalk_ir::Variance::Invariant,
+            ty::Variance::Contravariant => chalk_ir::Variance::Contravariant,
+            ty::Variance::Bivariant => unimplemented!(),
+        }
+    }
+}
 
 impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>>>
     for ty::ProjectionPredicate<'tcx>
@@ -1016,10 +1034,6 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
-            // FIXME(chalk): currently we convert params to placeholders starting at
-            // index `0`. To support placeholders, we'll actually need to do a
-            // first pass to collect placeholders. Then we can insert params after.
-            ty::Placeholder(_) => unimplemented!(),
             ty::Param(param) => match self.list.iter().position(|r| r == &param) {
                 Some(idx) => self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::from_usize(0),
@@ -1035,15 +1049,15 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
                     }))
                 }
             },
-
             _ => t.super_fold_with(self),
         }
     }
 
     fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
         match r {
-            // FIXME(chalk) - jackh726 - this currently isn't hit in any tests.
-            // This covers any region variables in a goal, right?
+            // FIXME(chalk) - jackh726 - this currently isn't hit in any tests,
+            // since canonicalization will already change these to canonical
+            // variables (ty::ReLateBound).
             ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) {
                 Some(idx) => {
                     let br = ty::BoundRegion {
@@ -1066,6 +1080,39 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
     }
 }
 
+crate struct ReverseParamsSubstitutor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+}
+
+impl<'tcx> ReverseParamsSubstitutor<'tcx> {
+    crate fn new(
+        tcx: TyCtxt<'tcx>,
+        params: rustc_data_structures::fx::FxHashMap<usize, rustc_middle::ty::ParamTy>,
+    ) -> Self {
+        Self { tcx, params }
+    }
+}
+
+impl<'tcx> TypeFolder<'tcx> for ReverseParamsSubstitutor<'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        match *t.kind() {
+            ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
+                match self.params.get(&name.as_usize()) {
+                    Some(param) => self.tcx.mk_ty(ty::Param(*param)),
+                    None => t,
+                }
+            }
+
+            _ => t.super_fold_with(self),
+        }
+    }
+}
+
 /// Used to collect `Placeholder`s.
 crate struct PlaceholdersCollector {
     universe_index: ty::UniverseIndex,
@@ -1110,32 +1157,3 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
         r.super_visit_with(self)
     }
 }
-
-/// Used to substitute specific `Regions`s with placeholders.
-crate struct RegionsSubstitutor<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    reempty_placeholder: ty::Region<'tcx>,
-}
-
-impl<'tcx> RegionsSubstitutor<'tcx> {
-    crate fn new(tcx: TyCtxt<'tcx>, reempty_placeholder: ty::Region<'tcx>) -> Self {
-        RegionsSubstitutor { tcx, reempty_placeholder }
-    }
-}
-
-impl<'tcx> TypeFolder<'tcx> for RegionsSubstitutor<'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-        self.tcx
-    }
-
-    fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
-        match r {
-            ty::ReEmpty(ui) => {
-                assert_eq!(ui.as_usize(), 0);
-                self.reempty_placeholder
-            }
-
-            _ => r.super_fold_with(self),
-        }
-    }
-}
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index 09bfdabf47373..3c2a266dab9bc 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -22,9 +22,8 @@ use rustc_infer::infer::canonical::{
 use rustc_infer::traits::{self, CanonicalChalkEnvironmentAndGoal};
 
 use crate::chalk::db::RustIrDatabase as ChalkRustIrDatabase;
-use crate::chalk::lowering::{
-    LowerInto, ParamsSubstitutor, PlaceholdersCollector, RegionsSubstitutor,
-};
+use crate::chalk::lowering::LowerInto;
+use crate::chalk::lowering::{ParamsSubstitutor, PlaceholdersCollector, ReverseParamsSubstitutor};
 
 use chalk_solve::Solution;
 
@@ -42,19 +41,10 @@ crate fn evaluate_goal<'tcx>(
     let mut placeholders_collector = PlaceholdersCollector::new();
     obligation.visit_with(&mut placeholders_collector);
 
-    let reempty_placeholder = tcx.mk_region(ty::RegionKind::RePlaceholder(ty::Placeholder {
-        universe: ty::UniverseIndex::ROOT,
-        name: ty::BoundRegionKind::BrAnon(placeholders_collector.next_anon_region_placeholder + 1),
-    }));
-
     let mut params_substitutor =
         ParamsSubstitutor::new(tcx, placeholders_collector.next_ty_placeholder);
     let obligation = obligation.fold_with(&mut params_substitutor);
-    // FIXME(chalk): we really should be substituting these back in the solution
-    let _params: FxHashMap<usize, ParamTy> = params_substitutor.params;
-
-    let mut regions_substitutor = RegionsSubstitutor::new(tcx, reempty_placeholder);
-    let obligation = obligation.fold_with(&mut regions_substitutor);
+    let params: FxHashMap<usize, ParamTy> = params_substitutor.params;
 
     let max_universe = obligation.max_universe.index();
 
@@ -96,7 +86,8 @@ crate fn evaluate_goal<'tcx>(
 
     use chalk_solve::Solver;
     let mut solver = chalk_engine::solve::SLGSolver::new(32, None);
-    let db = ChalkRustIrDatabase { interner, reempty_placeholder };
+    let db = ChalkRustIrDatabase { interner };
+    debug!(?lowered_goal);
     let solution = solver.solve(&db, &lowered_goal);
     debug!(?obligation, ?solution, "evaluate goal");
 
@@ -110,8 +101,9 @@ crate fn evaluate_goal<'tcx>(
         use rustc_middle::infer::canonical::CanonicalVarInfo;
 
         let mut var_values: IndexVec<BoundVar, GenericArg<'tcx>> = IndexVec::new();
+        let mut reverse_param_substitutor = ReverseParamsSubstitutor::new(tcx, params);
         subst.as_slice(interner).iter().for_each(|p| {
-            var_values.push(p.lower_into(interner));
+            var_values.push(p.lower_into(interner).fold_with(&mut reverse_param_substitutor));
         });
         let variables: Vec<_> = binders
             .iter(interner)
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 86115a9029465..47034a164aea8 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -63,7 +63,7 @@ def support_xz():
     except tarfile.CompressionError:
         return False
 
-def get(base, url, path, checksums, verbose=False, do_verify=True):
+def get(base, url, path, checksums, verbose=False, do_verify=True, help_on_error=None):
     with tempfile.NamedTemporaryFile(delete=False) as temp_file:
         temp_path = temp_file.name
 
@@ -82,7 +82,7 @@ def get(base, url, path, checksums, verbose=False, do_verify=True):
                         print("ignoring already-download file",
                             path, "due to failed verification")
                     os.unlink(path)
-        download(temp_path, "{}/{}".format(base, url), True, verbose)
+        download(temp_path, "{}/{}".format(base, url), True, verbose, help_on_error=help_on_error)
         if do_verify and not verify(temp_path, sha256, verbose):
             raise RuntimeError("failed verification")
         if verbose:
@@ -95,17 +95,17 @@ def get(base, url, path, checksums, verbose=False, do_verify=True):
             os.unlink(temp_path)
 
 
-def download(path, url, probably_big, verbose):
+def download(path, url, probably_big, verbose, help_on_error=None):
     for _ in range(0, 4):
         try:
-            _download(path, url, probably_big, verbose, True)
+            _download(path, url, probably_big, verbose, True, help_on_error=help_on_error)
             return
         except RuntimeError:
             print("\nspurious failure, trying again")
-    _download(path, url, probably_big, verbose, False)
+    _download(path, url, probably_big, verbose, False, help_on_error=help_on_error)
 
 
-def _download(path, url, probably_big, verbose, exception):
+def _download(path, url, probably_big, verbose, exception, help_on_error=None):
     if probably_big or verbose:
         print("downloading {}".format(url))
     # see https://serverfault.com/questions/301128/how-to-download
@@ -126,7 +126,8 @@ def _download(path, url, probably_big, verbose, exception):
              "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
              "--retry", "3", "-Sf", "-o", path, url],
             verbose=verbose,
-            exception=exception)
+            exception=exception,
+            help_on_error=help_on_error)
 
 
 def verify(path, expected, verbose):
@@ -167,7 +168,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
     shutil.rmtree(os.path.join(dst, fname))
 
 
-def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
+def run(args, verbose=False, exception=False, is_bootstrap=False, help_on_error=None, **kwargs):
     """Run a child program in a new process"""
     if verbose:
         print("running: " + ' '.join(args))
@@ -178,6 +179,8 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
     code = ret.wait()
     if code != 0:
         err = "failed to run: " + ' '.join(args)
+        if help_on_error is not None:
+            err = f"{err}\n{help_on_error}"
         if verbose or exception:
             raise RuntimeError(err)
         # For most failures, we definitely do want to print this error, or the user will have no
@@ -624,6 +627,14 @@ def _download_ci_llvm(self, llvm_sha, llvm_assertions):
         filename = "rust-dev-nightly-" + self.build + tarball_suffix
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
+            help_on_error = "error: failed to download llvm from ci"
+            help_on_error += "\nhelp: old builds get deleted after a certain time"
+            help_on_error += "\nhelp: if trying to compile an old commit of rustc,"
+            help_on_error += " disable `download-ci-llvm` in config.toml:"
+            help_on_error += "\n"
+            help_on_error += "\n[llvm]"
+            help_on_error += "\ndownload-ci-llvm = false"
+            help_on_error += "\n"
             get(
                 base,
                 "{}/{}".format(url, filename),
@@ -631,6 +642,7 @@ def _download_ci_llvm(self, llvm_sha, llvm_assertions):
                 self.checksums_sha256,
                 verbose=self.verbose,
                 do_verify=False,
+                help_on_error=help_on_error,
             )
         unpack(tarball, tarball_suffix, self.llvm_root(),
                 match="rust-dev",
diff --git a/src/test/pretty/use-tree.rs b/src/test/pretty/use-tree.rs
new file mode 100644
index 0000000000000..5da9523524552
--- /dev/null
+++ b/src/test/pretty/use-tree.rs
@@ -0,0 +1,23 @@
+// pp-exact
+// edition:2021
+
+#![allow(unused_imports)]
+
+use ::std::fmt::{self, Debug, Display, Write as _};
+
+use core::option::Option::*;
+
+use core::{
+    cmp::{Eq, Ord, PartialEq, PartialOrd},
+    convert::{AsMut, AsRef, From, Into},
+    iter::{
+        DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator,
+        IntoIterator, Iterator,
+    },
+    marker::{
+        Copy as Copy, Send as Send, Sized as Sized, Sync as Sync, Unpin as U,
+    },
+    ops::{*, Drop, Fn, FnMut, FnOnce},
+};
+
+fn main() {}
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
index 0c4907fd00294..d180de9be3bf3 100644
--- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs
@@ -1,6 +1,5 @@
 // NOTE: rustc cannot currently handle bounds of the form `for<'a> <Foo as Bar<'a>>::Assoc: Baz`.
 // This should hopefully be fixed with Chalk.
-// ignore-compare-mode-chalk
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
index 4ecae471ec2da..c23e54594ee30 100644
--- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
+++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:36
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36
    |
 LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
    |                                    ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely
@@ -11,7 +11,7 @@ LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
    |             ++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:43
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43
    |
 LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator
@@ -23,7 +23,7 @@ LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
    |             ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
-  --> $DIR/bad-bounds-on-assoc-in-trait.rs:27:93
+  --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93
    |
 LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>;
    |                                                                                             ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely
diff --git a/src/test/ui/associated-type-bounds/trait-params.rs b/src/test/ui/associated-type-bounds/trait-params.rs
index a9aa2747e52af..b0703a4ee22b3 100644
--- a/src/test/ui/associated-type-bounds/trait-params.rs
+++ b/src/test/ui/associated-type-bounds/trait-params.rs
@@ -1,5 +1,4 @@
 // build-pass (FIXME(62277): could be check-pass?)
-// ignore-compare-mode-chalk
 
 #![feature(associated_type_bounds)]
 
diff --git a/src/test/ui/associated-type-bounds/union-bounds.rs b/src/test/ui/associated-type-bounds/union-bounds.rs
index f1aab2a6da071..97c5acf1f72ca 100644
--- a/src/test/ui/associated-type-bounds/union-bounds.rs
+++ b/src/test/ui/associated-type-bounds/union-bounds.rs
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-compare-mode-chalk
 
 #![feature(associated_type_bounds)]
 #![feature(untagged_unions)]
diff --git a/src/test/ui/associated-types/associated-types-stream.rs b/src/test/ui/associated-types/associated-types-stream.rs
index 220ee6af2fc9f..c9b302b96919f 100644
--- a/src/test/ui/associated-types/associated-types-stream.rs
+++ b/src/test/ui/associated-types/associated-types-stream.rs
@@ -1,8 +1,6 @@
 // run-pass
 // Test references to the trait `Stream` in the bounds for associated
 // types defined on `Stream`. Issue #20551.
-// ignore-compare-mode-chalk
-
 
 trait Stream {
     type Car;
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs
index 5193400882d12..f74c5a8590d1d 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs
+++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.rs
@@ -1,4 +1,3 @@
-// ignore-compare-mode-chalk
 trait Z<'a, T: ?Sized>
 where
     T: Z<'a, u16>,
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
index 730229b5208da..354caef1e41d8 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:4:8
+  --> $DIR/hr-associated-type-bound-param-2.rs:3:8
    |
 LL |     T: Z<'a, u16>,
    |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `Z`
-  --> $DIR/hr-associated-type-bound-param-2.rs:7:35
+  --> $DIR/hr-associated-type-bound-param-2.rs:6:35
    |
 LL | trait Z<'a, T: ?Sized>
    |       - required by a bound in this
@@ -14,13 +14,13 @@ LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:4:8
+  --> $DIR/hr-associated-type-bound-param-2.rs:3:8
    |
 LL |     T: Z<'a, u16>,
    |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `Z`
-  --> $DIR/hr-associated-type-bound-param-2.rs:7:35
+  --> $DIR/hr-associated-type-bound-param-2.rs:6:35
    |
 LL | trait Z<'a, T: ?Sized>
    |       - required by a bound in this
@@ -29,13 +29,13 @@ LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-2.rs:16:14
+  --> $DIR/hr-associated-type-bound-param-2.rs:15:14
    |
 LL |     type W = str;
    |              ^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `Z`
-  --> $DIR/hr-associated-type-bound-param-2.rs:7:35
+  --> $DIR/hr-associated-type-bound-param-2.rs:6:35
    |
 LL | trait Z<'a, T: ?Sized>
    |       - required by a bound in this
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs
index 920aa83528070..d7f3151a502ee 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs
+++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.rs
@@ -1,4 +1,3 @@
-// ignore-compare-mode-chalk
 trait Cycle: Sized {
     type Next: Cycle<Next = Self>;
 }
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
index 63cd89316b38c..4c04d12a71470 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-5.rs:27:14
+  --> $DIR/hr-associated-type-bound-param-5.rs:26:14
    |
 LL |     type U = str;
    |              ^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-5.rs:18:45
+  --> $DIR/hr-associated-type-bound-param-5.rs:17:45
    |
 LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
    |       - required by a bound in this
@@ -14,13 +14,13 @@ LL |     for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
    |                                             ^^^^^ required by this bound in `X`
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-5.rs:32:14
+  --> $DIR/hr-associated-type-bound-param-5.rs:31:14
    |
 LL |     type U = str;
    |              ^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-5.rs:18:45
+  --> $DIR/hr-associated-type-bound-param-5.rs:17:45
    |
 LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
    |       - required by a bound in this
diff --git a/src/test/ui/associated-types/issue-50301.rs b/src/test/ui/associated-types/issue-50301.rs
index 4fcb41485d0e2..47ee3e7ad70e8 100644
--- a/src/test/ui/associated-types/issue-50301.rs
+++ b/src/test/ui/associated-types/issue-50301.rs
@@ -1,6 +1,5 @@
 // Tests that HRTBs are correctly accepted -- https://github.com/rust-lang/rust/issues/50301
 // check-pass
-// ignore-compare-mode-chalk
 trait Trait
 where
     for<'a> &'a Self::IntoIter: IntoIterator<Item = u32>,
diff --git a/src/test/ui/associated-types/issue-91069.rs b/src/test/ui/associated-types/issue-91069.rs
new file mode 100644
index 0000000000000..109c2eed27a33
--- /dev/null
+++ b/src/test/ui/associated-types/issue-91069.rs
@@ -0,0 +1,24 @@
+// check-pass
+
+pub trait Associate {
+    type Associated;
+}
+
+pub struct Wrap<'a> {
+    pub field: &'a i32,
+}
+
+pub trait Create<T> {
+    fn create() -> Self;
+}
+
+pub fn oh_no<'a, T>()
+where
+    Wrap<'a>: Associate,
+    <Wrap<'a> as Associate>::Associated: Create<T>,
+{
+    <Wrap<'a> as Associate>::Associated::create();
+}
+
+
+pub fn main() {}
diff --git a/src/test/ui/chalkify/assert.rs b/src/test/ui/chalkify/assert.rs
new file mode 100644
index 0000000000000..f4ebf91924ced
--- /dev/null
+++ b/src/test/ui/chalkify/assert.rs
@@ -0,0 +1,6 @@
+// run-pass
+// compile-flags: -Z chalk
+
+fn main() {
+    assert_eq!(1, 1);
+}
diff --git a/src/test/ui/chalkify/println.rs b/src/test/ui/chalkify/println.rs
index cf36aef8afaf3..0f0df29019e7b 100644
--- a/src/test/ui/chalkify/println.rs
+++ b/src/test/ui/chalkify/println.rs
@@ -2,6 +2,5 @@
 // compile-flags: -Z chalk
 
 fn main() {
-    // FIXME(chalk): Require `RegionOutlives`/`TypeOutlives`/`Subtype` support
-    //println!("hello");
+    println!("hello");
 }
diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs
index 13d9e6a657885..d56abc42bf540 100644
--- a/src/test/ui/chalkify/trait-objects.rs
+++ b/src/test/ui/chalkify/trait-objects.rs
@@ -5,8 +5,7 @@ use std::fmt::Display;
 
 fn main() {
     let d: &dyn Display = &mut 3;
-    // FIXME(chalk) should be able to call d.to_string() as well, but doing so
-    // requires Chalk to be able to prove trait object well-formed goals.
+    d.to_string();
     (&d).to_string();
     let f: &dyn Fn(i32) -> _ = &|x| x + x;
     f(2);
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr
new file mode 100644
index 0000000000000..2a4b6f3b76f90
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `<usize as SliceIndex<[u8]>>::Output == _`
+  --> $DIR/ub-nonnull.rs:19:30
+   |
+LL |     let out_of_bounds_ptr = &ptr[255];
+   |                              ^^^^^^^^ cannot satisfy `<usize as SliceIndex<[u8]>>::Output == _`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr
new file mode 100644
index 0000000000000..39352ca848a80
--- /dev/null
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/ub-wide-ptr.rs:90:67
+   |
+LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
+   |                                                                   ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/deriving/deriving-associated-types.rs b/src/test/ui/deriving/deriving-associated-types.rs
index 13735ff2c5a1c..4b1cbe80c506d 100644
--- a/src/test/ui/deriving/deriving-associated-types.rs
+++ b/src/test/ui/deriving/deriving-associated-types.rs
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-compare-mode-chalk
 pub trait DeclaredTrait {
     type Type;
 }
diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs
new file mode 100644
index 0000000000000..aea8aaf4bb393
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs
@@ -0,0 +1,17 @@
+// check-fail
+
+// This should pass, but it requires `Sized` to be coinductive.
+
+#![feature(generic_associated_types)]
+
+trait Allocator {
+    type Allocated<T>;
+}
+
+enum LinkedList<A: Allocator> {
+    Head,
+    Next(A::Allocated<Self>)
+    //~^ overflow
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr
new file mode 100644
index 0000000000000..e18af9c257f7f
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr
@@ -0,0 +1,20 @@
+error[E0275]: overflow evaluating the requirement `LinkedList<A>: Sized`
+  --> $DIR/issue-80626.rs:13:10
+   |
+LL |     Next(A::Allocated<Self>)
+   |          ^^^^^^^^^^^^^^^^^^
+   |
+   = note: no field of an enum variant may have a dynamically sized type
+   = help: change the field's type to have a statically known size
+help: borrowed types always have a statically known size
+   |
+LL |     Next(&A::Allocated<Self>)
+   |          +
+help: the `Box` type always has a statically known size and allocates its contents in the heap
+   |
+LL |     Next(Box<A::Allocated<Self>>)
+   |          ++++                  +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs
new file mode 100644
index 0000000000000..3f8776a363770
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs
@@ -0,0 +1,27 @@
+// check-fail
+
+// This should pass, but seems to run into a TAIT issue.
+
+#![feature(generic_associated_types)]
+#![feature(type_alias_impl_trait)]
+
+pub trait Stream {
+    type Item;
+}
+
+impl Stream for () {
+    type Item = i32;
+}
+
+trait Yay<AdditionalValue> {
+    type InnerStream<'s>: Stream<Item = i32> + 's;
+    fn foo<'s>() -> Self::InnerStream<'s>;
+}
+
+impl<'a> Yay<&'a ()> for () {
+    type InnerStream<'s> = impl Stream<Item = i32> + 's;
+    //~^ the type
+    fn foo<'s>() -> Self::InnerStream<'s> { todo!() }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
new file mode 100644
index 0000000000000..9f4efc0addb73
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
@@ -0,0 +1,15 @@
+error[E0477]: the type `impl Stream<Item = i32>` does not fulfill the required lifetime
+  --> $DIR/issue-86218.rs:22:28
+   |
+LL |     type InnerStream<'s> = impl Stream<Item = i32> + 's;
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: type must outlive the lifetime `'s` as defined here as required by this binding
+  --> $DIR/issue-86218.rs:22:22
+   |
+LL |     type InnerStream<'s> = impl Stream<Item = i32> + 's;
+   |                      ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs
new file mode 100644
index 0000000000000..5f7a42a740df6
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs
@@ -0,0 +1,45 @@
+// check-fail
+
+// This should pass, but we need an extension of implied bounds (probably).
+
+#![feature(generic_associated_types)]
+
+pub trait AsRef2 {
+  type Output<'a> where Self: 'a;
+
+  fn as_ref2<'a>(&'a self) -> Self::Output<'a>;
+}
+
+impl<T> AsRef2 for Vec<T> {
+  type Output<'a> where Self: 'a = &'a [T];
+
+  fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+    &self[..]
+  }
+}
+
+#[derive(Debug)]
+struct Foo<T>(T);
+#[derive(Debug)]
+struct FooRef<'a, U>(&'a [U]);
+
+impl<'b, T, U> AsRef2 for Foo<T> //~ the type parameter
+where
+    // * `for<'b, 'c> T: AsRef2<Output<'b> = &'c [U]>>` does not work
+    //
+    // * `U` is unconstrained but should be allowed in this context because `Output` is
+    // an associated type
+    T: AsRef2<Output<'b> = &'b [U]>,
+    U: 'b
+{
+  type Output<'a> where Self: 'a = FooRef<'a, U>;
+
+  fn as_ref2<'a>(&'a self) -> Self::Output<'a> {
+    FooRef(self.0.as_ref2())
+  }
+}
+
+fn main() {
+    let foo = Foo(vec![1, 2, 3]);
+    dbg!(foo.as_ref2());
+}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr
new file mode 100644
index 0000000000000..31b3a9619b6af
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-87735.rs:26:13
+   |
+LL | impl<'b, T, U> AsRef2 for Foo<T>
+   |             ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs
new file mode 100644
index 0000000000000..4dbaf429ead26
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs
@@ -0,0 +1,22 @@
+// check-fail
+
+// This should pass, but unnormalized input args aren't treated as implied.
+
+#![feature(generic_associated_types)]
+
+trait MyTrait {
+    type Assoc<'a, 'b> where 'b: 'a;
+    fn do_sth(arg: Self::Assoc<'_, '_>);
+}
+
+struct Foo;
+
+impl MyTrait for Foo {
+    type Assoc<'a, 'b> where 'b: 'a = u32;
+
+    fn do_sth(_: u32) {} //~ lifetime bound
+    // fn do_sth(_: Self::Assoc<'static, 'static>) {}
+    // fn do_sth(_: Self::Assoc<'_, '_>) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr
new file mode 100644
index 0000000000000..c38d447859233
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr
@@ -0,0 +1,20 @@
+error[E0478]: lifetime bound not satisfied
+  --> $DIR/issue-87748.rs:17:5
+   |
+LL |     fn do_sth(_: u32) {}
+   |     ^^^^^^^^^^^^^^^^^
+   |
+note: lifetime parameter instantiated with the anonymous lifetime #2 defined here
+  --> $DIR/issue-87748.rs:17:5
+   |
+LL |     fn do_sth(_: u32) {}
+   |     ^^^^^^^^^^^^^^^^^
+note: but lifetime parameter must outlive the anonymous lifetime #1 defined here
+  --> $DIR/issue-87748.rs:17:5
+   |
+LL |     fn do_sth(_: u32) {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0478`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs
new file mode 100644
index 0000000000000..1cd3534ba77a0
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs
@@ -0,0 +1,21 @@
+// check-fail
+
+// This should pass.
+
+#![feature(generic_associated_types)]
+
+use std::fmt::Debug;
+
+trait Foo {
+    type Ass where Self::Ass: Debug;
+}
+
+#[derive(Debug)]
+struct Bar;
+
+impl Foo for Bar {
+    type Ass = Bar;
+    //~^ overflow
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr
new file mode 100644
index 0000000000000..d2dc991a2b640
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<Bar as Foo>::Ass == _`
+  --> $DIR/issue-87755.rs:17:16
+   |
+LL |     type Ass = Bar;
+   |                ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs
new file mode 100644
index 0000000000000..3d2ff38ab049e
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs
@@ -0,0 +1,26 @@
+// check-fail
+
+// This should pass, but using a type alias vs a reference directly
+// changes late-bound -> early-bound.
+
+#![feature(generic_associated_types)]
+
+trait Scanner {
+    type Input<'a>;
+    type Token<'a>;
+
+    fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>;
+}
+
+struct IdScanner();
+
+impl Scanner for IdScanner {
+    type Input<'a> = &'a str;
+    type Token<'a> = &'a str;
+
+    fn scan<'a>(&mut self, s : &'a str) -> &'a str { //~ lifetime parameters
+        s
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr
new file mode 100644
index 0000000000000..fe2abdedbf37c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr
@@ -0,0 +1,12 @@
+error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration
+  --> $DIR/issue-87803.rs:20:12
+   |
+LL |     fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>;
+   |            ---- lifetimes in impl do not match this method in trait
+...
+LL |     fn scan<'a>(&mut self, s : &'a str) -> &'a str {
+   |            ^^^^ lifetimes do not match method in trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs
new file mode 100644
index 0000000000000..f4633ca516999
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs
@@ -0,0 +1,31 @@
+// check-fail
+
+// This should pass, but has a missed normalization due to HRTB.
+
+#![feature(generic_associated_types)]
+
+trait Iterable {
+    type Iterator<'a> where Self: 'a;
+    fn iter(&self) -> Self::Iterator<'_>;
+}
+
+struct SomeImplementation();
+
+impl Iterable for SomeImplementation {
+    type Iterator<'a> = std::iter::Empty<usize>;
+    fn iter(&self) -> Self::Iterator<'_> {
+        std::iter::empty()
+    }
+}
+
+fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
+    f(&mut i.iter());
+}
+
+fn main() {
+    do_something(SomeImplementation(), |_| ());
+    do_something(SomeImplementation(), test);
+    //~^ type mismatch
+}
+
+fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
new file mode 100644
index 0000000000000..05bc58cbba4e6
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
@@ -0,0 +1,20 @@
+error[E0631]: type mismatch in function arguments
+  --> $DIR/issue-88382.rs:27:40
+   |
+LL |     do_something(SomeImplementation(), test);
+   |     ------------                       ^^^^ expected signature of `for<'a> fn(&mut <SomeImplementation as Iterable>::Iterator<'a>) -> _`
+   |     |
+   |     required by a bound introduced by this call
+...
+LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
+   | ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
+   |
+note: required by a bound in `do_something`
+  --> $DIR/issue-88382.rs:21:56
+   |
+LL | fn do_something<I: Iterable>(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) {
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs
new file mode 100644
index 0000000000000..7e62790cc50c3
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs
@@ -0,0 +1,31 @@
+// check-fail
+
+// This should pass, but has a missed normalization due to HRTB.
+
+#![feature(generic_associated_types)]
+
+pub trait Marker {}
+
+pub trait Trait {
+    type Assoc<'a>;
+}
+
+fn test<T>(value: T)
+where
+    T: Trait,
+    for<'a> T::Assoc<'a>: Marker,
+{
+}
+
+impl Marker for () {}
+
+struct Foo;
+
+impl Trait for Foo {
+    type Assoc<'a> = ();
+}
+
+fn main() {
+    test(Foo);
+    //~^ the trait bound
+}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
new file mode 100644
index 0000000000000..604658da7d2c2
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
+  --> $DIR/issue-88460.rs:29:5
+   |
+LL |     test(Foo);
+   |     ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
+   |
+note: required by a bound in `test`
+  --> $DIR/issue-88460.rs:16:27
+   |
+LL | fn test<T>(value: T)
+   |    ---- required by a bound in this
+...
+LL |     for<'a> T::Assoc<'a>: Marker,
+   |                           ^^^^^^ required by this bound in `test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs
new file mode 100644
index 0000000000000..90568fcb40125
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs
@@ -0,0 +1,34 @@
+// check-fail
+
+// This should pass, but requires more logic.
+
+#![feature(generic_associated_types)]
+
+trait A {
+    type I<'a>;
+}
+
+pub struct TestA<F>
+{
+    f: F,
+}
+
+impl<F> A for TestA<F> {
+    type I<'a> = &'a F;
+}
+
+struct TestB<Q, F>
+{
+    q: Q,
+    f: F,
+}
+
+impl<'q, Q, I, F> A for TestB<Q, F> //~ the type parameter
+where
+    Q: A<I<'q> = &'q I>,
+    F: Fn(I),
+{
+    type I<'a> = ();
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr
new file mode 100644
index 0000000000000..ccc5ae0b621a1
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/issue-88526.rs:26:13
+   |
+LL | impl<'q, Q, I, F> A for TestB<Q, F>
+   |             ^ unconstrained type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs
new file mode 100644
index 0000000000000..5d850849fd21c
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs
@@ -0,0 +1,43 @@
+// check-fail
+// edition:2021
+
+// This should pass, but seems to run into a TAIT bug.
+
+#![feature(type_alias_impl_trait)]
+#![feature(generic_associated_types)]
+
+use std::future::Future;
+
+trait Stream {
+    type Item;
+}
+
+struct Empty<T>(T);
+impl<T> Stream for Empty<T> {
+    type Item = ();
+}
+fn empty<T>() -> Empty<T> {
+    todo!()
+}
+
+trait X {
+    type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a;
+
+    type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;
+
+    fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>;
+}
+
+struct Y;
+
+impl X for Y {
+    type LineStream<'a, Repr> = impl Stream<Item = Repr>; //~ could not find
+
+    type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;
+
+    fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { //~ type mismatch
+        async {empty()}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
new file mode 100644
index 0000000000000..48745fe0fbd96
--- /dev/null
+++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
@@ -0,0 +1,21 @@
+error[E0271]: type mismatch resolving `<impl Future<Output = [async output]> as Future>::Output == impl Stream<Item = Repr>`
+  --> $DIR/issue-89008.rs:38:43
+   |
+LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
+   |                                 ------------------------ the expected opaque type
+...
+LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found struct `Empty`
+   |
+   = note: expected opaque type `impl Stream<Item = Repr>`
+                   found struct `Empty<_>`
+
+error: could not find defining uses
+  --> $DIR/issue-89008.rs:34:33
+   |
+LL |     type LineStream<'a, Repr> = impl Stream<Item = Repr>;
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs
new file mode 100644
index 0000000000000..2b82d2946b3ba
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-91139.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Foo<T> {
+    type Type<'a>
+    where
+        T: 'a;
+}
+
+impl<T> Foo<T> for () {
+    type Type<'a>
+    where
+        T: 'a,
+    = ();
+}
+
+fn foo<T>() {
+    let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+}
+
+pub fn main() {}
diff --git a/src/test/ui/impl-trait/example-calendar.rs b/src/test/ui/impl-trait/example-calendar.rs
index 45dcb74a6e05c..da45f0d133deb 100644
--- a/src/test/ui/impl-trait/example-calendar.rs
+++ b/src/test/ui/impl-trait/example-calendar.rs
@@ -1,5 +1,4 @@
 // run-pass
-// ignore-compare-mode-chalk
 
 #![feature(fn_traits,
            step_trait,
diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs
index a519397806e07..17a6a85787442 100644
--- a/src/test/ui/impl-trait/issue-55872-2.rs
+++ b/src/test/ui/impl-trait/issue-55872-2.rs
@@ -1,5 +1,4 @@
 // edition:2018
-// ignore-compare-mode-chalk
 
 #![feature(type_alias_impl_trait)]
 
diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr
index 97545ba3d1124..b76b564dfb139 100644
--- a/src/test/ui/impl-trait/issue-55872-2.stderr
+++ b/src/test/ui/impl-trait/issue-55872-2.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `impl Future<Output = [async output]>: Copy` is not satisfied
-  --> $DIR/issue-55872-2.rs:14:20
+  --> $DIR/issue-55872-2.rs:13:20
    |
 LL |     fn foo<T>() -> Self::E {
    |                    ^^^^^^^ the trait `Copy` is not implemented for `impl Future<Output = [async output]>`
 
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-2.rs:14:28
+  --> $DIR/issue-55872-2.rs:13:28
    |
 LL |       fn foo<T>() -> Self::E {
    |  ____________________________^
diff --git a/src/test/ui/impl-trait/issue-55872.rs b/src/test/ui/impl-trait/issue-55872.rs
index bbd940254178c..183728b0f7f0a 100644
--- a/src/test/ui/impl-trait/issue-55872.rs
+++ b/src/test/ui/impl-trait/issue-55872.rs
@@ -1,4 +1,3 @@
-// ignore-compare-mode-chalk
 #![feature(type_alias_impl_trait)]
 
 pub trait Bar {
diff --git a/src/test/ui/impl-trait/issue-55872.stderr b/src/test/ui/impl-trait/issue-55872.stderr
index 60654ec34610f..39d870dc003bb 100644
--- a/src/test/ui/impl-trait/issue-55872.stderr
+++ b/src/test/ui/impl-trait/issue-55872.stderr
@@ -1,5 +1,5 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872.rs:13:28
+  --> $DIR/issue-55872.rs:12:28
    |
 LL |       fn foo<T>() -> Self::E {
    |  ____________________________^
diff --git a/src/test/ui/impl-trait/issues/issue-65581.rs b/src/test/ui/impl-trait/issues/issue-65581.rs
index af65b79d3e838..b947fc1d2396f 100644
--- a/src/test/ui/impl-trait/issues/issue-65581.rs
+++ b/src/test/ui/impl-trait/issues/issue-65581.rs
@@ -1,4 +1,5 @@
 // check-pass
+// ignore-compare-mode-chalk
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/issues/issue-23122-1.rs b/src/test/ui/issues/issue-23122-1.rs
index efa4e614be5b0..7fe0900ed5fde 100644
--- a/src/test/ui/issues/issue-23122-1.rs
+++ b/src/test/ui/issues/issue-23122-1.rs
@@ -1,10 +1,10 @@
-// ignore-compare-mode-chalk
-
 trait Next {
     type Next: Next;
 }
 
-struct GetNext<T: Next> { t: T }
+struct GetNext<T: Next> {
+    t: T,
+}
 
 impl<T: Next> Next for GetNext<T> {
     type Next = <GetNext<T> as Next>::Next;
diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs
index 7866b931ec4b9..95e1f60d8b029 100644
--- a/src/test/ui/issues/issue-23122-2.rs
+++ b/src/test/ui/issues/issue-23122-2.rs
@@ -1,9 +1,10 @@
-// ignore-compare-mode-chalk
 trait Next {
     type Next: Next;
 }
 
-struct GetNext<T: Next> { t: T }
+struct GetNext<T: Next> {
+    t: T,
+}
 
 impl<T: Next> Next for GetNext<T> {
     type Next = <GetNext<T::Next> as Next>::Next;
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index b345e90178742..7519e632d5446 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -1,12 +1,12 @@
 error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:9:17
+  --> $DIR/issue-23122-2.rs:10:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
 note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
-  --> $DIR/issue-23122-2.rs:8:15
+  --> $DIR/issue-23122-2.rs:9:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |               ^^^^     ^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-28561.rs b/src/test/ui/issues/issue-28561.rs
index 184f5cb26c546..1241fb0b1f85f 100644
--- a/src/test/ui/issues/issue-28561.rs
+++ b/src/test/ui/issues/issue-28561.rs
@@ -1,5 +1,4 @@
 // check-pass
-// ignore-compare-mode-chalk
 #[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
 struct Array<T> {
     f00: [T; 00],
diff --git a/src/test/ui/issues/issue-33187.rs b/src/test/ui/issues/issue-33187.rs
index f6b56610ec7d9..8db9e00588564 100644
--- a/src/test/ui/issues/issue-33187.rs
+++ b/src/test/ui/issues/issue-33187.rs
@@ -1,10 +1,15 @@
 // run-pass
-// ignore-compare-mode-chalk
+
 struct Foo<A: Repr>(<A as Repr>::Data);
 
-impl<A> Copy for Foo<A> where <A as Repr>::Data: Copy { }
-impl<A> Clone for Foo<A> where <A as Repr>::Data: Clone {
-    fn clone(&self) -> Self { Foo(self.0.clone()) }
+impl<A> Copy for Foo<A> where <A as Repr>::Data: Copy {}
+impl<A> Clone for Foo<A>
+where
+    <A as Repr>::Data: Clone,
+{
+    fn clone(&self) -> Self {
+        Foo(self.0.clone())
+    }
 }
 
 trait Repr {
@@ -15,5 +20,4 @@ impl<A> Repr for A {
     type Data = u32;
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/issues/issue-37051.rs b/src/test/ui/issues/issue-37051.rs
index e0c47197eaa03..9cae6cf5e7665 100644
--- a/src/test/ui/issues/issue-37051.rs
+++ b/src/test/ui/issues/issue-37051.rs
@@ -1,5 +1,4 @@
 // check-pass
-// ignore-compare-mode-chalk
 
 #![feature(associated_type_defaults)]
 
diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/issues/issue-55796.rs
index 1086669ee7463..d802ce3b6cfbf 100644
--- a/src/test/ui/issues/issue-55796.rs
+++ b/src/test/ui/issues/issue-55796.rs
@@ -1,5 +1,3 @@
-// ignore-compare-mode-chalk
-
 pub trait EdgeTrait<N> {
     fn target(&self) -> N;
 }
@@ -16,12 +14,12 @@ pub trait Graph<'a> {
 
     fn out_neighbors(&'a self, u: &Self::Node) -> Box<dyn Iterator<Item = Self::Node>> {
         Box::new(self.out_edges(u).map(|e| e.target()))
-//~^ ERROR cannot infer
+        //~^ ERROR cannot infer
     }
 
     fn in_neighbors(&'a self, u: &Self::Node) -> Box<dyn Iterator<Item = Self::Node>> {
         Box::new(self.in_edges(u).map(|e| e.target()))
-//~^ ERROR cannot infer
+        //~^ ERROR cannot infer
     }
 }
 
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
index 304339657f0a9..569a13f45bce8 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -1,22 +1,22 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/issue-55796.rs:18:9
+  --> $DIR/issue-55796.rs:16:9
    |
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
-  --> $DIR/issue-55796.rs:7:17
+  --> $DIR/issue-55796.rs:5:17
    |
 LL | pub trait Graph<'a> {
    |                 ^^
-note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:18:40: 18:54]>` will meet its required lifetime bounds
-  --> $DIR/issue-55796.rs:18:9
+note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:16:40: 16:54]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:16:9
    |
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the types are compatible
-  --> $DIR/issue-55796.rs:18:9
+  --> $DIR/issue-55796.rs:16:9
    |
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,24 +24,24 @@ LL |         Box::new(self.out_edges(u).map(|e| e.target()))
               found `Box<dyn Iterator<Item = <Self as Graph<'a>>::Node>>`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/issue-55796.rs:23:9
+  --> $DIR/issue-55796.rs:21:9
    |
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
-  --> $DIR/issue-55796.rs:7:17
+  --> $DIR/issue-55796.rs:5:17
    |
 LL | pub trait Graph<'a> {
    |                 ^^
-note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:23:39: 23:53]>` will meet its required lifetime bounds
-  --> $DIR/issue-55796.rs:23:9
+note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:21:39: 21:53]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:21:9
    |
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the types are compatible
-  --> $DIR/issue-55796.rs:23:9
+  --> $DIR/issue-55796.rs:21:9
    |
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs b/src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs
index 44ea9f12d38ff..36e9932602fb0 100644
--- a/src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs
+++ b/src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs
@@ -1,6 +1,5 @@
 // build-pass
 // ignore-tidy-filelength
-// ignore-compare-mode-chalk
 #![crate_type = "rlib"]
 
 fn banana(v: &str) -> u32 {
diff --git a/src/test/ui/nll/ty-outlives/issue-53789-2.rs b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
index d15e402460794..5109a0e4a683d 100644
--- a/src/test/ui/nll/ty-outlives/issue-53789-2.rs
+++ b/src/test/ui/nll/ty-outlives/issue-53789-2.rs
@@ -1,16 +1,14 @@
 // Regression test for #53789.
 //
 // check-pass
-// ignore-compare-mode-chalk
 
+use std::cmp::Ord;
 use std::collections::BTreeMap;
 use std::ops::Range;
-use std::cmp::Ord;
 
 macro_rules! valuetree {
     () => {
-        type ValueTree =
-            <Self::Strategy as $crate::Strategy>::Value;
+        type ValueTree = <Self::Strategy as $crate::Strategy>::Value;
     };
 }
 
@@ -41,7 +39,9 @@ macro_rules! product_type {
 macro_rules! default {
     ($type: ty, $val: expr) => {
         impl Default for $type {
-            fn default() -> Self { $val.into() }
+            fn default() -> Self {
+                $val.into()
+            }
         }
     };
 }
@@ -90,21 +90,17 @@ trait ValueTree {
 }
 
 trait Strategy {
-    type Value : ValueTree;
+    type Value: ValueTree;
 }
 
 #[derive(Clone)]
-struct VecStrategy<T : Strategy> {
+struct VecStrategy<T: Strategy> {
     element: T,
     size: Range<usize>,
 }
 
-fn vec<T : Strategy>(element: T, size: Range<usize>)
-                     -> VecStrategy<T> {
-    VecStrategy {
-        element: element,
-        size: size,
-    }
+fn vec<T: Strategy>(element: T, size: Range<usize>) -> VecStrategy<T> {
+    VecStrategy { element: element, size: size }
 }
 
 type ValueFor<S> = <<S as Strategy>::Value as ValueTree>::Value;
@@ -124,7 +120,6 @@ type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy;
 struct SizeBounds(Range<usize>);
 default!(SizeBounds, 0..100);
 
-
 impl From<Range<usize>> for SizeBounds {
     fn from(high: Range<usize>) -> Self {
         unimplemented!()
@@ -137,24 +132,26 @@ impl From<SizeBounds> for Range<usize> {
     }
 }
 
-
-fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters)
-                                  -> StrategyType<'a, A> {
+fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> {
     unimplemented!()
 }
 
-impl<K: ValueTree, V: ValueTree> Strategy for (K, V) where
-    <K as ValueTree>::Value: Ord {
+impl<K: ValueTree, V: ValueTree> Strategy for (K, V)
+where
+    <K as ValueTree>::Value: Ord,
+{
     type Value = TupleValueTree<(K, V)>;
 }
 
-impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)> where
-    <K as ValueTree>::Value: Ord {
+impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)>
+where
+    <K as ValueTree>::Value: Ord,
+{
     type Value = BTreeMapValueTree<K, V>;
 }
 
 #[derive(Clone)]
-struct VecValueTree<T : ValueTree> {
+struct VecValueTree<T: ValueTree> {
     elements: Vec<T>,
 }
 
@@ -185,8 +182,8 @@ impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B>
 where
     A: Arbitrary<'static> + Ord,
     B: Arbitrary<'static>,
-StrategyFor<A>: 'static,
-StrategyFor<B>: 'static,
+    StrategyFor<A>: 'static,
+    StrategyFor<B>: 'static,
 {
     valuetree!();
     type Parameters = RangedParams2<A::Parameters, B::Parameters>;
@@ -208,10 +205,14 @@ mapfn! {
     }
 }
 
-fn btree_map<K : Strategy + 'static, V : Strategy + 'static>
-    (key: K, value: V, size: Range<usize>)
-     -> BTreeMapStrategy<K, V>
-where ValueFor<K> : Ord {
+fn btree_map<K: Strategy + 'static, V: Strategy + 'static>(
+    key: K,
+    value: V,
+    size: Range<usize>,
+) -> BTreeMapStrategy<K, V>
+where
+    ValueFor<K>: Ord,
+{
     unimplemented!()
 }
 
@@ -245,4 +246,4 @@ mod statics {
     }
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.rs b/src/test/ui/specialization/default-associated-type-bound-1.rs
similarity index 95%
rename from src/test/ui/specialization/deafult-associated-type-bound-1.rs
rename to src/test/ui/specialization/default-associated-type-bound-1.rs
index 6eb2aa980d152..c043114b565c8 100644
--- a/src/test/ui/specialization/deafult-associated-type-bound-1.rs
+++ b/src/test/ui/specialization/default-associated-type-bound-1.rs
@@ -1,6 +1,5 @@
 // Check that we check that default associated types satisfy the required
 // bounds on them.
-// ignore-compare-mode-chalk
 
 #![feature(specialization)]
 //~^ WARNING `specialization` is incomplete
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr b/src/test/ui/specialization/default-associated-type-bound-1.stderr
similarity index 84%
rename from src/test/ui/specialization/deafult-associated-type-bound-1.stderr
rename to src/test/ui/specialization/default-associated-type-bound-1.stderr
index 9e400f8702474..6680a29f94245 100644
--- a/src/test/ui/specialization/deafult-associated-type-bound-1.stderr
+++ b/src/test/ui/specialization/default-associated-type-bound-1.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deafult-associated-type-bound-1.rs:5:12
+  --> $DIR/default-associated-type-bound-1.rs:4:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -9,13 +9,13 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
 
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/deafult-associated-type-bound-1.rs:19:22
+  --> $DIR/default-associated-type-bound-1.rs:18:22
    |
 LL |     default type U = str;
    |                      ^^^ the trait `Clone` is not implemented for `str`
    |
 note: required by a bound in `X::U`
-  --> $DIR/deafult-associated-type-bound-1.rs:9:13
+  --> $DIR/default-associated-type-bound-1.rs:8:13
    |
 LL |     type U: Clone;
    |             ^^^^^ required by this bound in `X::U`
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.rs b/src/test/ui/specialization/default-associated-type-bound-2.rs
similarity index 100%
rename from src/test/ui/specialization/deafult-associated-type-bound-2.rs
rename to src/test/ui/specialization/default-associated-type-bound-2.rs
diff --git a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr b/src/test/ui/specialization/default-associated-type-bound-2.stderr
similarity index 88%
rename from src/test/ui/specialization/deafult-associated-type-bound-2.stderr
rename to src/test/ui/specialization/default-associated-type-bound-2.stderr
index 47ea69d40bbb7..0fd1f65b0a201 100644
--- a/src/test/ui/specialization/deafult-associated-type-bound-2.stderr
+++ b/src/test/ui/specialization/default-associated-type-bound-2.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deafult-associated-type-bound-2.rs:2:12
+  --> $DIR/default-associated-type-bound-2.rs:2:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -9,14 +9,14 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
 
 error[E0277]: can't compare `&'static B` with `B`
-  --> $DIR/deafult-associated-type-bound-2.rs:16:22
+  --> $DIR/default-associated-type-bound-2.rs:16:22
    |
 LL |     default type U = &'static B;
    |                      ^^^^^^^^^^ no implementation for `&'static B == B`
    |
    = help: the trait `PartialEq<B>` is not implemented for `&'static B`
 note: required by a bound in `X::U`
-  --> $DIR/deafult-associated-type-bound-2.rs:6:13
+  --> $DIR/default-associated-type-bound-2.rs:6:13
    |
 LL |     type U: PartialEq<T>;
    |             ^^^^^^^^^^^^ required by this bound in `X::U`
diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.rs b/src/test/ui/specialization/default-generic-associated-type-bound.rs
similarity index 100%
rename from src/test/ui/specialization/deafult-generic-associated-type-bound.rs
rename to src/test/ui/specialization/default-generic-associated-type-bound.rs
diff --git a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
similarity index 86%
rename from src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
rename to src/test/ui/specialization/default-generic-associated-type-bound.stderr
index da5fe97cf1b8b..58c6667c8c7ad 100644
--- a/src/test/ui/specialization/deafult-generic-associated-type-bound.stderr
+++ b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/deafult-generic-associated-type-bound.rs:3:12
+  --> $DIR/default-generic-associated-type-bound.rs:3:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
@@ -9,14 +9,14 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
 
 error[E0277]: can't compare `T` with `T`
-  --> $DIR/deafult-generic-associated-type-bound.rs:18:26
+  --> $DIR/default-generic-associated-type-bound.rs:18:26
    |
 LL |     default type U<'a> = &'a T;
    |                          ^^^^^ no implementation for `T == T`
    |
    = note: required because of the requirements on the impl of `PartialEq` for `&'a T`
 note: required by a bound in `X::U`
-  --> $DIR/deafult-generic-associated-type-bound.rs:8:17
+  --> $DIR/default-generic-associated-type-bound.rs:8:17
    |
 LL |     type U<'a>: PartialEq<&'a Self> where Self: 'a;
    |                 ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U`
diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.rs b/src/test/ui/type-alias-impl-trait/issue-53598.rs
index 37b330ba4b8fc..f936dc42f133d 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53598.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53598.rs
@@ -1,4 +1,3 @@
-// ignore-compare-mode-chalk
 #![feature(type_alias_impl_trait)]
 
 use std::fmt::Debug;
diff --git a/src/test/ui/type-alias-impl-trait/issue-53598.stderr b/src/test/ui/type-alias-impl-trait/issue-53598.stderr
index 4c8144a235930..9971c7e0e20ee 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53598.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53598.stderr
@@ -1,5 +1,5 @@
 error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-53598.rs:20:42
+  --> $DIR/issue-53598.rs:19:42
    |
 LL |       fn foo<T: Debug>(_: T) -> Self::Item {
    |  __________________________________________^
diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.rs b/src/test/ui/type-alias-impl-trait/issue-57700.rs
index f1db4d3291b40..13a6b7c2f7ceb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57700.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-57700.rs
@@ -1,4 +1,3 @@
-// ignore-compare-mode-chalk
 #![feature(arbitrary_self_types)]
 #![feature(type_alias_impl_trait)]
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-57700.stderr b/src/test/ui/type-alias-impl-trait/issue-57700.stderr
index c701e3e74ef59..b2e3f46f1f582 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57700.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57700.stderr
@@ -1,5 +1,5 @@
 error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-57700.rs:16:58
+  --> $DIR/issue-57700.rs:15:58
    |
 LL |       fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
    |  __________________________________________________________^
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.rs b/src/test/ui/type-alias-impl-trait/issue-60371.rs
index 9d2ba849c8667..badf35484f360 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.rs
@@ -1,5 +1,3 @@
-// ignore-compare-mode-chalk
-
 trait Bug {
     type Item: Bug;
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
index 62ab7eb456010..dc8a381aece94 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/issue-60371.rs:10:17
+  --> $DIR/issue-60371.rs:8:17
    |
 LL |     type Item = impl Bug;
    |                 ^^^^^^^^
@@ -8,7 +8,7 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `(): Bug` is not satisfied
-  --> $DIR/issue-60371.rs:12:40
+  --> $DIR/issue-60371.rs:10:40
    |
 LL |     const FUN: fn() -> Self::Item = || ();
    |                                        ^ the trait `Bug` is not implemented for `()`
@@ -17,7 +17,7 @@ LL |     const FUN: fn() -> Self::Item = || ();
              <&() as Bug>
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60371.rs:12:37
+  --> $DIR/issue-60371.rs:10:37
    |
 LL | impl Bug for &() {
    |              - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 94e82e3d9f766..46daaf42883f0 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -182,8 +182,9 @@ impl Checker {
     fn walk(&mut self, dir: &Path, report: &mut Report) {
         for entry in t!(dir.read_dir()).map(|e| t!(e)) {
             let path = entry.path();
-            let kind = t!(entry.file_type());
-            if kind.is_dir() {
+            // Goes through symlinks
+            let metadata = t!(fs::metadata(&path));
+            if metadata.is_dir() {
                 self.walk(&path, report);
             } else {
                 self.check(&path, report);
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index 8ea6bb308b7ba..2a23d72edc064 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -1,7 +1,7 @@
 //! Checks that all error codes have at least one test to prevent having error
 //! codes that are silently not thrown by the compiler anymore.
 
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
 use std::fs::read_to_string;
 use std::path::Path;
@@ -205,6 +205,7 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
     let mut found_explanations = 0;
     let mut found_tests = 0;
     let mut error_codes: HashMap<String, ErrorCodeStatus> = HashMap::new();
+    let mut explanations: HashSet<String> = HashSet::new();
     // We want error codes which match the following cases:
     //
     // * foo(a, E0111, a)
@@ -218,17 +219,27 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
     for path in paths {
         super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| {
             let file_name = entry.file_name();
+            let entry_path = entry.path();
+
             if file_name == "error_codes.rs" {
                 extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors);
                 found_explanations += 1;
-            } else if entry.path().extension() == Some(OsStr::new("stderr")) {
+            } else if entry_path.extension() == Some(OsStr::new("stderr")) {
                 extract_error_codes_from_tests(contents, &mut error_codes);
                 found_tests += 1;
-            } else if entry.path().extension() == Some(OsStr::new("rs")) {
+            } else if entry_path.extension() == Some(OsStr::new("rs")) {
                 let path = entry.path().to_string_lossy();
                 if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) {
                     extract_error_codes_from_source(contents, &mut error_codes, &regex);
                 }
+            } else if entry_path
+                .parent()
+                .and_then(|p| p.file_name())
+                .map(|p| p == "error_codes")
+                .unwrap_or(false)
+                && entry_path.extension() == Some(OsStr::new("md"))
+            {
+                explanations.insert(file_name.to_str().unwrap().replace(".md", ""));
             }
         });
     }
@@ -240,6 +251,10 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
         eprintln!("No error code was found in compilation errors!");
         *bad = true;
     }
+    if explanations.is_empty() {
+        eprintln!("No error code explanation was found!");
+        *bad = true;
+    }
     if errors.is_empty() {
         println!("Found {} error codes", error_codes.len());
 
@@ -282,11 +297,21 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
             }
         }
     }
+    if errors.is_empty() {
+        for explanation in explanations {
+            if !error_codes.contains_key(&explanation) {
+                errors.push(format!(
+                    "{} error code explanation should be listed in `error_codes.rs`",
+                    explanation
+                ));
+            }
+        }
+    }
     errors.sort();
     for err in &errors {
         eprintln!("{}", err);
     }
-    println!("Found {} error codes with no tests", errors.len());
+    println!("Found {} error(s) in error codes", errors.len());
     if !errors.is_empty() {
         *bad = true;
     }