about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock13
-rw-r--r--compiler/rustc_ast/src/ast.rs2
-rw-r--r--compiler/rustc_ast/src/node_id.rs2
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml2
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml1
-rw-r--r--compiler/rustc_ast_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pp.rs17
-rw-r--r--compiler/rustc_ast_pretty/src/pp/convenience.rs2
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs272
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/delimited.rs41
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs16
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs15
-rw-r--r--compiler/rustc_borrowck/Cargo.toml3
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs1
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs1
-rw-r--r--compiler/rustc_borrowck/src/location.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs1
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs2
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml2
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs1
-rw-r--r--compiler/rustc_hir/src/hir_id.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs18
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs2
-rw-r--r--compiler/rustc_index/src/vec/tests.rs1
-rw-r--r--compiler/rustc_index_macros/src/lib.rs15
-rw-r--r--compiler/rustc_index_macros/src/newtype.rs12
-rw-r--r--compiler/rustc_infer/Cargo.toml1
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--compiler/rustc_lint/src/levels.rs1
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs157
-rw-r--r--compiler/rustc_middle/src/middle/region.rs2
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/mir/query.rs1
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs21
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs44
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs9
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs1
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs1
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs2
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs1
-rw-r--r--compiler/rustc_passes/Cargo.toml3
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs1
-rw-r--r--compiler/rustc_session/src/config.rs3
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs71
-rw-r--r--compiler/rustc_span/src/def_id.rs5
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/abi/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs1
-rw-r--r--compiler/rustc_transmute/Cargo.toml2
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml2
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs256
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs4
-rw-r--r--compiler/rustc_type_ir/src/interner.rs16
-rw-r--r--compiler/rustc_type_ir/src/lib.rs13
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs6
-rw-r--r--compiler/stable_mir/src/lib.rs2
-rw-r--r--compiler/stable_mir/src/mir/body.rs50
-rw-r--r--compiler/stable_mir/src/mir/visit.rs28
-rw-r--r--src/bootstrap/src/bin/rustc.rs2
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/formats/item_type.rs51
-rw-r--r--src/librustdoc/html/static/js/search.js52
-rw-r--r--src/tools/clippy/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/declare_clippy_lint/Cargo.toml2
-rw-r--r--src/tools/rustfmt/Cargo.toml2
-rw-r--r--tests/rustdoc-js-std/keyword.js4
-rw-r--r--tests/rustdoc-js-std/macro-check.js4
-rw-r--r--tests/rustdoc-js-std/parser-bindings.js8
-rw-r--r--tests/rustdoc-js-std/parser-filter.js22
-rw-r--r--tests/rustdoc-js-std/parser-ident.js6
-rw-r--r--tests/rustdoc-js-std/parser-returned.js2
-rw-r--r--tests/rustdoc-js-std/parser-slice-array.js20
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/cargo-feature.rs14
-rw-r--r--tests/ui/check-cfg/cargo-feature.stderr11
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr16
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr16
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.rs8
-rw-r--r--tests/ui/check-cfg/exhaustive-names.empty_names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr2
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-names.rs1
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr16
-rw-r--r--tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs29
-rw-r--r--tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr9
102 files changed, 954 insertions, 573 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ad6dac97a0a..8c9b12028f0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2060,9 +2060,9 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.10.5"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
 dependencies = [
  "either",
 ]
@@ -3471,6 +3471,7 @@ dependencies = [
 name = "rustc_ast_pretty"
 version = "0.0.0"
 dependencies = [
+ "itertools",
  "rustc_ast",
  "rustc_span",
  "thin-vec",
@@ -3523,7 +3524,6 @@ dependencies = [
  "rustc_macros",
  "rustc_middle",
  "rustc_mir_dataflow",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -3934,7 +3934,6 @@ dependencies = [
  "rustc_lint",
  "rustc_macros",
  "rustc_middle",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -3997,7 +3996,6 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
- "rustc_serialize",
  "rustc_span",
  "rustc_target",
  "smallvec",
@@ -4215,7 +4213,6 @@ dependencies = [
  "rustc_infer",
  "rustc_macros",
  "rustc_middle",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4239,7 +4236,6 @@ dependencies = [
  "rustc_index",
  "rustc_macros",
  "rustc_middle",
- "rustc_serialize",
  "rustc_span",
  "rustc_target",
  "smallvec",
@@ -4266,7 +4262,6 @@ dependencies = [
  "rustc_middle",
  "rustc_mir_build",
  "rustc_mir_dataflow",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4340,7 +4335,6 @@ dependencies = [
  "rustc_lexer",
  "rustc_macros",
  "rustc_middle",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4564,7 +4558,6 @@ dependencies = [
  "rustc_middle",
  "rustc_parse_format",
  "rustc_query_system",
- "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index c85ff6f5c44..83fe95f16f9 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2574,7 +2574,7 @@ pub enum AttrStyle {
 }
 
 rustc_index::newtype_index! {
-    #[custom_encodable]
+    #[orderable]
     #[debug_format = "AttrId({})"]
     pub struct AttrId {}
 }
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index d16741757d1..1cd24495309 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -8,6 +8,8 @@ rustc_index::newtype_index! {
     /// This is later turned into [`DefId`] and `HirId` for the HIR.
     ///
     /// [`DefId`]: rustc_span::def_id::DefId
+    #[encodable]
+    #[orderable]
     #[debug_format = "NodeId({})"]
     pub struct NodeId {
         /// The [`NodeId`] used to represent the root of the crate.
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 0001394c8d3..99e79f65fb4 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.10.1"
+itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index af1524c8baa..12a08f06558 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 thin-vec = "0.2.12"
diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs
index 9e4ffd8dd6a..670f2a45835 100644
--- a/compiler/rustc_ast_pretty/src/lib.rs
+++ b/compiler/rustc_ast_pretty/src/lib.rs
@@ -3,9 +3,7 @@
 #![doc(rust_logo)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![feature(associated_type_bounds)]
 #![feature(box_patterns)]
-#![feature(with_negative_coherence)]
 #![recursion_limit = "256"]
 
 mod helpers;
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index 7ab8c3eaba2..96f5eff6890 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -165,20 +165,20 @@ enum IndentStyle {
 }
 
 #[derive(Clone, Copy, Default, PartialEq)]
-pub struct BreakToken {
+pub(crate) struct BreakToken {
     offset: isize,
     blank_space: isize,
     pre_break: Option<char>,
 }
 
 #[derive(Clone, Copy, PartialEq)]
-pub struct BeginToken {
+pub(crate) struct BeginToken {
     indent: IndentStyle,
     breaks: Breaks,
 }
 
-#[derive(Clone, PartialEq)]
-pub enum Token {
+#[derive(PartialEq)]
+pub(crate) enum Token {
     // In practice a string token contains either a `&'static str` or a
     // `String`. `Cow` is overkill for this because we never modify the data,
     // but it's more convenient than rolling our own more specialized type.
@@ -229,7 +229,6 @@ pub struct Printer {
     last_printed: Option<Token>,
 }
 
-#[derive(Clone)]
 struct BufEntry {
     token: Token,
     size: isize,
@@ -251,16 +250,16 @@ impl Printer {
         }
     }
 
-    pub fn last_token(&self) -> Option<&Token> {
+    pub(crate) fn last_token(&self) -> Option<&Token> {
         self.last_token_still_buffered().or_else(|| self.last_printed.as_ref())
     }
 
-    pub fn last_token_still_buffered(&self) -> Option<&Token> {
+    pub(crate) fn last_token_still_buffered(&self) -> Option<&Token> {
         self.buf.last().map(|last| &last.token)
     }
 
     /// Be very careful with this!
-    pub fn replace_last_token_still_buffered(&mut self, token: Token) {
+    pub(crate) fn replace_last_token_still_buffered(&mut self, token: Token) {
         self.buf.last_mut().unwrap().token = token;
     }
 
@@ -314,7 +313,7 @@ impl Printer {
         }
     }
 
-    pub fn offset(&mut self, offset: isize) {
+    pub(crate) fn offset(&mut self, offset: isize) {
         if let Some(BufEntry { token: Token::Break(token), .. }) = &mut self.buf.last_mut() {
             token.offset += offset;
         }
diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs
index 93310dd45c5..c4c4fdce7fe 100644
--- a/compiler/rustc_ast_pretty/src/pp/convenience.rs
+++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs
@@ -66,7 +66,7 @@ impl Printer {
         }
     }
 
-    pub fn hardbreak_tok_offset(off: isize) -> Token {
+    pub(crate) fn hardbreak_tok_offset(off: isize) -> Token {
         Token::Break(BreakToken {
             offset: off,
             blank_space: SIZE_INFINITY,
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index e486ab8e3b8..da91c3c8a19 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1,4 +1,7 @@
-mod delimited;
+//! AST pretty printing.
+//!
+//! Note that HIR pretty printing is layered on top of this crate.
+
 mod expr;
 mod item;
 
@@ -23,8 +26,6 @@ use rustc_span::{BytePos, FileName, Span, DUMMY_SP};
 use std::borrow::Cow;
 use thin_vec::ThinVec;
 
-pub use self::delimited::IterDelimited;
-
 pub enum MacHeader<'a> {
     Path(&'a ast::Path),
     Keyword(&'static str),
@@ -46,8 +47,7 @@ pub trait PpAnn {
     fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
 }
 
-#[derive(Copy, Clone)]
-pub struct NoAnn;
+struct NoAnn;
 
 impl PpAnn for NoAnn {}
 
@@ -64,11 +64,11 @@ impl<'a> Comments<'a> {
     }
 
     // FIXME: This shouldn't probably clone lmao
-    pub fn next(&self) -> Option<Comment> {
+    fn next(&self) -> Option<Comment> {
         self.comments.get(self.current).cloned()
     }
 
-    pub fn trailing_comment(
+    fn trailing_comment(
         &self,
         span: rustc_span::Span,
         next_pos: Option<BytePos>,
@@ -95,7 +95,7 @@ pub struct State<'a> {
     ann: &'a (dyn PpAnn + 'a),
 }
 
-pub(crate) const INDENT_UNIT: isize = 4;
+const INDENT_UNIT: isize = 4;
 
 /// Requires you to pass an input filename and reader so that
 /// it can scan the input text for comments to copy forward.
@@ -220,7 +220,7 @@ fn doc_comment_to_string(
     }
 }
 
-pub fn literal_to_string(lit: token::Lit) -> String {
+fn literal_to_string(lit: token::Lit) -> String {
     let token::Lit { kind, symbol, suffix } = lit;
     let mut out = match kind {
         token::Byte => format!("b'{symbol}'"),
@@ -260,11 +260,17 @@ impl std::ops::DerefMut for State<'_> {
     }
 }
 
+/// This trait is used for both AST and HIR pretty-printing.
 pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
     fn comments(&mut self) -> &mut Option<Comments<'a>>;
-    fn print_ident(&mut self, ident: Ident);
+    fn ann_post(&mut self, ident: Ident);
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
 
+    fn print_ident(&mut self, ident: Ident) {
+        self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
+        self.ann_post(ident)
+    }
+
     fn strsep<T, F>(
         &mut self,
         sep: &'static str,
@@ -401,15 +407,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         }
     }
 
-    fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
-        self.print_token_literal(lit.as_token_lit(), lit.span)
-    }
-
-    fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
-        self.maybe_print_comment(span.lo());
-        self.word(token_lit.to_string())
-    }
-
     fn print_string(&mut self, st: &str, style: ast::StrStyle) {
         let st = match style {
             ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()),
@@ -420,30 +417,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         self.word(st)
     }
 
-    fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
-        self.print_string(sym.as_str(), style);
-    }
-
     fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
         self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
     }
 
-    fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
-        self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
-    }
-
     fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
         self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
     }
 
-    fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
-        self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
-    }
-
-    fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
-        self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
-    }
-
     fn print_either_attributes(
         &mut self,
         attrs: &[ast::Attribute],
@@ -467,10 +448,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         printed
     }
 
-    fn print_attribute(&mut self, attr: &ast::Attribute) {
-        self.print_attribute_inline(attr, false)
-    }
-
     fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) {
         if !is_inline {
             self.hardbreak_if_not_bol();
@@ -525,33 +502,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         self.end();
     }
 
-    fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
-        match item {
-            ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi),
-            ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit),
-        }
-    }
-
-    fn print_meta_item(&mut self, item: &ast::MetaItem) {
-        self.ibox(INDENT_UNIT);
-        match &item.kind {
-            ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
-            ast::MetaItemKind::NameValue(value) => {
-                self.print_path(&item.path, false, 0);
-                self.space();
-                self.word_space("=");
-                self.print_meta_item_lit(value);
-            }
-            ast::MetaItemKind::List(items) => {
-                self.print_path(&item.path, false, 0);
-                self.popen();
-                self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i));
-                self.pclose();
-            }
-        }
-        self.end();
-    }
-
     /// This doesn't deserve to be called "pretty" printing, but it should be
     /// meaning-preserving. A quick hack that might help would be to look at the
     /// spans embedded in the TTs to decide where to put spaces and newlines.
@@ -843,17 +793,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         Self::to_string(|s| s.print_type(ty))
     }
 
-    fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
-        Self::to_string(|s| s.print_type_bounds(bounds))
-    }
-
-    fn where_bound_predicate_to_string(
-        &self,
-        where_bound_predicate: &ast::WhereBoundPredicate,
-    ) -> String {
-        Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
-    }
-
     fn pat_to_string(&self, pat: &ast::Pat) -> String {
         Self::to_string(|s| s.print_pat(pat))
     }
@@ -866,14 +805,6 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         Self::to_string(|s| s.print_meta_item_lit(lit))
     }
 
-    fn tt_to_string(&self, tt: &TokenTree) -> String {
-        Self::to_string(|s| s.print_tt(tt, false))
-    }
-
-    fn tts_to_string(&self, tokens: &TokenStream) -> String {
-        Self::to_string(|s| s.print_tts(tokens, false))
-    }
-
     fn stmt_to_string(&self, stmt: &ast::Stmt) -> String {
         Self::to_string(|s| s.print_stmt(stmt))
     }
@@ -882,26 +813,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         Self::to_string(|s| s.print_item(i))
     }
 
-    fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String {
-        Self::to_string(|s| s.print_assoc_item(i))
-    }
-
-    fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String {
-        Self::to_string(|s| s.print_foreign_item(i))
-    }
-
-    fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
-        Self::to_string(|s| s.print_generic_params(generic_params))
-    }
-
     fn path_to_string(&self, p: &ast::Path) -> String {
         Self::to_string(|s| s.print_path(p, false, 0))
     }
 
-    fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
-        Self::to_string(|s| s.print_path_segment(p, false))
-    }
-
     fn vis_to_string(&self, v: &ast::Visibility) -> String {
         Self::to_string(|s| s.print_visibility(v))
     }
@@ -916,22 +831,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
         })
     }
 
-    fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
-        Self::to_string(|s| s.print_meta_list_item(li))
-    }
-
     fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String {
         Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
     }
 
-    fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
-        Self::to_string(|s| s.print_attribute(attr))
-    }
-
-    fn param_to_string(&self, arg: &ast::Param) -> String {
-        Self::to_string(|s| s.print_param(arg, false))
-    }
-
     fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
         let mut printer = State::new();
         f(&mut printer);
@@ -944,9 +847,8 @@ impl<'a> PrintState<'a> for State<'a> {
         &mut self.comments
     }
 
-    fn print_ident(&mut self, ident: Ident) {
-        self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
-        self.ann.post(self, AnnNode::Ident(&ident))
+    fn ann_post(&mut self, ident: Ident) {
+        self.ann.post(self, AnnNode::Ident(&ident));
     }
 
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) {
@@ -979,13 +881,8 @@ impl<'a> State<'a> {
         State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
     }
 
-    pub(crate) fn commasep_cmnt<T, F, G>(
-        &mut self,
-        b: Breaks,
-        elts: &[T],
-        mut op: F,
-        mut get_span: G,
-    ) where
+    fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
+    where
         F: FnMut(&mut State<'_>, &T),
         G: FnMut(&T) -> rustc_span::Span,
     {
@@ -1005,7 +902,7 @@ impl<'a> State<'a> {
         self.end();
     }
 
-    pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
+    fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
     }
 
@@ -1156,7 +1053,7 @@ impl<'a> State<'a> {
         self.print_trait_ref(&t.trait_ref)
     }
 
-    pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) {
+    fn print_stmt(&mut self, st: &ast::Stmt) {
         self.maybe_print_comment(st.span.lo());
         match &st.kind {
             ast::StmtKind::Local(loc) => {
@@ -1211,19 +1108,19 @@ impl<'a> State<'a> {
         self.maybe_print_trailing_comment(st.span, None)
     }
 
-    pub(crate) fn print_block(&mut self, blk: &ast::Block) {
+    fn print_block(&mut self, blk: &ast::Block) {
         self.print_block_with_attrs(blk, &[])
     }
 
-    pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
+    fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
         self.print_block_maybe_unclosed(blk, &[], false)
     }
 
-    pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
+    fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
         self.print_block_maybe_unclosed(blk, attrs, true)
     }
 
-    pub(crate) fn print_block_maybe_unclosed(
+    fn print_block_maybe_unclosed(
         &mut self,
         blk: &ast::Block,
         attrs: &[ast::Attribute],
@@ -1257,7 +1154,7 @@ impl<'a> State<'a> {
     }
 
     /// Print a `let pat = expr` expression.
-    pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
+    fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
         self.word("let ");
         self.print_pat(pat);
         self.space();
@@ -1266,7 +1163,7 @@ impl<'a> State<'a> {
         self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals())
     }
 
-    pub(crate) fn print_mac(&mut self, m: &ast::MacCall) {
+    fn print_mac(&mut self, m: &ast::MacCall) {
         self.print_mac_common(
             Some(MacHeader::Path(&m.path)),
             true,
@@ -1407,7 +1304,7 @@ impl<'a> State<'a> {
         self.pclose();
     }
 
-    pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) {
+    fn print_local_decl(&mut self, loc: &ast::Local) {
         self.print_pat(&loc.pat);
         if let Some(ty) = &loc.ty {
             self.word_space(":");
@@ -1415,7 +1312,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_name(&mut self, name: Symbol) {
+    fn print_name(&mut self, name: Symbol) {
         self.word(name.to_string());
         self.ann.post(self, AnnNode::Name(&name))
     }
@@ -1439,7 +1336,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_pat(&mut self, pat: &ast::Pat) {
+    fn print_pat(&mut self, pat: &ast::Pat) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
         /* Pat isn't normalized, but the beauty of it
@@ -1592,7 +1489,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) {
+    fn print_asyncness(&mut self, asyncness: ast::Async) {
         if asyncness.is_async() {
             self.word_nbsp("async");
         }
@@ -1637,11 +1534,11 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
+    fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
         self.print_name(lifetime.ident.name)
     }
 
-    pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
+    fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
         for (i, bound) in bounds.iter().enumerate() {
             if i != 0 {
                 self.word(" + ");
@@ -1653,7 +1550,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
+    fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
         if generic_params.is_empty() {
             return;
         }
@@ -1717,12 +1614,12 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
+    fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
         self.print_mutability(mt.mutbl, print_const);
         self.print_type(&mt.ty)
     }
 
-    pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
+    fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
         self.ibox(INDENT_UNIT);
 
         self.print_outer_attributes_inline(&input.attrs);
@@ -1750,7 +1647,7 @@ impl<'a> State<'a> {
         self.end();
     }
 
-    pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
+    fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
         if let ast::FnRetTy::Ty(ty) = fn_ret_ty {
             self.space_if_not_bol();
             self.ibox(INDENT_UNIT);
@@ -1761,7 +1658,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_ty_fn(
+    fn print_ty_fn(
         &mut self,
         ext: ast::Extern,
         unsafety: ast::Unsafe,
@@ -1785,7 +1682,7 @@ impl<'a> State<'a> {
         self.end();
     }
 
-    pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) {
+    fn print_fn_header_info(&mut self, header: ast::FnHeader) {
         self.print_constness(header.constness);
         self.print_asyncness(header.asyncness);
         self.print_unsafety(header.unsafety);
@@ -1805,24 +1702,107 @@ impl<'a> State<'a> {
         self.word("fn")
     }
 
-    pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) {
+    fn print_unsafety(&mut self, s: ast::Unsafe) {
         match s {
             ast::Unsafe::No => {}
             ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"),
         }
     }
 
-    pub(crate) fn print_constness(&mut self, s: ast::Const) {
+    fn print_constness(&mut self, s: ast::Const) {
         match s {
             ast::Const::No => {}
             ast::Const::Yes(_) => self.word_nbsp("const"),
         }
     }
 
-    pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) {
+    fn print_is_auto(&mut self, s: ast::IsAuto) {
         match s {
             ast::IsAuto::Yes => self.word_nbsp("auto"),
             ast::IsAuto::No => {}
         }
     }
+
+    fn print_meta_item_lit(&mut self, lit: &ast::MetaItemLit) {
+        self.print_token_literal(lit.as_token_lit(), lit.span)
+    }
+
+    fn print_token_literal(&mut self, token_lit: token::Lit, span: Span) {
+        self.maybe_print_comment(span.lo());
+        self.word(token_lit.to_string())
+    }
+
+    fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
+        self.print_string(sym.as_str(), style);
+    }
+
+    fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
+        self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
+    }
+
+    fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
+        self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
+    }
+
+    fn print_attribute(&mut self, attr: &ast::Attribute) {
+        self.print_attribute_inline(attr, false)
+    }
+
+    fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
+        match item {
+            ast::NestedMetaItem::MetaItem(mi) => self.print_meta_item(mi),
+            ast::NestedMetaItem::Lit(lit) => self.print_meta_item_lit(lit),
+        }
+    }
+
+    fn print_meta_item(&mut self, item: &ast::MetaItem) {
+        self.ibox(INDENT_UNIT);
+        match &item.kind {
+            ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
+            ast::MetaItemKind::NameValue(value) => {
+                self.print_path(&item.path, false, 0);
+                self.space();
+                self.word_space("=");
+                self.print_meta_item_lit(value);
+            }
+            ast::MetaItemKind::List(items) => {
+                self.print_path(&item.path, false, 0);
+                self.popen();
+                self.commasep(Consistent, items, |s, i| s.print_meta_list_item(i));
+                self.pclose();
+            }
+        }
+        self.end();
+    }
+
+    pub(crate) fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
+        Self::to_string(|s| s.print_type_bounds(bounds))
+    }
+
+    pub(crate) fn where_bound_predicate_to_string(
+        &self,
+        where_bound_predicate: &ast::WhereBoundPredicate,
+    ) -> String {
+        Self::to_string(|s| s.print_where_bound_predicate(where_bound_predicate))
+    }
+
+    pub(crate) fn tt_to_string(&self, tt: &TokenTree) -> String {
+        Self::to_string(|s| s.print_tt(tt, false))
+    }
+
+    pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String {
+        Self::to_string(|s| s.print_tts(tokens, false))
+    }
+
+    pub(crate) fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
+        Self::to_string(|s| s.print_path_segment(p, false))
+    }
+
+    pub(crate) fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
+        Self::to_string(|s| s.print_meta_list_item(li))
+    }
+
+    pub(crate) fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
+        Self::to_string(|s| s.print_attribute(attr))
+    }
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs b/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs
deleted file mode 100644
index fe0640baaa1..00000000000
--- a/compiler/rustc_ast_pretty/src/pprust/state/delimited.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-use std::iter::Peekable;
-use std::mem;
-use std::ops::Deref;
-
-pub struct Delimited<I: Iterator> {
-    is_first: bool,
-    iter: Peekable<I>,
-}
-
-pub trait IterDelimited: Iterator + Sized {
-    fn delimited(self) -> Delimited<Self> {
-        Delimited { is_first: true, iter: self.peekable() }
-    }
-}
-
-impl<I: Iterator> IterDelimited for I {}
-
-pub struct IteratorItem<T> {
-    value: T,
-    pub is_first: bool,
-    pub is_last: bool,
-}
-
-impl<I: Iterator> Iterator for Delimited<I> {
-    type Item = IteratorItem<I::Item>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let value = self.iter.next()?;
-        let is_first = mem::replace(&mut self.is_first, false);
-        let is_last = self.iter.peek().is_none();
-        Some(IteratorItem { value, is_first, is_last })
-    }
-}
-
-impl<T> Deref for IteratorItem<T> {
-    type Target = T;
-
-    fn deref(&self) -> &Self::Target {
-        &self.value
-    }
-}
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index edbc3500373..ed9b68a1d5a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -1,6 +1,6 @@
 use crate::pp::Breaks::Inconsistent;
-use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
-
+use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
+use itertools::{Itertools, Position};
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::util::literal::escape_byte_str_symbol;
@@ -149,10 +149,12 @@ impl<'a> State<'a> {
             return;
         }
         self.cbox(0);
-        for field in fields.iter().delimited() {
+        for (pos, field) in fields.iter().with_position() {
+            let is_first = matches!(pos, Position::First | Position::Only);
+            let is_last = matches!(pos, Position::Last | Position::Only);
             self.maybe_print_comment(field.span.hi());
             self.print_outer_attributes(&field.attrs);
-            if field.is_first {
+            if is_first {
                 self.space_if_not_bol();
             }
             if !field.is_shorthand {
@@ -160,7 +162,7 @@ impl<'a> State<'a> {
                 self.word_nbsp(":");
             }
             self.print_expr(&field.expr);
-            if !field.is_last || has_rest {
+            if !is_last || has_rest {
                 self.word_space(",");
             } else {
                 self.trailing_comma_or_space();
@@ -279,7 +281,7 @@ impl<'a> State<'a> {
         self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
     }
 
-    pub fn print_expr(&mut self, expr: &ast::Expr) {
+    pub(super) fn print_expr(&mut self, expr: &ast::Expr) {
         self.print_expr_outer_attr_style(expr, true)
     }
 
@@ -679,7 +681,7 @@ impl<'a> State<'a> {
     }
 }
 
-pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
+fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
     let mut template = "\"".to_string();
     for piece in pieces {
         match piece {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index e94bfd81658..fd5b529b1d4 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -1,8 +1,8 @@
 use crate::pp::Breaks::Inconsistent;
-use crate::pprust::state::delimited::IterDelimited;
 use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
 
 use ast::StaticItem;
+use itertools::{Itertools, Position};
 use rustc_ast as ast;
 use rustc_ast::GenericBound;
 use rustc_ast::ModKind;
@@ -20,7 +20,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
+    fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
         let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
@@ -518,7 +518,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) {
+    fn print_assoc_item(&mut self, item: &ast::AssocItem) {
         let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
         self.ann.pre(self, AnnNode::SubItem(id));
         self.hardbreak_if_not_bol();
@@ -621,7 +621,7 @@ impl<'a> State<'a> {
         self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
     }
 
-    pub(crate) fn print_where_clause_parts(
+    fn print_where_clause_parts(
         &mut self,
         has_where_token: bool,
         predicates: &[ast::WherePredicate],
@@ -668,7 +668,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_where_bound_predicate(
+    pub(crate) fn print_where_bound_predicate(
         &mut self,
         where_bound_predicate: &ast::WhereBoundPredicate,
     ) {
@@ -712,9 +712,10 @@ impl<'a> State<'a> {
                     self.word("{");
                     self.zerobreak();
                     self.ibox(0);
-                    for use_tree in items.iter().delimited() {
+                    for (pos, use_tree) in items.iter().with_position() {
+                        let is_last = matches!(pos, Position::Last | Position::Only);
                         self.print_use_tree(&use_tree.0);
-                        if !use_tree.is_last {
+                        if !is_last {
                             self.word(",");
                             if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
                                 self.hardbreak();
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 636817a7ce1..714f46270f9 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 either = "1.5.0"
-itertools = "0.10.1"
+itertools = "0.11"
 polonius-engine = "0.13.0"
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -19,7 +19,6 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index 315886bbe29..041ac75ec01 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -122,6 +122,7 @@ rustc_index::newtype_index! {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "ConstraintSccIndex({})"]
     pub struct ConstraintSccIndex {}
 }
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 8676d2ba7c4..27b558be3b7 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -109,6 +109,7 @@ impl_visitable! {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "bw{}"]
     pub struct BorrowIndex {}
 }
diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs
index 0e669abfd14..6f09393169f 100644
--- a/compiler/rustc_borrowck/src/location.rs
+++ b/compiler/rustc_borrowck/src/location.rs
@@ -20,6 +20,7 @@ pub struct LocationTable {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "LocationIndex({})"]
     pub struct LocationIndex {}
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 38452df32e9..96b3a4e6d18 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -90,6 +90,7 @@ impl RegionValueElements {
 rustc_index::newtype_index! {
     /// A single integer representing a `Location` in the MIR control-flow
     /// graph. Constructed efficiently from `RegionValueElements`.
+    #[orderable]
     #[debug_format = "PointIndex({})"]
     pub struct PointIndex {}
 }
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 1d309eb908e..580ef9b06e7 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -10,7 +10,7 @@ test = false
 # tidy-alphabetical-start
 bitflags = "1.0"
 cstr = "0.2"
-itertools = "0.10.5"
+itertools = "0.11"
 libc = "0.2"
 measureme = "10.0.0"
 object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 4f540de7ae0..f2be6f27ff6 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -189,8 +189,6 @@ impl GlobalFileTable {
 }
 
 rustc_index::newtype_index! {
-    // Tell the newtype macro to not generate `Encode`/`Decode` impls.
-    #[custom_encodable]
     struct LocalFileId {}
 }
 
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index d385d367f39..0ca19e5fe4a 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2021"
 ar_archive_writer = "0.1.5"
 bitflags = "1.2.1"
 cc = "1.0.69"
-itertools = "0.10.1"
+itertools = "0.11"
 jobserver = "0.1.22"
 pathdiff = "0.2.0"
 regex = "1.4"
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 8d91c4c4376..77d9e491748 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -10,7 +10,7 @@ bitflags = "1.2.1"
 elsa = "=1.7.1"
 ena = "0.14.2"
 indexmap = { version = "2.0.0" }
-itertools = "0.10.1"
+itertools = "0.11"
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 libc = "0.2"
 measureme = "10.0.0"
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 5dd414cfd41..4b819e1cbd6 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -23,6 +23,7 @@ struct PreOrderFrame<Iter> {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     struct PreorderIndex {}
 }
 
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 7b741e8882d..d339075c171 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -154,6 +154,8 @@ rustc_index::newtype_index! {
     /// an "item-like" to something else can be implemented by a `Vec` instead of a
     /// tree or hash map.
     #[derive(HashStable_Generic)]
+    #[encodable]
+    #[orderable]
     pub struct ItemLocalId {}
 }
 
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 7205b7a21a8..3f8c0db8752 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -198,7 +198,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
             // entire graph when there are many connected regions.
 
             rustc_index::newtype_index! {
-                #[custom_encodable]
+                #[orderable]
                 pub struct RegionId {}
             }
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 0148c71dbb5..8df01b6555c 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1,3 +1,6 @@
+//! HIR pretty-printing is layered on top of AST pretty-printing. A number of
+//! the definitions in this file have equivalents in `rustc_ast_pretty`.
+
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
@@ -12,7 +15,7 @@ use rustc_hir::LifetimeParamKind;
 use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term};
 use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
 use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{self, FileName};
 use rustc_target::spec::abi::Abi;
 
@@ -49,8 +52,8 @@ pub trait PpAnn {
 }
 
 pub struct NoAnn;
+
 impl PpAnn for NoAnn {}
-pub const NO_ANN: &dyn PpAnn = &NoAnn;
 
 impl PpAnn for &dyn rustc_hir::intravisit::Map<'_> {
     fn nested(&self, state: &mut State<'_>, nested: Nested) {
@@ -136,9 +139,8 @@ impl<'a> PrintState<'a> for State<'a> {
         &mut self.comments
     }
 
-    fn print_ident(&mut self, ident: Ident) {
-        self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
-        self.ann.post(self, AnnNode::Name(&ident.name))
+    fn ann_post(&mut self, ident: Ident) {
+        self.ann.post(self, AnnNode::Name(&ident.name));
     }
 
     fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bool) {
@@ -183,15 +185,15 @@ where
 }
 
 pub fn ty_to_string(ty: &hir::Ty<'_>) -> String {
-    to_string(NO_ANN, |s| s.print_type(ty))
+    to_string(&NoAnn, |s| s.print_type(ty))
 }
 
 pub fn qpath_to_string(segment: &hir::QPath<'_>) -> String {
-    to_string(NO_ANN, |s| s.print_qpath(segment, false))
+    to_string(&NoAnn, |s| s.print_qpath(segment, false))
 }
 
 pub fn pat_to_string(pat: &hir::Pat<'_>) -> String {
-    to_string(NO_ANN, |s| s.print_pat(pat))
+    to_string(&NoAnn, |s| s.print_pat(pat))
 }
 
 impl<'a> State<'a> {
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 0062889d244..b0c60304424 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -19,7 +19,6 @@ rustc_infer = { path = "../rustc_infer" }
 rustc_lint = { path = "../rustc_lint" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f74000571ac..a9f67f984da 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3063,7 +3063,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         };
 
-        self.commit_if_ok(|_| {
+        self.commit_if_ok(|snapshot| {
+            let outer_universe = self.universe();
+
             let ocx = ObligationCtxt::new(self);
             let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
             let impl_trait_ref =
@@ -3073,7 +3075,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Match the impl self type against the base ty. If this fails,
             // we just skip this impl, since it's not particularly useful.
             let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
-            ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
+            ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?;
 
             // Register the impl's predicates. One of these predicates
             // must be unsatisfied, or else we wouldn't have gotten here
@@ -3109,11 +3111,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
             );
 
-            let errors = ocx.select_where_possible();
+            let true_errors = ocx.select_where_possible();
+
+            // Do a leak check -- we can't really report report a useful error here,
+            // but it at least avoids an ICE when the error has to do with higher-ranked
+            // lifetimes.
+            self.leak_check(outer_universe, Some(snapshot))?;
+
+            // Bail if we have ambiguity errors, which we can't report in a useful way.
+            let ambiguity_errors = ocx.select_all_or_error();
+            if true_errors.is_empty() && !ambiguity_errors.is_empty() {
+                return Err(NoSolution);
+            }
+
             // There should be at least one error reported. If not, we
             // will still delay a span bug in `report_fulfillment_errors`.
             Ok::<_, NoSolution>((
-                self.err_ctxt().report_fulfillment_errors(errors),
+                self.err_ctxt().report_fulfillment_errors(true_errors),
                 impl_trait_ref.args.type_at(1),
                 element_ty,
             ))
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index 7aadb95d939..566d407d23c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -4,11 +4,13 @@ use rustc_middle::ty::error::TypeError;
 use std::cmp;
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "ExpectedIdx({})"]
     pub(crate) struct ExpectedIdx {}
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "ProvidedIdx({})"]
     pub(crate) struct ProvidedIdx {}
 }
diff --git a/compiler/rustc_index/src/vec/tests.rs b/compiler/rustc_index/src/vec/tests.rs
index 1959f4e07b7..381d79c24fc 100644
--- a/compiler/rustc_index/src/vec/tests.rs
+++ b/compiler/rustc_index/src/vec/tests.rs
@@ -2,6 +2,7 @@
 use crate as rustc_index;
 
 crate::newtype_index! {
+    #[orderable]
     #[max = 0xFFFF_FFFA]
     struct MyIdx {}
 }
diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs
index f6a6175374a..13500949a22 100644
--- a/compiler/rustc_index_macros/src/lib.rs
+++ b/compiler/rustc_index_macros/src/lib.rs
@@ -18,8 +18,19 @@ mod newtype;
 ///   to create/return a value.
 ///
 /// Internally, the index uses a u32, so the index must not exceed
-/// `u32::MAX`. You can also customize things like the `Debug` impl,
-/// what traits are derived, and so forth via the macro.
+/// `u32::MAX`.
+///
+/// The impls provided by default are Clone, Copy, PartialEq, Eq, and Hash.
+///
+/// Accepted attributes for customization:
+/// - #[derive(HashStable_Generic)]/#[derive(HashStable)]: derives
+///   `HashStable`, as normal.
+/// - #[encodable]: derives `Encodable`/`Decodable`.
+/// - #[orderable]: derives `PartialOrd`/`Ord`, plus step-related methods.
+/// - #[debug_format = "Foo({})"]: derives `Debug` with particular output.
+/// - #[max = 0xFFFF_FFFD]: specifies the max value, which allows niche
+///   optimizations. The default max value is 0xFFFF_FF00.
+/// - #[gate_rustc_only]: makes parts of the generated code nightly-only.
 #[proc_macro]
 #[cfg_attr(
     feature = "nightly",
diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs
index 2a974fd2628..df1318c835e 100644
--- a/compiler/rustc_index_macros/src/newtype.rs
+++ b/compiler/rustc_index_macros/src/newtype.rs
@@ -22,8 +22,8 @@ impl Parse for Newtype {
         let mut debug_format: Option<Lit> = None;
         let mut max = None;
         let mut consts = Vec::new();
-        let mut encodable = true;
-        let mut ord = true;
+        let mut encodable = false;
+        let mut ord = false;
         let mut gate_rustc_only = quote! {};
         let mut gate_rustc_only_cfg = quote! { all() };
 
@@ -34,12 +34,12 @@ impl Parse for Newtype {
                     gate_rustc_only_cfg = quote! { feature = "nightly" };
                     false
                 }
-                "custom_encodable" => {
-                    encodable = false;
+                "encodable" => {
+                    encodable = true;
                     false
                 }
-                "no_ord_impl" => {
-                    ord = false;
+                "orderable" => {
+                    ord = true;
                     false
                 }
                 "max" => {
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 00251a19226..73a02a431df 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -15,7 +15,6 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 479343c3ec2..e06596df7b9 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -341,11 +341,13 @@ impl<'tcx> SccUniverse<'tcx> {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "LeakCheckNode({})"]
     struct LeakCheckNode {}
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "LeakCheckScc({})"]
     struct LeakCheckScc {}
 }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 5250dbc7906..99bea647bd5 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -114,7 +114,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
     }
 }
 
-/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
+/// Runs the "early phases" of the compiler: initial `cfg` processing,
 /// syntax expansion, secondary `cfg` expansion, synthesis of a test
 /// harness if one is to be provided, injection of a dependency on the
 /// standard library and prelude, and name resolution.
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index f427b77d65c..fbcb49b1df5 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -739,6 +739,8 @@ pub trait LintContext {
                         } else {
                             db.span_suggestion(name_span, "there is a config with a similar name", best_match, Applicability::MaybeIncorrect);
                         }
+                    } else if name == sym::feature && std::env::var_os("CARGO").is_some() {
+                        db.help("consider defining some features in `Cargo.toml`");
                     } else if !possibilities.is_empty() {
                         let mut possibilities = possibilities.iter()
                             .map(Symbol::as_str)
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 1281cc9f920..3fc4f092443 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -56,7 +56,6 @@ struct LintLevelSets {
 }
 
 rustc_index::newtype_index! {
-    #[custom_encodable] // we don't need encoding
     struct LintStackIndex {
         const COMMAND_LINE = 0;
     }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 5a957d2c26d..ef5a1caadb7 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -23,6 +23,8 @@
 
 use rustc_macros::HashStable;
 use rustc_type_ir::Canonical as IrCanonical;
+use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo;
+pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
 use smallvec::SmallVec;
 use std::ops::Index;
 
@@ -33,6 +35,8 @@ use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
 
 pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>;
 
+pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo<TyCtxt<'tcx>>;
+
 pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
 
 impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
@@ -138,158 +142,6 @@ impl<'tcx> Default for OriginalQueryValues<'tcx> {
     }
 }
 
-/// Information about a canonical variable that is included with the
-/// canonical value. This is sufficient information for code to create
-/// a copy of the canonical value in some other inference context,
-/// with fresh inference variables replacing the canonical values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct CanonicalVarInfo<'tcx> {
-    pub kind: CanonicalVarKind<'tcx>,
-}
-
-impl<'tcx> CanonicalVarInfo<'tcx> {
-    pub fn universe(&self) -> ty::UniverseIndex {
-        self.kind.universe()
-    }
-
-    #[must_use]
-    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
-        CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
-    }
-
-    pub fn is_existential(&self) -> bool {
-        match self.kind {
-            CanonicalVarKind::Ty(_) => true,
-            CanonicalVarKind::PlaceholderTy(_) => false,
-            CanonicalVarKind::Region(_) => true,
-            CanonicalVarKind::PlaceholderRegion(..) => false,
-            CanonicalVarKind::Const(..) => true,
-            CanonicalVarKind::PlaceholderConst(_, _) => false,
-            CanonicalVarKind::Effect => true,
-        }
-    }
-
-    pub fn is_region(&self) -> bool {
-        match self.kind {
-            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
-            CanonicalVarKind::Ty(_)
-            | CanonicalVarKind::PlaceholderTy(_)
-            | CanonicalVarKind::Const(_, _)
-            | CanonicalVarKind::PlaceholderConst(_, _)
-            | CanonicalVarKind::Effect => false,
-        }
-    }
-
-    pub fn expect_placeholder_index(self) -> usize {
-        match self.kind {
-            CanonicalVarKind::Ty(_)
-            | CanonicalVarKind::Region(_)
-            | CanonicalVarKind::Const(_, _)
-            | CanonicalVarKind::Effect => bug!("expected placeholder: {self:?}"),
-
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
-        }
-    }
-}
-
-/// Describes the "kind" of the canonical variable. This is a "kind"
-/// in the type-theory sense of the term -- i.e., a "meta" type system
-/// that analyzes type-like values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub enum CanonicalVarKind<'tcx> {
-    /// Some kind of type inference variable.
-    Ty(CanonicalTyVarKind),
-
-    /// A "placeholder" that represents "any type".
-    PlaceholderTy(ty::PlaceholderType),
-
-    /// Region variable `'?R`.
-    Region(ty::UniverseIndex),
-
-    /// A "placeholder" that represents "any region". Created when you
-    /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
-    /// bound region `'a`.
-    PlaceholderRegion(ty::PlaceholderRegion),
-
-    /// Some kind of const inference variable.
-    Const(ty::UniverseIndex, Ty<'tcx>),
-
-    /// Effect variable `'?E`.
-    Effect,
-
-    /// A "placeholder" that represents "any const".
-    PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>),
-}
-
-impl<'tcx> CanonicalVarKind<'tcx> {
-    pub fn universe(self) -> ty::UniverseIndex {
-        match self {
-            CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
-            CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
-                ty::UniverseIndex::ROOT
-            }
-            CanonicalVarKind::Effect => ty::UniverseIndex::ROOT,
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
-            CanonicalVarKind::Region(ui) => ui,
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
-            CanonicalVarKind::Const(ui, _) => ui,
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
-        }
-    }
-
-    /// Replaces the universe of this canonical variable with `ui`.
-    ///
-    /// In case this is a float or int variable, this causes an ICE if
-    /// the updated universe is not the root.
-    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
-        match self {
-            CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
-                CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
-            }
-            CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
-            | CanonicalVarKind::Effect => {
-                assert_eq!(ui, ty::UniverseIndex::ROOT);
-                self
-            }
-            CanonicalVarKind::PlaceholderTy(placeholder) => {
-                CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
-            }
-            CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
-            CanonicalVarKind::PlaceholderRegion(placeholder) => {
-                CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
-            }
-            CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
-            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
-                CanonicalVarKind::PlaceholderConst(
-                    ty::Placeholder { universe: ui, ..placeholder },
-                    ty,
-                )
-            }
-        }
-    }
-}
-
-/// Rust actually has more than one category of type variables;
-/// notably, the type variables we create for literals (e.g., 22 or
-/// 22.) can only be instantiated with integral/float types (e.g.,
-/// usize or f32). In order to faithfully reproduce a type, we need to
-/// know what set of types a given type variable can be unified with.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
-pub enum CanonicalTyVarKind {
-    /// General type variable `?T` that can be unified with arbitrary types.
-    General(ty::UniverseIndex),
-
-    /// Integral type variable `?I` (that can only be unified with integral types).
-    Int,
-
-    /// Floating-point type variable `?F` (that can only be unified with float types).
-    Float,
-}
-
 /// After we execute a query with a canonicalized key, we get back a
 /// `Canonical<QueryResponse<..>>`. You can use
 /// `instantiate_query_result` to access the data in this result.
@@ -366,7 +218,6 @@ pub type QueryOutlivesConstraint<'tcx> =
 
 TrivialTypeTraversalImpls! {
     crate::infer::canonical::Certainty,
-    crate::infer::canonical::CanonicalTyVarKind,
 }
 
 impl<'tcx> CanonicalVarValues<'tcx> {
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 9d55295fb66..b8f04ed03dc 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -148,6 +148,8 @@ rustc_index::newtype_index! {
     /// * The subscope with `first_statement_index == 1` is scope of `c`,
     ///   and thus does not include EXPR_2, but covers the `...`.
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     pub struct FirstStatementIndex {}
 }
 
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 08d377a8695..f15ee0082ce 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -17,6 +17,8 @@ rustc_index::newtype_index! {
     /// Note that LLVM handles counter IDs as `uint32_t`, so there is no need
     /// to use a larger representation on the Rust side.
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[max = 0xFFFF_FFFF]
     #[debug_format = "CounterId({})"]
     pub struct CounterId {}
@@ -37,6 +39,8 @@ rustc_index::newtype_index! {
     /// Note that LLVM handles expression IDs as `uint32_t`, so there is no need
     /// to use a larger representation on the Rust side.
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[max = 0xFFFF_FFFF]
     #[debug_format = "ExpressionId({})"]
     pub struct ExpressionId {}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index d4778cdccf3..1e5a7401c6f 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -736,6 +736,8 @@ impl SourceInfo {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[debug_format = "_{}"]
     pub struct Local {
         const RETURN_PLACE = 0;
@@ -1171,6 +1173,8 @@ rustc_index::newtype_index! {
     /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[debug_format = "bb{}"]
     pub struct BasicBlock {
         const START_BLOCK = 0;
@@ -1305,6 +1309,7 @@ impl<'tcx> BasicBlockData<'tcx> {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[encodable]
     #[debug_format = "scope[{}]"]
     pub struct SourceScope {
         const OUTERMOST_SOURCE_SCOPE = 0;
@@ -1533,6 +1538,8 @@ impl UserTypeProjection {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[debug_format = "promoted[{}]"]
     pub struct Promoted {}
 }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index b5dd3010d3a..4f98c302298 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -132,6 +132,7 @@ pub struct UnsafetyCheckResult {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[encodable]
     #[debug_format = "_{}"]
     pub struct CoroutineSavedLocal {}
 }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index c1bb03e99da..2e367df2c4f 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -956,13 +956,26 @@ pub enum CodegenObligationError {
     FulfillmentError,
 }
 
+/// Defines the treatment of opaque types in a given inference context.
+///
+/// This affects both what opaques are allowed to be defined, but also whether
+/// opaques are replaced with inference vars eagerly in the old solver (e.g.
+/// in projection, and in the signature during function type-checking).
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub enum DefiningAnchor {
-    /// `DefId` of the item.
+    /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
+    /// replace opaque types in `replace_opaque_types_with_inference_vars`.
     Bind(LocalDefId),
-    /// When opaque types are not resolved, we `Bubble` up, meaning
-    /// return the opaque/hidden type pair from query, for caller of query to handle it.
+    /// In contexts where we don't currently know what opaques are allowed to be
+    /// defined, such as (old solver) canonical queries, we will simply allow
+    /// opaques to be defined, but "bubble" them up in the canonical response or
+    /// otherwise treat them to be handled later.
+    ///
+    /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
+    /// which may affect what predicates pass and fail in the old trait solver.
     Bubble,
-    /// Used to catch type mismatch errors when handling opaque types.
+    /// Do not allow any opaques to be defined. This is used to catch type mismatch
+    /// errors when handling opaque types, and also should be used when we would
+    /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
     Error,
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f240a99c8ff..1d7abcf53ea 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -94,7 +94,7 @@ pub use self::parameterized::ParameterizedOverTcx;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
-    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind,
     BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind,
     CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate,
     ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs,
@@ -1517,8 +1517,36 @@ pub struct Placeholder<T> {
 
 pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
+impl rustc_type_ir::Placeholder for PlaceholderRegion {
+    fn universe(&self) -> UniverseIndex {
+        self.universe
+    }
+
+    fn var(&self) -> BoundVar {
+        self.bound.var
+    }
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+        Placeholder { universe: ui, ..self }
+    }
+}
+
 pub type PlaceholderType = Placeholder<BoundTy>;
 
+impl rustc_type_ir::Placeholder for PlaceholderType {
+    fn universe(&self) -> UniverseIndex {
+        self.universe
+    }
+
+    fn var(&self) -> BoundVar {
+        self.bound.var
+    }
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+        Placeholder { universe: ui, ..self }
+    }
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub struct BoundConst<'tcx> {
@@ -1528,6 +1556,20 @@ pub struct BoundConst<'tcx> {
 
 pub type PlaceholderConst = Placeholder<BoundVar>;
 
+impl rustc_type_ir::Placeholder for PlaceholderConst {
+    fn universe(&self) -> UniverseIndex {
+        self.universe
+    }
+
+    fn var(&self) -> BoundVar {
+        self.bound
+    }
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self {
+        Placeholder { universe: ui, ..self }
+    }
+}
+
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
 /// particular point.
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index ff333b3f09a..f12a512da31 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -32,6 +32,7 @@ use std::fmt;
 use std::ops::{ControlFlow, Deref, Range};
 use ty::util::IntTypeExt;
 
+use rustc_type_ir::BoundVar;
 use rustc_type_ir::ClauseKind as IrClauseKind;
 use rustc_type_ir::CollectAndApply;
 use rustc_type_ir::ConstKind as IrConstKind;
@@ -1611,6 +1612,8 @@ impl fmt::Debug for EarlyParamRegion {
 rustc_index::newtype_index! {
     /// A **region** (lifetime) **v**ariable **ID**.
     #[derive(HashStable)]
+    #[encodable]
+    #[orderable]
     #[debug_format = "'?{}"]
     pub struct RegionVid {}
 }
@@ -1621,12 +1624,6 @@ impl Atom for RegionVid {
     }
 }
 
-rustc_index::newtype_index! {
-    #[derive(HashStable)]
-    #[debug_format = "{}"]
-    pub struct BoundVar {}
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct BoundTy {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 0331546cdd9..4a5c89411da 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -578,6 +578,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
 
 rustc_index::newtype_index! {
     #[derive(HashStable)]
+    #[encodable]
     #[debug_format = "UserType({})"]
     pub struct UserTypeAnnotationIndex {
         const START_INDEX = 0;
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 6dceacd75a5..db542234052 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -17,7 +17,6 @@ rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index d6ca873e992..993fee95895 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -186,6 +186,7 @@ pub(crate) enum BreakableTarget {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     struct DropIdx {}
 }
 
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 61664eb2a6f..7199db677c4 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -16,7 +16,6 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 7ab1a9ed069..22cf3999239 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -14,6 +14,7 @@ use self::abs_domain::{AbstractElem, Lift};
 mod abs_domain;
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "mp{}"]
     pub struct MovePathIndex {}
 }
@@ -25,6 +26,7 @@ impl polonius_engine::Atom for MovePathIndex {
 }
 
 rustc_index::newtype_index! {
+    #[orderable]
     #[debug_format = "mo{}"]
     pub struct MoveOutIndex {}
 }
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 0448e9d276d..c2ca0a6bcb8 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2021"
 [dependencies]
 # tidy-alphabetical-start
 either = "1"
-itertools = "0.10.1"
+itertools = "0.11"
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
@@ -20,7 +20,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_mir_build = { path = "../rustc_mir_build" }
 rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 7defc9ec148..0d807db404c 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -264,6 +264,7 @@ impl graph::WithPredecessors for CoverageGraph {
 
 rustc_index::newtype_index! {
     /// A node in the control-flow graph of CoverageGraph.
+    #[orderable]
     #[debug_format = "bcb{}"]
     pub(super) struct BasicCoverageBlock {
         const START_BCB = 0;
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 40c3811e054..80e6c104bd4 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.10.1"
+itertools = "0.11"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr = { path = "../rustc_attr" }
@@ -19,7 +19,6 @@ rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index e97ef807204..a70f4138cfb 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -54,6 +54,7 @@ use std::marker::PhantomData;
 // unused so that we can store multiple index types in `CompressedHybridIndex`,
 // and use those bits to encode which index type it contains.
 rustc_index::newtype_index! {
+    #[encodable]
     #[max = 0x7FFF_FFFF]
     pub struct SerializedDepNodeIndex {}
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 8ab48c99007..2d2a3c3d665 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1443,9 +1443,8 @@ impl CheckCfg {
         let relocation_model_values = RelocModel::all();
 
         // Unknown possible values:
-        //  - `feature`
         //  - `target_feature`
-        for name in [sym::feature, sym::target_feature] {
+        for name in [sym::target_feature] {
             self.expecteds.entry(name).or_insert(ExpectedValues::Any);
         }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 167a01ab799..2a9f0b42678 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -18,7 +18,10 @@ use rustc_middle::ty::{self, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, Variance
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_target::abi::FieldIdx;
 use stable_mir::mir::mono::InstanceDef;
-use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
+use stable_mir::mir::{
+    Body, ConstOperand, CopyNonOverlapping, Statement, UserTypeProjection, VarDebugInfoFragment,
+    VariantIdx,
+};
 use stable_mir::ty::{
     AdtDef, AdtKind, ClosureDef, ClosureKind, Const, ConstId, ConstantKind, EarlyParamRegion,
     FloatTy, FnDef, GenericArgs, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span,
@@ -69,15 +72,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
 
     fn get_filename(&self, span: &Span) -> Filename {
         let tables = self.0.borrow();
-        opaque(
-            &tables
-                .tcx
-                .sess
-                .source_map()
-                .span_to_filename(tables[*span])
-                .display(rustc_span::FileNameDisplayPreference::Local)
-                .to_string(),
-        )
+        tables
+            .tcx
+            .sess
+            .source_map()
+            .span_to_filename(tables[*span])
+            .display(rustc_span::FileNameDisplayPreference::Local)
+            .to_string()
     }
 
     fn get_lines(&self, span: &Span) -> LineInfo {
@@ -444,10 +445,24 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
                 })
                 .collect(),
             self.arg_count,
+            self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
         )
     }
 }
 
+impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
+    type T = stable_mir::mir::VarDebugInfo;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        stable_mir::mir::VarDebugInfo {
+            name: self.name.to_string(),
+            source_info: self.source_info.stable(tables),
+            composite: self.composite.as_ref().map(|composite| composite.stable(tables)),
+            value: self.value.stable(tables),
+            argument_index: self.argument_index,
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
@@ -455,6 +470,42 @@ impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
     }
 }
 
+impl<'tcx> Stable<'tcx> for mir::SourceInfo {
+    type T = stable_mir::mir::SourceInfo;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
+    type T = stable_mir::mir::VarDebugInfoFragment;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        VarDebugInfoFragment {
+            ty: self.ty.stable(tables),
+            projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
+    type T = stable_mir::mir::VarDebugInfoContents;
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        match self {
+            mir::VarDebugInfoContents::Place(place) => {
+                stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
+            }
+            mir::VarDebugInfoContents::Const(const_operand) => {
+                let op = ConstOperand {
+                    span: const_operand.span.stable(tables),
+                    user_ty: const_operand.user_ty.map(|index| index.as_usize()),
+                    const_: const_operand.const_.stable(tables),
+                };
+                stable_mir::mir::VarDebugInfoContents::Const(op)
+            }
+        }
+    }
+}
+
 impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
     type T = stable_mir::mir::StatementKind;
     fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 595babc26ae..4b5bd75d5b1 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -13,7 +13,7 @@ pub type StableCrateIdMap =
     indexmap::IndexMap<StableCrateId, CrateNum, BuildHasherDefault<Unhasher>>;
 
 rustc_index::newtype_index! {
-    #[custom_encodable]
+    #[orderable]
     #[debug_format = "crate{}"]
     pub struct CrateNum {}
 }
@@ -213,7 +213,7 @@ rustc_index::newtype_index! {
     /// A DefIndex is an index into the hir-map for a crate, identifying a
     /// particular definition. It should really be considered an interned
     /// shorthand for a particular DefPath.
-    #[custom_encodable] // (only encodable in metadata)
+    #[orderable]
     #[debug_format = "DefIndex({})"]
     pub struct DefIndex {
         /// The crate root is always assigned index 0 by the AST Map code,
@@ -222,6 +222,7 @@ rustc_index::newtype_index! {
     }
 }
 
+// njn: I don't understand these
 impl<E: Encoder> Encodable<E> for DefIndex {
     default fn encode(&self, _: &mut E) {
         panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 988ff57254c..b717229b68d 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -60,7 +60,7 @@ pub struct SyntaxContextData {
 
 rustc_index::newtype_index! {
     /// A unique ID associated with a macro invocation and expansion.
-    #[custom_encodable]
+    #[orderable]
     pub struct ExpnIndex {}
 }
 
@@ -80,8 +80,6 @@ impl fmt::Debug for ExpnId {
 
 rustc_index::newtype_index! {
     /// A unique ID associated with a macro invocation and expansion.
-    #[custom_encodable]
-    #[no_ord_impl]
     #[debug_format = "expn{}"]
     pub struct LocalExpnId {}
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2e3b5446405..ea80bc82bd1 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2018,6 +2018,7 @@ impl fmt::Display for MacroRulesNormalizedIdent {
 pub struct Symbol(SymbolIndex);
 
 rustc_index::newtype_index! {
+    #[orderable]
     struct SymbolIndex {}
 }
 
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index b00567e87c6..a274790bffc 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -42,6 +42,8 @@ rustc_index::newtype_index! {
     /// `d` is `FieldIdx(1)` in `VariantIdx(1)`, and
     /// `f` is `FieldIdx(1)` in `VariantIdx(0)`.
     #[derive(HashStable_Generic)]
+    #[encodable]
+    #[orderable]
     pub struct FieldIdx {}
 }
 
@@ -57,6 +59,8 @@ rustc_index::newtype_index! {
     /// `struct`s, `tuples`, and `unions`s are considered to have a single variant
     /// with variant index zero, aka [`FIRST_VARIANT`].
     #[derive(HashStable_Generic)]
+    #[encodable]
+    #[orderable]
     pub struct VariantIdx {
         /// Equivalent to `VariantIdx(0)`.
         const FIRST_VARIANT = 0;
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 667ee3d4e1c..7d098180b93 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -17,7 +17,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_query_system = { path = "../rustc_query_system" }
-rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index 68f81a05536..71adebffc15 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -13,6 +13,7 @@ use rustc_session::Limit;
 use std::collections::hash_map::Entry;
 
 rustc_index::newtype_index! {
+    #[orderable]
     pub struct StackDepth {}
 }
 
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index 07420985a85..066016231fa 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -27,5 +27,5 @@ rustc = [
 
 [dev-dependencies]
 # tidy-alphabetical-start
-itertools = "0.10.1"
+itertools = "0.11"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 7e00f1e0c42..f8eb82da8f6 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.10.1"
+itertools = "0.11"
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 9f170c5b4db..d2768703297 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{Interner, UniverseIndex};
+use crate::{Interner, Placeholder, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
@@ -113,3 +113,257 @@ where
         self.variables.visit_with(folder)
     }
 }
+
+/// Information about a canonical variable that is included with the
+/// canonical value. This is sufficient information for code to create
+/// a copy of the canonical value in some other inference context,
+/// with fresh inference variables replacing the canonical values.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Hash(bound = ""),
+    Copy(bound = "CanonicalVarKind<I>: Copy"),
+    Debug(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct CanonicalVarInfo<I: Interner> {
+    pub kind: CanonicalVarKind<I>,
+}
+
+impl<I: Interner> PartialEq for CanonicalVarInfo<I> {
+    fn eq(&self, other: &Self) -> bool {
+        self.kind == other.kind
+    }
+}
+
+impl<I: Interner> Eq for CanonicalVarInfo<I> {}
+
+impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
+where
+    I::Ty: TypeVisitable<I>,
+{
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.kind.visit_with(visitor)
+    }
+}
+
+impl<I: Interner> TypeFoldable<I> for CanonicalVarInfo<I>
+where
+    I::Ty: TypeFoldable<I>,
+{
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? })
+    }
+}
+
+impl<I: Interner> CanonicalVarInfo<I> {
+    pub fn universe(&self) -> UniverseIndex {
+        self.kind.universe()
+    }
+
+    #[must_use]
+    pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo<I> {
+        CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+    }
+
+    pub fn is_existential(&self) -> bool {
+        match self.kind {
+            CanonicalVarKind::Ty(_) => true,
+            CanonicalVarKind::PlaceholderTy(_) => false,
+            CanonicalVarKind::Region(_) => true,
+            CanonicalVarKind::PlaceholderRegion(..) => false,
+            CanonicalVarKind::Const(..) => true,
+            CanonicalVarKind::PlaceholderConst(_, _) => false,
+            CanonicalVarKind::Effect => true,
+        }
+    }
+
+    pub fn is_region(&self) -> bool {
+        match self.kind {
+            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::PlaceholderTy(_)
+            | CanonicalVarKind::Const(_, _)
+            | CanonicalVarKind::PlaceholderConst(_, _)
+            | CanonicalVarKind::Effect => false,
+        }
+    }
+
+    pub fn expect_placeholder_index(self) -> usize {
+        match self.kind {
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::Region(_)
+            | CanonicalVarKind::Const(_, _)
+            | CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
+
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.var().as_usize(),
+        }
+    }
+}
+
+/// Describes the "kind" of the canonical variable. This is a "kind"
+/// in the type-theory sense of the term -- i.e., a "meta" type system
+/// that analyzes type-like values.
+#[derive(derivative::Derivative)]
+#[derivative(Clone(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum CanonicalVarKind<I: Interner> {
+    /// Some kind of type inference variable.
+    Ty(CanonicalTyVarKind),
+
+    /// A "placeholder" that represents "any type".
+    PlaceholderTy(I::PlaceholderTy),
+
+    /// Region variable `'?R`.
+    Region(UniverseIndex),
+
+    /// A "placeholder" that represents "any region". Created when you
+    /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
+    /// bound region `'a`.
+    PlaceholderRegion(I::PlaceholderRegion),
+
+    /// Some kind of const inference variable.
+    Const(UniverseIndex, I::Ty),
+
+    /// Effect variable `'?E`.
+    Effect,
+
+    /// A "placeholder" that represents "any const".
+    PlaceholderConst(I::PlaceholderConst, I::Ty),
+}
+
+impl<I: Interner> Copy for CanonicalVarKind<I>
+where
+    I::PlaceholderTy: Copy,
+    I::PlaceholderRegion: Copy,
+    I::PlaceholderConst: Copy,
+    I::Ty: Copy,
+{
+}
+
+impl<I: Interner> PartialEq for CanonicalVarKind<I> {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Self::Ty(l0), Self::Ty(r0)) => l0 == r0,
+            (Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
+            (Self::Region(l0), Self::Region(r0)) => l0 == r0,
+            (Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
+            (Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1,
+            (Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => {
+                l0 == r0 && l1 == r1
+            }
+            _ => std::mem::discriminant(self) == std::mem::discriminant(other),
+        }
+    }
+}
+
+impl<I: Interner> Eq for CanonicalVarKind<I> {}
+
+impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
+where
+    I::Ty: TypeVisitable<I>,
+{
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        match self {
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::PlaceholderTy(_)
+            | CanonicalVarKind::Region(_)
+            | CanonicalVarKind::PlaceholderRegion(_)
+            | CanonicalVarKind::Effect => ControlFlow::Continue(()),
+            CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
+                ty.visit_with(visitor)
+            }
+        }
+    }
+}
+
+impl<I: Interner> TypeFoldable<I> for CanonicalVarKind<I>
+where
+    I::Ty: TypeFoldable<I>,
+{
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(match self {
+            CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind),
+            CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind),
+            CanonicalVarKind::Const(kind, ty) => {
+                CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?)
+            }
+            CanonicalVarKind::PlaceholderTy(placeholder) => {
+                CanonicalVarKind::PlaceholderTy(placeholder)
+            }
+            CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                CanonicalVarKind::PlaceholderRegion(placeholder)
+            }
+            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+                CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?)
+            }
+            CanonicalVarKind::Effect => CanonicalVarKind::Effect,
+        })
+    }
+}
+
+impl<I: Interner> CanonicalVarKind<I> {
+    pub fn universe(&self) -> UniverseIndex {
+        match self {
+            CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => *ui,
+            CanonicalVarKind::Region(ui) => *ui,
+            CanonicalVarKind::Const(ui, _) => *ui,
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
+            CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
+                UniverseIndex::ROOT
+            }
+            CanonicalVarKind::Effect => UniverseIndex::ROOT,
+        }
+    }
+
+    /// Replaces the universe of this canonical variable with `ui`.
+    ///
+    /// In case this is a float or int variable, this causes an ICE if
+    /// the updated universe is not the root.
+    pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind<I> {
+        match self {
+            CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
+                CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+            }
+            CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+            CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+
+            CanonicalVarKind::PlaceholderTy(placeholder) => {
+                CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
+            }
+            CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
+            }
+            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+                CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
+            }
+            CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
+            | CanonicalVarKind::Effect => {
+                assert_eq!(ui, UniverseIndex::ROOT);
+                self
+            }
+        }
+    }
+}
+
+/// Rust actually has more than one category of type variables;
+/// notably, the type variables we create for literals (e.g., 22 or
+/// 22.) can only be instantiated with integral/float types (e.g.,
+/// usize or f32). In order to faithfully reproduce a type, we need to
+/// know what set of types a given type variable can be unified with.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum CanonicalTyVarKind {
+    /// General type variable `?T` that can be unified with arbitrary types.
+    General(UniverseIndex),
+
+    /// Integral type variable `?I` (that can only be unified with integral types).
+    Int,
+
+    /// Floating-point type variable `?F` (that can only be unified with float types).
+    Float,
+}
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index a5f90421de5..409033a2d8d 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -95,6 +95,8 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
 
 rustc_index::newtype_index! {
     /// A **`const`** **v**ariable **ID**.
+    #[encodable]
+    #[orderable]
     #[debug_format = "?{}c"]
     #[gate_rustc_only]
     pub struct ConstVid {}
@@ -108,6 +110,8 @@ rustc_index::newtype_index! {
     /// relate an effect variable with a normal one, we would ICE, which can catch bugs
     /// where we are not correctly using the effect var for an effect param. Fallback
     /// is also implemented on top of having separate effect and normal const variables.
+    #[encodable]
+    #[orderable]
     #[debug_format = "?{}e"]
     #[gate_rustc_only]
     pub struct EffectVid {}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 170a791fb54..16508c1a257 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -2,7 +2,7 @@ use smallvec::SmallVec;
 use std::fmt::Debug;
 use std::hash::Hash;
 
-use crate::{DebugWithInfcx, Mutability};
+use crate::{BoundVar, DebugWithInfcx, Mutability, UniverseIndex};
 
 pub trait Interner: Sized {
     type DefId: Clone + Debug + Hash + Ord;
@@ -26,7 +26,7 @@ pub trait Interner: Sized {
     type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type ParamTy: Clone + Debug + Hash + Ord;
     type BoundTy: Clone + Debug + Hash + Ord;
-    type PlaceholderTy: Clone + Debug + Hash + Ord;
+    type PlaceholderTy: Clone + Debug + Hash + Ord + Placeholder;
 
     // Things stored inside of tys
     type ErrorGuaranteed: Clone + Debug + Hash + Ord;
@@ -37,7 +37,7 @@ pub trait Interner: Sized {
     // Kinds of consts
     type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderConst: Clone + Debug + Hash + Ord;
+    type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder;
     type ParamConst: Clone + Debug + Hash + Ord;
     type BoundConst: Clone + Debug + Hash + Ord;
     type ValueConst: Clone + Debug + Hash + Ord;
@@ -49,7 +49,7 @@ pub trait Interner: Sized {
     type BoundRegion: Clone + Debug + Hash + Ord;
     type LateParamRegion: Clone + Debug + Hash + Ord;
     type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
-    type PlaceholderRegion: Clone + Debug + Hash + Ord;
+    type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder;
 
     // Predicates
     type Predicate: Clone + Debug + Hash + Eq;
@@ -64,6 +64,14 @@ pub trait Interner: Sized {
     fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
 }
 
+/// Common capabilities of placeholder kinds
+pub trait Placeholder {
+    fn universe(&self) -> UniverseIndex;
+    fn var(&self) -> BoundVar;
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
+}
+
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
 /// that produces `T` items. You could combine them with
 /// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index acea7aa46f6..2aeb4230bb8 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -92,6 +92,8 @@ rustc_index::newtype_index! {
     ///
     /// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
     #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+    #[encodable]
+    #[orderable]
     #[debug_format = "DebruijnIndex({})"]
     #[gate_rustc_only]
     pub struct DebruijnIndex {
@@ -293,6 +295,8 @@ rustc_index::newtype_index! {
     /// type -- an idealized representative of "types in general" that we
     /// use for checking generic functions.
     #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+    #[encodable]
+    #[orderable]
     #[debug_format = "U{}"]
     #[gate_rustc_only]
     pub struct UniverseIndex {}
@@ -332,3 +336,12 @@ impl UniverseIndex {
         self.private < other.private
     }
 }
+
+rustc_index::newtype_index! {
+    #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+    #[encodable]
+    #[orderable]
+    #[debug_format = "{}"]
+    #[gate_rustc_only]
+    pub struct BoundVar {}
+}
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 494eeaf3dc8..3d4e7f77a4f 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -622,6 +622,8 @@ pub struct FloatVarValue(pub FloatTy);
 
 rustc_index::newtype_index! {
     /// A **ty**pe **v**ariable **ID**.
+    #[encodable]
+    #[orderable]
     #[debug_format = "?{}t"]
     #[gate_rustc_only]
     pub struct TyVid {}
@@ -629,6 +631,8 @@ rustc_index::newtype_index! {
 
 rustc_index::newtype_index! {
     /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
+    #[encodable]
+    #[orderable]
     #[debug_format = "?{}i"]
     #[gate_rustc_only]
     pub struct IntVid {}
@@ -636,6 +640,8 @@ rustc_index::newtype_index! {
 
 rustc_index::newtype_index! {
     /// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
+    #[encodable]
+    #[orderable]
     #[debug_format = "?{}f"]
     #[gate_rustc_only]
     pub struct FloatVid {}
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 91f1066d720..5eb6a8a5e54 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -110,7 +110,7 @@ pub enum ItemKind {
     Const,
 }
 
-pub type Filename = Opaque;
+pub type Filename = String;
 
 /// Holds information about an item in the crate.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index ac07246dfd3..8d237fc9f1d 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -2,7 +2,7 @@ use crate::mir::pretty::{function_body, pretty_statement};
 use crate::ty::{
     AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
 };
-use crate::{Error, Opaque, Span};
+use crate::{Error, Opaque, Span, Symbol};
 use std::io;
 
 /// The SMIR representation of a single function.
@@ -19,6 +19,9 @@ pub struct Body {
 
     // The number of arguments this function takes.
     pub(super) arg_count: usize,
+
+    // Debug information pertaining to user variables, including captures.
+    pub(super) var_debug_info: Vec<VarDebugInfo>,
 }
 
 impl Body {
@@ -26,14 +29,19 @@ impl Body {
     ///
     /// A constructor is required to build a `Body` from outside the crate
     /// because the `arg_count` and `locals` fields are private.
-    pub fn new(blocks: Vec<BasicBlock>, locals: LocalDecls, arg_count: usize) -> Self {
+    pub fn new(
+        blocks: Vec<BasicBlock>,
+        locals: LocalDecls,
+        arg_count: usize,
+        var_debug_info: Vec<VarDebugInfo>,
+    ) -> Self {
         // If locals doesn't contain enough entries, it can lead to panics in
         // `ret_local`, `arg_locals`, and `inner_locals`.
         assert!(
             locals.len() > arg_count,
             "A Body must contain at least a local for the return value and each of the function's arguments"
         );
-        Self { blocks, locals, arg_count }
+        Self { blocks, locals, arg_count, var_debug_info }
     }
 
     /// Return local that holds this function's return value.
@@ -427,6 +435,42 @@ pub struct Place {
     pub projection: Vec<ProjectionElem>,
 }
 
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VarDebugInfo {
+    pub name: Symbol,
+    pub source_info: SourceInfo,
+    pub composite: Option<VarDebugInfoFragment>,
+    pub value: VarDebugInfoContents,
+    pub argument_index: Option<u16>,
+}
+
+pub type SourceScope = u32;
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct SourceInfo {
+    pub span: Span,
+    pub scope: SourceScope,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VarDebugInfoFragment {
+    pub ty: Ty,
+    pub projection: Vec<ProjectionElem>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VarDebugInfoContents {
+    Place(Place),
+    Const(ConstOperand),
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct ConstOperand {
+    pub span: Span,
+    pub user_ty: Option<UserTypeAnnotationIndex>,
+    pub const_: Const,
+}
+
 // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
 // is so it can be used for both Places (for which the projection elements are of type
 // ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index bc2d57eaa24..69bf6ca72b0 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -128,8 +128,12 @@ pub trait MirVisitor {
         self.super_assert_msg(msg, location)
     }
 
+    fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
+        self.super_var_debug_info(var_debug_info);
+    }
+
     fn super_body(&mut self, body: &Body) {
-        let Body { blocks, locals: _, arg_count } = body;
+        let Body { blocks, locals: _, arg_count, var_debug_info } = body;
 
         for bb in blocks {
             self.visit_basic_block(bb);
@@ -145,6 +149,10 @@ pub trait MirVisitor {
         for (idx, arg) in body.inner_locals().iter().enumerate() {
             self.visit_local_decl(idx + local_start, arg)
         }
+
+        for info in var_debug_info.iter() {
+            self.visit_var_debug_info(info);
+        }
     }
 
     fn super_basic_block(&mut self, bb: &BasicBlock) {
@@ -382,6 +390,24 @@ pub trait MirVisitor {
         let _ = args;
     }
 
+    fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) {
+        let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } =
+            var_debug_info;
+        self.visit_span(&source_info.span);
+        let location = Location(source_info.span);
+        if let Some(composite) = composite {
+            self.visit_ty(&composite.ty, location);
+        }
+        match value {
+            VarDebugInfoContents::Place(place) => {
+                self.visit_place(place, PlaceContext::NON_USE, location);
+            }
+            VarDebugInfoContents::Const(constant) => {
+                self.visit_const(&constant.const_, location);
+            }
+        }
+    }
+
     fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) {
         match msg {
             AssertMessage::BoundsCheck { len, index } => {
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 070a2da6afb..af66cb3ffd7 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -114,7 +114,7 @@ fn main() {
         {
             cmd.arg("-Ztls-model=initial-exec");
         }
-    } else {
+    } else if std::env::var("MIRI").is_err() {
         // Find any host flags that were passed by bootstrap.
         // The flags are stored in a RUSTC_HOST_FLAGS variable, separated by spaces.
         if let Ok(flags) = std::env::var("RUSTC_HOST_FLAGS") {
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index f3917b978df..e13e95ef708 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -9,7 +9,7 @@ path = "lib.rs"
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.12", default-features = false, features = ["config"] }
-itertools = "0.10.1"
+itertools = "0.11"
 indexmap = "2"
 minifier = "0.3.0"
 once_cell = "1.10.0"
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 22527876b76..5666751d1ce 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -16,6 +16,13 @@ use crate::clean;
 /// Consequently, every change to this type should be synchronized to
 /// the `itemTypes` mapping table in `html/static/js/search.js`.
 ///
+/// The search engine in search.js also uses item type numbers as a tie breaker when
+/// sorting results. Keywords and primitives are given first because we want them to be easily
+/// found by new users who don't know about advanced features like type filters. The rest are
+/// mostly in an arbitrary order, but it's easier to test the search engine when
+/// it's deterministic, and these are strictly finer-grained than language namespaces, so
+/// using the path and the item type together to sort ensures that search sorting is stable.
+///
 /// In addition, code in `html::render` uses this enum to generate CSS classes, page prefixes, and
 /// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
 /// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
@@ -23,28 +30,28 @@ use crate::clean;
 #[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)]
 #[repr(u8)]
 pub(crate) enum ItemType {
-    Module = 0,
-    ExternCrate = 1,
-    Import = 2,
-    Struct = 3,
-    Enum = 4,
-    Function = 5,
-    TypeAlias = 6,
-    Static = 7,
-    Trait = 8,
-    Impl = 9,
-    TyMethod = 10,
-    Method = 11,
-    StructField = 12,
-    Variant = 13,
-    Macro = 14,
-    Primitive = 15,
-    AssocType = 16,
-    Constant = 17,
-    AssocConst = 18,
-    Union = 19,
-    ForeignType = 20,
-    Keyword = 21,
+    Keyword = 0,
+    Primitive = 1,
+    Module = 2,
+    ExternCrate = 3,
+    Import = 4,
+    Struct = 5,
+    Enum = 6,
+    Function = 7,
+    TypeAlias = 8,
+    Static = 9,
+    Trait = 10,
+    Impl = 11,
+    TyMethod = 12,
+    Method = 13,
+    StructField = 14,
+    Variant = 15,
+    Macro = 16,
+    AssocType = 17,
+    Constant = 18,
+    AssocConst = 19,
+    Union = 20,
+    ForeignType = 21,
     OpaqueTy = 22,
     ProcAttribute = 23,
     ProcDerive = 24,
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 22dcb870143..4822690fd04 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -18,28 +18,28 @@ if (!Array.prototype.toSpliced) {
 // This mapping table should match the discriminants of
 // `rustdoc::formats::item_type::ItemType` type in Rust.
 const itemTypes = [
+    "keyword",
+    "primitive",
     "mod",
     "externcrate",
     "import",
-    "struct",
+    "struct", // 5
     "enum",
-    "fn", // 5
+    "fn",
     "type",
     "static",
-    "trait",
+    "trait", // 10
     "impl",
-    "tymethod", // 10
+    "tymethod",
     "method",
     "structfield",
-    "variant",
+    "variant", // 15
     "macro",
-    "primitive", // 15
     "associatedtype",
     "constant",
     "associatedconstant",
-    "union",
-    "foreigntype", // 20
-    "keyword",
+    "union", // 20
+    "foreigntype",
     "existential",
     "attr",
     "derive",
@@ -48,6 +48,8 @@ const itemTypes = [
 ];
 
 const longItemTypes = [
+    "keyword",
+    "primitive type",
     "module",
     "extern crate",
     "re-export",
@@ -63,13 +65,11 @@ const longItemTypes = [
     "struct field",
     "enum variant",
     "macro",
-    "primitive type",
     "assoc type",
     "constant",
     "assoc const",
     "union",
     "foreign type",
-    "keyword",
     "existential type",
     "attribute macro",
     "derive macro",
@@ -77,8 +77,6 @@ const longItemTypes = [
 ];
 
 // used for special search precedence
-const TY_PRIMITIVE = itemTypes.indexOf("primitive");
-const TY_KEYWORD = itemTypes.indexOf("keyword");
 const TY_GENERIC = itemTypes.indexOf("generic");
 const ROOT_PATH = typeof window !== "undefined" ? window.rootPath : "../";
 
@@ -1317,16 +1315,6 @@ function initSearch(rawSearchIndex) {
                     return (a > b ? +1 : -1);
                 }
 
-                // special precedence for primitive and keyword pages
-                if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
-                    (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
-                    return -1;
-                }
-                if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
-                    (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
-                    return 1;
-                }
-
                 // sort by description (no description goes later)
                 a = (aaa.item.desc === "");
                 b = (bbb.item.desc === "");
@@ -1840,26 +1828,16 @@ function initSearch(rawSearchIndex) {
 
             const length = path.length;
             const clength = contains.length;
-            if (clength > length) {
-                return maxEditDistance + 1;
-            }
-            for (let i = 0; i < length; ++i) {
-                if (i + clength > length) {
-                    break;
-                }
+            pathiter: for (let i = length - clength; i >= 0; i -= 1) {
                 let dist_total = 0;
-                let aborted = false;
                 for (let x = 0; x < clength; ++x) {
                     const dist = editDistance(path[i + x], contains[x], maxEditDistance);
                     if (dist > maxEditDistance) {
-                        aborted = true;
-                        break;
+                        continue pathiter;
                     }
                     dist_total += dist;
                 }
-                if (!aborted) {
-                    ret_dist = Math.min(ret_dist, Math.round(dist_total / clength));
-                }
+                ret_dist = Math.min(ret_dist, Math.round(dist_total / clength));
             }
             return ret_dist;
         }
@@ -2953,7 +2931,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
             // https://mathiasbynens.be/notes/shapes-ics
             const crateRow = {
                 crate: crate,
-                ty: 1, // == ExternCrate
+                ty: 3, // == ExternCrate
                 name: crate,
                 path: "",
                 desc: crateCorpus.doc,
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 3b138b480b6..f6084a46272 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -37,7 +37,7 @@ toml = "0.7.3"
 walkdir = "2.3"
 # This is used by the `collect-metadata` alias.
 filetime = "0.2"
-itertools = "0.10.1"
+itertools = "0.11"
 
 # UI test dependencies
 clippy_utils = { path = "clippy_utils" }
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index c3f8a782d27..ce738e3f4ec 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 aho-corasick = "0.7"
 clap = "4.1.4"
 indoc = "1.0"
-itertools = "0.10.1"
+itertools = "0.11"
 opener = "0.5"
 shell-escape = "0.1"
 walkdir = "2.3"
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 84246d285c0..a9375214be4 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -14,7 +14,7 @@ cargo_metadata = "0.15.3"
 clippy_config = { path = "../clippy_config" }
 clippy_utils = { path = "../clippy_utils" }
 declare_clippy_lint = { path = "../declare_clippy_lint" }
-itertools = "0.10.1"
+itertools = "0.11"
 quine-mc_cluskey = "0.2"
 regex-syntax = "0.7"
 serde = { version = "1.0", features = ["derive"] }
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index d7053d3ff84..5d23326cec8 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -7,7 +7,7 @@ publish = false
 [dependencies]
 clippy_config = { path = "../clippy_config" }
 arrayvec = { version = "0.7", default-features = false }
-itertools = "0.10.1"
+itertools = "0.11"
 rustc-semver = "1.1"
 
 [features]
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 8c1150ed010..af123e107d5 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
 proc-macro = true
 
 [dependencies]
-itertools = "0.10.1"
+itertools = "0.11"
 quote = "1.0.21"
 syn = "2.0"
 
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index 00e0ed37a84..032b9b54810 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -43,7 +43,7 @@ diff = "0.1"
 dirs = "4.0"
 getopts = "0.2"
 ignore = "0.4"
-itertools = "0.10"
+itertools = "0.11"
 lazy_static = "1.4"
 regex = "1.7"
 serde = { version = "1.0.160", features = ["derive"] }
diff --git a/tests/rustdoc-js-std/keyword.js b/tests/rustdoc-js-std/keyword.js
index b85ba34138b..1837b1e71f7 100644
--- a/tests/rustdoc-js-std/keyword.js
+++ b/tests/rustdoc-js-std/keyword.js
@@ -3,7 +3,7 @@
 const EXPECTED = {
     'query': 'fn',
     'others': [
-        { 'path': 'std', 'name': 'fn', ty: 15 }, // 15 is for primitive types
-        { 'path': 'std', 'name': 'fn', ty: 21 }, // 21 is for keywords
+        { 'path': 'std', 'name': 'fn', ty: 1 }, // 1 is for primitive types
+        { 'path': 'std', 'name': 'fn', ty: 0 }, // 0 is for keywords
     ],
 };
diff --git a/tests/rustdoc-js-std/macro-check.js b/tests/rustdoc-js-std/macro-check.js
index c22b1753fd7..37d5e7dae62 100644
--- a/tests/rustdoc-js-std/macro-check.js
+++ b/tests/rustdoc-js-std/macro-check.js
@@ -3,7 +3,7 @@
 const EXPECTED = {
     'query': 'panic',
     'others': [
-        { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
-        { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
+        { 'path': 'std', 'name': 'panic', ty: 16 }, // 16 is for macros
+        { 'path': 'std', 'name': 'panic', ty: 2 }, // 2 is for modules
     ],
 };
diff --git a/tests/rustdoc-js-std/parser-bindings.js b/tests/rustdoc-js-std/parser-bindings.js
index faf880c8116..c4909c6242d 100644
--- a/tests/rustdoc-js-std/parser-bindings.js
+++ b/tests/rustdoc-js-std/parser-bindings.js
@@ -81,7 +81,7 @@ const PARSED = [
                             pathWithoutLast: [],
                             pathLast: "never",
                             generics: [],
-                            typeFilter: 15,
+                            typeFilter: 1,
                         }]
                     ],
                 ],
@@ -112,7 +112,7 @@ const PARSED = [
                             pathWithoutLast: [],
                             pathLast: "[]",
                             generics: [],
-                            typeFilter: 15,
+                            typeFilter: 1,
                         }]
                     ],
                 ],
@@ -149,10 +149,10 @@ const PARSED = [
                                     pathWithoutLast: [],
                                     pathLast: "never",
                                     generics: [],
-                                    typeFilter: 15,
+                                    typeFilter: 1,
                                 },
                             ],
-                            typeFilter: 15,
+                            typeFilter: 1,
                         }]
                     ],
                 ],
diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js
index 3b9cc5b1bf0..a1dd0ea3b5a 100644
--- a/tests/rustdoc-js-std/parser-filter.js
+++ b/tests/rustdoc-js-std/parser-filter.js
@@ -7,7 +7,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "foo",
             generics: [],
-            typeFilter: 5,
+            typeFilter: 7,
         }],
         foundElems: 1,
         original: "fn:foo",
@@ -23,7 +23,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "foo",
             generics: [],
-            typeFilter: 4,
+            typeFilter: 6,
         }],
         foundElems: 1,
         original: "enum : foo",
@@ -48,7 +48,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "macro",
             generics: [],
-            typeFilter: 14,
+            typeFilter: 16,
         }],
         foundElems: 1,
         original: "macro!",
@@ -64,7 +64,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "mac",
             generics: [],
-            typeFilter: 14,
+            typeFilter: 16,
         }],
         foundElems: 1,
         original: "macro:mac!",
@@ -80,7 +80,7 @@ const PARSED = [
             pathWithoutLast: ["a"],
             pathLast: "mac",
             generics: [],
-            typeFilter: 14,
+            typeFilter: 16,
         }],
         foundElems: 1,
         original: "a::mac!",
@@ -99,7 +99,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "foo",
             generics: [],
-            typeFilter: 5,
+            typeFilter: 7,
         }],
         userQuery: "-> fn:foo",
         error: null,
@@ -121,10 +121,10 @@ const PARSED = [
                     pathWithoutLast: [],
                     pathLast: "bar",
                     generics: [],
-                    typeFilter: 5,
+                    typeFilter: 7,
                 }
             ],
-            typeFilter: 5,
+            typeFilter: 7,
         }],
         userQuery: "-> fn:foo<fn:bar>",
         error: null,
@@ -146,7 +146,7 @@ const PARSED = [
                     pathWithoutLast: [],
                     pathLast: "bar",
                     generics: [],
-                    typeFilter: 5,
+                    typeFilter: 7,
                 },
                 {
                     name: "baz::fuzz",
@@ -154,10 +154,10 @@ const PARSED = [
                     pathWithoutLast: ["baz"],
                     pathLast: "fuzz",
                     generics: [],
-                    typeFilter: 4,
+                    typeFilter: 6,
                 },
             ],
-            typeFilter: 5,
+            typeFilter: 7,
         }],
         userQuery: "-> fn:foo<fn:bar, enum : baz::fuzz>",
         error: null,
diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js
index f65a7ce6692..cc79c58f1da 100644
--- a/tests/rustdoc-js-std/parser-ident.js
+++ b/tests/rustdoc-js-std/parser-ident.js
@@ -13,7 +13,7 @@ const PARSED = [
                     pathWithoutLast: [],
                     pathLast: "never",
                     generics: [],
-                    typeFilter: 15,
+                    typeFilter: 1,
                 },
             ],
             typeFilter: -1,
@@ -32,7 +32,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "never",
             generics: [],
-            typeFilter: 15,
+            typeFilter: 1,
         }],
         foundElems: 1,
         original: "!",
@@ -48,7 +48,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "a",
             generics: [],
-            typeFilter: 14,
+            typeFilter: 16,
         }],
         foundElems: 1,
         original: "a!",
diff --git a/tests/rustdoc-js-std/parser-returned.js b/tests/rustdoc-js-std/parser-returned.js
index 6ea86609115..44e517c49b5 100644
--- a/tests/rustdoc-js-std/parser-returned.js
+++ b/tests/rustdoc-js-std/parser-returned.js
@@ -89,7 +89,7 @@ const PARSED = [
             pathWithoutLast: [],
             pathLast: "never",
             generics: [],
-            typeFilter: 15,
+            typeFilter: 1,
         }],
         userQuery: "-> !",
         error: null,
diff --git a/tests/rustdoc-js-std/parser-slice-array.js b/tests/rustdoc-js-std/parser-slice-array.js
index c22b7870dbf..239391bed42 100644
--- a/tests/rustdoc-js-std/parser-slice-array.js
+++ b/tests/rustdoc-js-std/parser-slice-array.js
@@ -43,16 +43,16 @@ const PARSED = [
                                         pathWithoutLast: [],
                                         pathLast: "[]",
                                         generics: [],
-                                        typeFilter: 15,
+                                        typeFilter: 1,
                                     },
                                 ],
-                                typeFilter: 15,
+                                typeFilter: 1,
                             },
                         ],
-                        typeFilter: 15,
+                        typeFilter: 1,
                     },
                 ],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
@@ -70,7 +70,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "[]",
                 generics: [],
-                typeFilter: 15,
+                typeFilter: 1,
             },
             {
                 name: "u8",
@@ -105,7 +105,7 @@ const PARSED = [
                         typeFilter: -1,
                     },
                 ],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
@@ -140,7 +140,7 @@ const PARSED = [
                         typeFilter: -1,
                     },
                 ],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
@@ -176,7 +176,7 @@ const PARSED = [
                         typeFilter: -1,
                     },
                 ],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
@@ -194,7 +194,7 @@ const PARSED = [
                 pathWithoutLast: [],
                 pathLast: "[]",
                 generics: [],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
@@ -284,7 +284,7 @@ const PARSED = [
                         typeFilter: -1,
                     },
                 ],
-                typeFilter: 15,
+                typeFilter: 1,
             },
         ],
         foundElems: 1,
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index b0c459fabf8..19d9443d477 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
 LL | #[cfg(FALSE)]
    |       ^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs
new file mode 100644
index 00000000000..ea48c6ea201
--- /dev/null
+++ b/tests/ui/check-cfg/cargo-feature.rs
@@ -0,0 +1,14 @@
+// This test checks that when no features are passed by Cargo we
+// suggest adding some in the Cargo.toml instead of vomitting a
+// list of all the expected names
+//
+// check-pass
+// rustc-env:CARGO=/usr/bin/cargo
+// compile-flags: --check-cfg=cfg() -Z unstable-options
+// error-pattern:Cargo.toml
+
+#[cfg(feature = "serde")]
+//~^ WARNING unexpected `cfg` condition name
+fn ser() {}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/cargo-feature.stderr b/tests/ui/check-cfg/cargo-feature.stderr
new file mode 100644
index 00000000000..619410a28f3
--- /dev/null
+++ b/tests/ui/check-cfg/cargo-feature.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/cargo-feature.rs:10:7
+   |
+LL | #[cfg(feature = "serde")]
+   |       ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider defining some features in `Cargo.toml`
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index b0228774b75..ffde972a25e 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture`
 LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |                            ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 12a055d02a7..971abb1a21a 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
@@ -17,5 +17,17 @@ LL | #[cfg(test = "value")]
    |
    = note: no expected value for `test`
 
-warning: 2 warnings emitted
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/exhaustive-names-values.rs:19:7
+   |
+LL | #[cfg(feature = "unk")]
+   |       ^^^^^^^^^^^^^^^
+
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/exhaustive-names-values.rs:26:7
+   |
+LL | #[cfg(feature = "std")]
+   |       ^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
index 12a055d02a7..971abb1a21a 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
@@ -17,5 +17,17 @@ LL | #[cfg(test = "value")]
    |
    = note: no expected value for `test`
 
-warning: 2 warnings emitted
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/exhaustive-names-values.rs:19:7
+   |
+LL | #[cfg(feature = "unk")]
+   |       ^^^^^^^^^^^^^^^
+
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/exhaustive-names-values.rs:26:7
+   |
+LL | #[cfg(feature = "std")]
+   |       ^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.rs b/tests/ui/check-cfg/exhaustive-names-values.rs
index ef1e458b249..ceb4831e22d 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.rs
+++ b/tests/ui/check-cfg/exhaustive-names-values.rs
@@ -17,11 +17,15 @@ pub fn f() {}
 pub fn f() {}
 
 #[cfg(feature = "unk")]
-//[feature]~^ WARNING unexpected `cfg` condition value
-//[full]~^^ WARNING unexpected `cfg` condition value
+//[empty_names_values]~^ WARNING unexpected `cfg` condition name
+//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
+//[feature]~^^^ WARNING unexpected `cfg` condition value
+//[full]~^^^^ WARNING unexpected `cfg` condition value
 pub fn feat() {}
 
 #[cfg(feature = "std")]
+//[empty_names_values]~^ WARNING unexpected `cfg` condition name
+//[empty_cfg]~^^ WARNING unexpected `cfg` condition name
 pub fn feat() {}
 
 #[cfg(windows)]
diff --git a/tests/ui/check-cfg/exhaustive-names.empty_names.stderr b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr
index 6bc7845c832..7d01c73cc09 100644
--- a/tests/ui/check-cfg/exhaustive-names.empty_names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.empty_names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
index 6bc7845c832..7d01c73cc09 100644
--- a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index 900ea4e4da0..3fb3ae27ec4 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom`
 LL |     #[cfg(crossbeam_loom)]
    |           ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs
index 1dcb419b4a7..32c14703d25 100644
--- a/tests/ui/check-cfg/well-known-names.rs
+++ b/tests/ui/check-cfg/well-known-names.rs
@@ -15,6 +15,7 @@ fn target_os() {}
 fn feature_misspell() {}
 
 #[cfg(feature = "foo")]
+//~^ WARNING unexpected `cfg` condition name
 fn feature() {}
 
 #[cfg(uniw)]
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index 3001289b7e0..a986e61bcdc 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -14,15 +14,21 @@ warning: unexpected `cfg` condition name: `features`
   --> $DIR/well-known-names.rs:13:7
    |
 LL | #[cfg(features = "foo")]
-   |       --------^^^^^^^^
-   |       |
-   |       help: there is a config with a similar name: `feature`
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+
+warning: unexpected `cfg` condition name: `feature`
+  --> $DIR/well-known-names.rs:17:7
+   |
+LL | #[cfg(feature = "foo")]
+   |       ^^^^^^^^^^^^^^^
 
 warning: unexpected `cfg` condition name: `uniw`
-  --> $DIR/well-known-names.rs:20:7
+  --> $DIR/well-known-names.rs:21:7
    |
 LL | #[cfg(uniw)]
    |       ^^^^ help: there is a config with a similar name: `unix`
 
-warning: 3 warnings emitted
+warning: 4 warnings emitted
 
diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
new file mode 100644
index 00000000000..c8f6db7aef3
--- /dev/null
+++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
@@ -0,0 +1,29 @@
+// Test against ICE in #118111
+
+use std::ops::Index;
+
+struct Map<T, F> {
+    f: F,
+    inner: T,
+}
+
+impl<T, F, Idx> Index<Idx> for Map<T, F>
+where
+    T: Index<Idx>,
+    F: FnOnce(&T, Idx) -> Idx,
+{
+    type Output = T::Output;
+
+    fn index(&self, index: Idx) -> &Self::Output {
+        todo!()
+    }
+}
+
+fn main() {
+    Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
+    //~^ ERROR cannot index into a value of type
+    // Problem here is that
+    //   `f: |_, i: usize| ...`
+    // should be
+    //   `f: |_: &_, i: usize| ...`
+}
diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
new file mode 100644
index 00000000000..7c978430839
--- /dev/null
+++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `Map<[usize; 1], {closure@$DIR/bad-index-modulo-higher-ranked-regions.rs:23:32: 23:45}>`
+  --> $DIR/bad-index-modulo-higher-ranked-regions.rs:23:55
+   |
+LL |     Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
+   |                                                       ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.