diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
index 8bc62418b3969..7b865c9c679bc 100644
--- a/src/doc/unstable-book/src/language-features/generators.md
+++ b/src/doc/unstable-book/src/language-features/generators.md
@@ -87,7 +87,7 @@ Feedback on the design and usage is always appreciated!
 
 The `Generator` trait in `std::ops` currently looks like:
 
-```
+```rust
 # #![feature(arbitrary_self_types, generator_trait)]
 # use std::ops::GeneratorState;
 # use std::pin::Pin;
@@ -107,7 +107,7 @@ point for executing the `Generator` itself.
 
 The return value of `resume`, `GeneratorState`, looks like:
 
-```
+```rust
 pub enum GeneratorState<Y, R> {
     Yielded(Y),
     Complete(R),
diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs
index 47ab8715cfa14..eef9ee7cb0093 100644
--- a/src/libcore/convert/mod.rs
+++ b/src/libcore/convert/mod.rs
@@ -41,6 +41,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::fmt;
+use crate::hash::{Hash, Hasher};
 
 mod num;
 
@@ -746,3 +747,10 @@ impl From<!> for Infallible {
         x
     }
 }
+
+#[stable(feature = "convert_infallible_hash", since = "1.44.0")]
+impl Hash for Infallible {
+    fn hash<H: Hasher>(&self, _: &mut H) {
+        match *self {}
+    }
+}
diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs
index fcb7475cc2e89..5ccfc1b276bfa 100644
--- a/src/librustc_lexer/src/lib.rs
+++ b/src/librustc_lexer/src/lib.rs
@@ -148,6 +148,10 @@ pub enum LiteralKind {
 pub struct UnvalidatedRawStr {
     /// The prefix (`r###"`) is valid
     valid_start: bool,
+
+    /// The postfix (`"###`) is valid
+    valid_end: bool,
+
     /// The number of leading `#`
     n_start_hashes: usize,
     /// The number of trailing `#`. `n_end_hashes` <= `n_start_hashes`
@@ -197,7 +201,7 @@ impl UnvalidatedRawStr {
         let n_start_safe: u16 =
             self.n_start_hashes.try_into().map_err(|_| LexRawStrError::TooManyDelimiters)?;
 
-        if self.n_start_hashes > self.n_end_hashes {
+        if self.n_start_hashes > self.n_end_hashes || !self.valid_end {
             Err(LexRawStrError::NoTerminator {
                 expected: self.n_start_hashes,
                 found: self.n_end_hashes,
@@ -687,6 +691,7 @@ impl Cursor<'_> {
             _ => {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: false,
                     n_start_hashes,
                     n_end_hashes: 0,
                     possible_terminator_offset,
@@ -702,6 +707,7 @@ impl Cursor<'_> {
             if self.is_eof() {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: false,
                     n_start_hashes,
                     n_end_hashes: max_hashes,
                     possible_terminator_offset,
@@ -727,6 +733,7 @@ impl Cursor<'_> {
             if n_end_hashes == n_start_hashes {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: true,
                     n_start_hashes,
                     n_end_hashes,
                     possible_terminator_offset: None,
diff --git a/src/librustc_lexer/src/tests.rs b/src/librustc_lexer/src/tests.rs
index 4af435536f011..06fc159fe2516 100644
--- a/src/librustc_lexer/src/tests.rs
+++ b/src/librustc_lexer/src/tests.rs
@@ -23,6 +23,7 @@ mod tests {
                 n_start_hashes: 0,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: true,
                 possible_terminator_offset: None,
             },
             Ok(ValidatedRawStr { n_hashes: 0 }),
@@ -37,6 +38,7 @@ mod tests {
                 n_start_hashes: 0,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: true,
                 possible_terminator_offset: None,
             },
             Ok(ValidatedRawStr { n_hashes: 0 }),
@@ -51,6 +53,7 @@ mod tests {
             UnvalidatedRawStr {
                 n_start_hashes: 1,
                 n_end_hashes: 1,
+                valid_end: true,
                 valid_start: true,
                 possible_terminator_offset: None,
             },
@@ -65,6 +68,7 @@ mod tests {
             UnvalidatedRawStr {
                 n_start_hashes: 1,
                 n_end_hashes: 0,
+                valid_end: false,
                 valid_start: true,
                 possible_terminator_offset: None,
             },
@@ -80,6 +84,7 @@ mod tests {
                 n_start_hashes: 2,
                 n_end_hashes: 1,
                 valid_start: true,
+                valid_end: false,
                 possible_terminator_offset: Some(7),
             },
             Err(LexRawStrError::NoTerminator {
@@ -95,6 +100,7 @@ mod tests {
                 n_start_hashes: 2,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: false,
                 possible_terminator_offset: None,
             },
             Err(LexRawStrError::NoTerminator {
@@ -113,9 +119,30 @@ mod tests {
                 n_start_hashes: 1,
                 n_end_hashes: 0,
                 valid_start: false,
+                valid_end: false,
                 possible_terminator_offset: None,
             },
             Err(LexRawStrError::InvalidStarter),
         );
     }
+
+    #[test]
+    fn test_unterminated_no_pound() {
+        // https://github.com/rust-lang/rust/issues/70677
+        check_raw_str(
+            r#"""#,
+            UnvalidatedRawStr {
+                n_start_hashes: 0,
+                n_end_hashes: 0,
+                valid_start: true,
+                valid_end: false,
+                possible_terminator_offset: None,
+            },
+            Err(LexRawStrError::NoTerminator {
+                expected: 0,
+                found: 0,
+                possible_terminator_offset: None,
+            }),
+        );
+    }
 }
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 004c5f2ebb7f4..04aa8187e1fe9 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -633,7 +633,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
-        self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self))
+        self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
     }
 
     fn kind(&self, item_id: DefIndex) -> EntryKind {
@@ -665,7 +665,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 .expect("no name in item_ident");
             let span = self
                 .root
-                .per_def
+                .tables
                 .ident_span
                 .get(self, item_index)
                 .map(|data| data.decode((self, sess)))
@@ -688,7 +688,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
-        self.root.per_def.span.get(self, index).unwrap().decode((self, sess))
+        self.root.tables.span.get(self, index).unwrap().decode((self, sess))
     }
 
     fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
@@ -781,7 +781,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             ctor_did,
             data.discr,
             self.root
-                .per_def
+                .tables
                 .children
                 .get(self, index)
                 .unwrap_or(Lazy::empty())
@@ -812,7 +812,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         let variants = if let ty::AdtKind::Enum = adt_kind {
             self.root
-                .per_def
+                .tables
                 .children
                 .get(self, item_id)
                 .unwrap_or(Lazy::empty())
@@ -831,7 +831,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
-        self.root.per_def.explicit_predicates.get(self, item_id).unwrap().decode((self, tcx))
+        self.root.tables.explicit_predicates.get(self, item_id).unwrap().decode((self, tcx))
     }
 
     fn get_inferred_outlives(
@@ -840,7 +840,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         tcx: TyCtxt<'tcx>,
     ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
         self.root
-            .per_def
+            .tables
             .inferred_outlives
             .get(self, item_id)
             .map(|predicates| predicates.decode((self, tcx)))
@@ -852,31 +852,31 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         item_id: DefIndex,
         tcx: TyCtxt<'tcx>,
     ) -> ty::GenericPredicates<'tcx> {
-        self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
+        self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx))
     }
 
     fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics {
-        self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess))
+        self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess))
     }
 
     fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx))
+        self.root.tables.ty.get(self, id).unwrap().decode((self, tcx))
     }
 
     fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
         match self.is_proc_macro(id) {
             true => self.root.proc_macro_stability,
-            false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)),
+            false => self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)),
         }
     }
 
     fn get_const_stability(&self, id: DefIndex) -> Option<attr::ConstStability> {
-        self.root.per_def.const_stability.get(self, id).map(|stab| stab.decode(self))
+        self.root.tables.const_stability.get(self, id).map(|stab| stab.decode(self))
     }
 
     fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
         self.root
-            .per_def
+            .tables
             .deprecation
             .get(self, id)
             .filter(|_| !self.is_proc_macro(id))
@@ -886,7 +886,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
         match self.is_proc_macro(id) {
             true => ty::Visibility::Public,
-            false => self.root.per_def.visibility.get(self, id).unwrap().decode(self),
+            false => self.root.tables.visibility.get(self, id).unwrap().decode(self),
         }
     }
 
@@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option<ty::TraitRef<'tcx>> {
-        self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
+        self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx)))
     }
 
     /// Iterates over all the stability attributes in the given crate.
@@ -984,7 +984,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         // Iterate over all children.
         let macros_only = self.dep_kind.lock().macros_only();
-        let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty());
+        let children = self.root.tables.children.get(self, id).unwrap_or(Lazy::empty());
         for child_index in children.decode((self, sess)) {
             if macros_only {
                 continue;
@@ -1004,7 +1004,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                     EntryKind::ForeignMod => {
                         let child_children = self
                             .root
-                            .per_def
+                            .tables
                             .children
                             .get(self, child_index)
                             .unwrap_or(Lazy::empty());
@@ -1016,7 +1016,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                                     vis: self.get_visibility(child_index),
                                     span: self
                                         .root
-                                        .per_def
+                                        .tables
                                         .span
                                         .get(self, child_index)
                                         .unwrap()
@@ -1096,13 +1096,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn is_item_mir_available(&self, id: DefIndex) -> bool {
-        !self.is_proc_macro(id) && self.root.per_def.mir.get(self, id).is_some()
+        !self.is_proc_macro(id) && self.root.tables.mir.get(self, id).is_some()
     }
 
     fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> BodyAndCache<'tcx> {
         let mut cache = self
             .root
-            .per_def
+            .tables
             .mir
             .get(self, id)
             .filter(|_| !self.is_proc_macro(id))
@@ -1121,7 +1121,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     ) -> IndexVec<Promoted, BodyAndCache<'tcx>> {
         let mut cache = self
             .root
-            .per_def
+            .tables
             .promoted_mir
             .get(self, id)
             .filter(|_| !self.is_proc_macro(id))
@@ -1172,7 +1172,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
-        self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty()).decode(self).collect()
+        self.root.tables.variances.get(self, id).unwrap_or(Lazy::empty()).decode(self).collect()
     }
 
     fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
@@ -1209,7 +1209,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         Lrc::from(
             self.root
-                .per_def
+                .tables
                 .attributes
                 .get(self, item_id)
                 .unwrap_or(Lazy::empty())
@@ -1220,7 +1220,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec<Spanned<ast::Name>> {
         self.root
-            .per_def
+            .tables
             .children
             .get(self, id)
             .unwrap_or(Lazy::empty())
@@ -1236,7 +1236,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     ) -> &'tcx [DefId] {
         tcx.arena.alloc_from_iter(
             self.root
-                .per_def
+                .tables
                 .inherent_impls
                 .get(self, id)
                 .unwrap_or(Lazy::empty())
@@ -1416,7 +1416,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
-        self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx))
+        self.root.tables.fn_sig.get(self, id).unwrap().decode((self, tcx))
     }
 
     #[inline]
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index f6e2730cb5761..3cc5fb1a991e1 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -45,7 +45,7 @@ struct EncodeContext<'tcx> {
     opaque: opaque::Encoder,
     tcx: TyCtxt<'tcx>,
 
-    per_def: PerDefTableBuilders<'tcx>,
+    tables: TableBuilders<'tcx>,
 
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -497,8 +497,8 @@ impl<'tcx> EncodeContext<'tcx> {
         };
 
         i = self.position();
-        let per_def = self.per_def.encode(&mut self.opaque);
-        let per_def_bytes = self.position() - i;
+        let tables = self.tables.encode(&mut self.opaque);
+        let tables_bytes = self.position() - i;
 
         // Encode the proc macro data
         i = self.position();
@@ -560,7 +560,7 @@ impl<'tcx> EncodeContext<'tcx> {
             impls,
             exported_symbols,
             interpret_alloc_index,
-            per_def,
+            tables,
         });
 
         let total_bytes = self.position();
@@ -585,7 +585,7 @@ impl<'tcx> EncodeContext<'tcx> {
             println!("  def-path table bytes: {}", def_path_table_bytes);
             println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
             println!("            item bytes: {}", item_bytes);
-            println!("   per-def table bytes: {}", per_def_bytes);
+            println!("           table bytes: {}", tables_bytes);
             println!("            zero bytes: {}", zero_bytes);
             println!("           total bytes: {}", total_bytes);
         }
@@ -597,12 +597,12 @@ impl<'tcx> EncodeContext<'tcx> {
 impl EncodeContext<'tcx> {
     fn encode_variances_of(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_variances_of({:?})", def_id);
-        record!(self.per_def.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
+        record!(self.tables.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
     }
 
     fn encode_item_type(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_item_type({:?})", def_id);
-        record!(self.per_def.ty[def_id] <- self.tcx.type_of(def_id));
+        record!(self.tables.ty[def_id] <- self.tcx.type_of(def_id));
     }
 
     fn encode_enum_variant_info(&mut self, enum_did: DefId, index: VariantIdx) {
@@ -621,12 +621,12 @@ impl EncodeContext<'tcx> {
         let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
         let enum_vis = &tcx.hir().expect_item(enum_id).vis;
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
-        record!(self.per_def.visibility[def_id] <-
+        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
+        record!(self.tables.visibility[def_id] <-
             ty::Visibility::from_hir(enum_vis, enum_id, self.tcx));
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
-        record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
-        record!(self.per_def.children[def_id] <- variant.fields.iter().map(|f| {
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
+        record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
             assert!(f.did.is_local());
             f.did.index
         }));
@@ -637,7 +637,7 @@ impl EncodeContext<'tcx> {
         if variant.ctor_kind == CtorKind::Fn {
             // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
             if let Some(ctor_def_id) = variant.ctor_def_id {
-                record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
+                record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id));
             }
             // FIXME(eddyb) is this ever used?
             self.encode_variances_of(def_id);
@@ -672,14 +672,14 @@ impl EncodeContext<'tcx> {
             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
         }
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
-        record!(self.per_def.visibility[def_id] <- ctor_vis);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
+        record!(self.tables.visibility[def_id] <- ctor_vis);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -707,11 +707,11 @@ impl EncodeContext<'tcx> {
             },
         };
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
-        record!(self.per_def.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
-        record!(self.per_def.attributes[def_id] <- attrs);
-        record!(self.per_def.children[def_id] <- md.item_ids.iter().map(|item_id| {
+        record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
+        record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.attributes[def_id] <- attrs);
+        record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
             tcx.hir().local_def_id(item_id.id).index
         }));
         self.encode_stability(def_id);
@@ -729,10 +729,10 @@ impl EncodeContext<'tcx> {
         let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
         let variant_data = tcx.hir().expect_variant_data(variant_id);
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Field);
-        record!(self.per_def.visibility[def_id] <- field.vis);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
-        record!(self.per_def.attributes[def_id] <- variant_data.fields()[field_index].attrs);
+        record!(self.tables.kind[def_id] <- EntryKind::Field);
+        record!(self.tables.visibility[def_id] <- field.vis);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.attributes[def_id] <- variant_data.fields()[field_index].attrs);
         self.encode_ident_span(def_id, field.ident);
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
@@ -771,14 +771,14 @@ impl EncodeContext<'tcx> {
             ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
         }
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
-        record!(self.per_def.visibility[def_id] <- ctor_vis);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr));
+        record!(self.tables.visibility[def_id] <- ctor_vis);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if variant.ctor_kind == CtorKind::Fn {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -790,12 +790,12 @@ impl EncodeContext<'tcx> {
 
     fn encode_generics(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_generics({:?})", def_id);
-        record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id));
+        record!(self.tables.generics[def_id] <- self.tcx.generics_of(def_id));
     }
 
     fn encode_explicit_predicates(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_explicit_predicates({:?})", def_id);
-        record!(self.per_def.explicit_predicates[def_id] <-
+        record!(self.tables.explicit_predicates[def_id] <-
             self.tcx.explicit_predicates_of(def_id));
     }
 
@@ -803,13 +803,13 @@ impl EncodeContext<'tcx> {
         debug!("EncodeContext::encode_inferred_outlives({:?})", def_id);
         let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
         if !inferred_outlives.is_empty() {
-            record!(self.per_def.inferred_outlives[def_id] <- inferred_outlives);
+            record!(self.tables.inferred_outlives[def_id] <- inferred_outlives);
         }
     }
 
     fn encode_super_predicates(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_super_predicates({:?})", def_id);
-        record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
+        record!(self.tables.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id));
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) {
@@ -826,7 +826,7 @@ impl EncodeContext<'tcx> {
             hir::Defaultness::Final => span_bug!(ast_item.span, "traits cannot have final items"),
         };
 
-        record!(self.per_def.kind[def_id] <- match trait_item.kind {
+        record!(self.tables.kind[def_id] <- match trait_item.kind {
             ty::AssocKind::Const => {
                 let rendered = rustc_hir_pretty::to_string(
                     &(&self.tcx.hir() as &dyn intravisit::Map<'_>),
@@ -867,9 +867,9 @@ impl EncodeContext<'tcx> {
             ty::AssocKind::Type => EntryKind::AssocType(container),
             ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"),
         });
-        record!(self.per_def.visibility[def_id] <- trait_item.vis);
-        record!(self.per_def.span[def_id] <- ast_item.span);
-        record!(self.per_def.attributes[def_id] <- ast_item.attrs);
+        record!(self.tables.visibility[def_id] <- trait_item.vis);
+        record!(self.tables.span[def_id] <- ast_item.span);
+        record!(self.tables.attributes[def_id] <- ast_item.attrs);
         self.encode_ident_span(def_id, ast_item.ident);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
@@ -886,7 +886,7 @@ impl EncodeContext<'tcx> {
             ty::AssocKind::OpaqueTy => unreachable!(),
         }
         if trait_item.kind == ty::AssocKind::Method {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -919,7 +919,7 @@ impl EncodeContext<'tcx> {
             }
         };
 
-        record!(self.per_def.kind[def_id] <- match impl_item.kind {
+        record!(self.tables.kind[def_id] <- match impl_item.kind {
             ty::AssocKind::Const => {
                 if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind {
                     let qualifs = self.tcx.at(ast_item.span).mir_const_qualif(def_id);
@@ -951,16 +951,16 @@ impl EncodeContext<'tcx> {
             ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container),
             ty::AssocKind::Type => EntryKind::AssocType(container)
         });
-        record!(self.per_def.visibility[def_id] <- impl_item.vis);
-        record!(self.per_def.span[def_id] <- ast_item.span);
-        record!(self.per_def.attributes[def_id] <- ast_item.attrs);
+        record!(self.tables.visibility[def_id] <- impl_item.vis);
+        record!(self.tables.span[def_id] <- ast_item.span);
+        record!(self.tables.attributes[def_id] <- ast_item.attrs);
         self.encode_ident_span(def_id, impl_item.ident);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if impl_item.kind == ty::AssocKind::Method {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -1005,14 +1005,14 @@ impl EncodeContext<'tcx> {
     fn encode_optimized_mir(&mut self, def_id: DefId) {
         debug!("EntryBuilder::encode_mir({:?})", def_id);
         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
-            record!(self.per_def.mir[def_id] <- self.tcx.optimized_mir(def_id));
+            record!(self.tables.mir[def_id] <- self.tcx.optimized_mir(def_id));
         }
     }
 
     fn encode_promoted_mir(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_promoted_mir({:?})", def_id);
         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
-            record!(self.per_def.promoted_mir[def_id] <- self.tcx.promoted_mir(def_id));
+            record!(self.tables.promoted_mir[def_id] <- self.tcx.promoted_mir(def_id));
         }
     }
 
@@ -1021,7 +1021,7 @@ impl EncodeContext<'tcx> {
         debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
         let implementations = self.tcx.inherent_impls(def_id);
         if !implementations.is_empty() {
-            record!(self.per_def.inherent_impls[def_id] <- implementations.iter().map(|&def_id| {
+            record!(self.tables.inherent_impls[def_id] <- implementations.iter().map(|&def_id| {
                 assert!(def_id.is_local());
                 def_id.index
             }));
@@ -1031,21 +1031,21 @@ impl EncodeContext<'tcx> {
     fn encode_stability(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_stability({:?})", def_id);
         if let Some(stab) = self.tcx.lookup_stability(def_id) {
-            record!(self.per_def.stability[def_id] <- stab)
+            record!(self.tables.stability[def_id] <- stab)
         }
     }
 
     fn encode_const_stability(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_const_stability({:?})", def_id);
         if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
-            record!(self.per_def.const_stability[def_id] <- stab)
+            record!(self.tables.const_stability[def_id] <- stab)
         }
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_deprecation({:?})", def_id);
         if let Some(depr) = self.tcx.lookup_deprecation(def_id) {
-            record!(self.per_def.deprecation[def_id] <- depr);
+            record!(self.tables.deprecation[def_id] <- depr);
         }
     }
 
@@ -1066,7 +1066,7 @@ impl EncodeContext<'tcx> {
 
         self.encode_ident_span(def_id, item.ident);
 
-        record!(self.per_def.kind[def_id] <- match item.kind {
+        record!(self.tables.kind[def_id] <- match item.kind {
             hir::ItemKind::Static(_, hir::Mutability::Mut, _) => EntryKind::MutStatic,
             hir::ItemKind::Static(_, hir::Mutability::Not, _) => EntryKind::ImmStatic,
             hir::ItemKind::Const(_, body_id) => {
@@ -1172,26 +1172,26 @@ impl EncodeContext<'tcx> {
             hir::ItemKind::ExternCrate(_) |
             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
         });
-        record!(self.per_def.visibility[def_id] <-
+        record!(self.tables.visibility[def_id] <-
             ty::Visibility::from_hir(&item.vis, item.hir_id, tcx));
-        record!(self.per_def.span[def_id] <- item.span);
-        record!(self.per_def.attributes[def_id] <- item.attrs);
+        record!(self.tables.span[def_id] <- item.span);
+        record!(self.tables.attributes[def_id] <- item.attrs);
         // FIXME(eddyb) there should be a nicer way to do this.
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <-
+            hir::ItemKind::ForeignMod(ref fm) => record!(self.tables.children[def_id] <-
                 fm.items
                     .iter()
                     .map(|foreign_item| tcx.hir().local_def_id(
                         foreign_item.hir_id).index)
             ),
-            hir::ItemKind::Enum(..) => record!(self.per_def.children[def_id] <-
+            hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
                 self.tcx.adt_def(def_id).variants.iter().map(|v| {
                     assert!(v.def_id.is_local());
                     v.def_id.index
                 })
             ),
             hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
-                record!(self.per_def.children[def_id] <-
+                record!(self.tables.children[def_id] <-
                     self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
                         assert!(f.did.is_local());
                         f.did.index
@@ -1200,7 +1200,7 @@ impl EncodeContext<'tcx> {
             }
             hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
-                record!(self.per_def.children[def_id] <-
+                record!(self.tables.children[def_id] <-
                     associated_item_def_ids.iter().map(|&def_id| {
                         assert!(def_id.is_local());
                         def_id.index
@@ -1225,11 +1225,11 @@ impl EncodeContext<'tcx> {
             _ => {}
         }
         if let hir::ItemKind::Fn(..) = item.kind {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
         }
         if let hir::ItemKind::Impl { .. } = item.kind {
             if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
-                record!(self.per_def.impl_trait_ref[def_id] <- trait_ref);
+                record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
             }
         }
         self.encode_inherent_implementations(def_id);
@@ -1288,19 +1288,19 @@ impl EncodeContext<'tcx> {
     /// Serialize the text of exported macros
     fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
         let def_id = self.tcx.hir().local_def_id(macro_def.hir_id);
-        record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
-        record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
-        record!(self.per_def.span[def_id] <- macro_def.span);
-        record!(self.per_def.attributes[def_id] <- macro_def.attrs);
+        record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
+        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
+        record!(self.tables.span[def_id] <- macro_def.span);
+        record!(self.tables.attributes[def_id] <- macro_def.attrs);
         self.encode_ident_span(def_id, macro_def.ident);
         self.encode_stability(def_id);
         self.encode_deprecation(def_id);
     }
 
     fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
-        record!(self.per_def.kind[def_id] <- kind);
-        record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.kind[def_id] <- kind);
+        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
         if encode_type {
             self.encode_item_type(def_id);
         }
@@ -1314,7 +1314,7 @@ impl EncodeContext<'tcx> {
         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
         let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id);
 
-        record!(self.per_def.kind[def_id] <- match ty.kind {
+        record!(self.tables.kind[def_id] <- match ty.kind {
             ty::Generator(..) => {
                 let data = self.tcx.generator_kind(def_id).unwrap();
                 EntryKind::Generator(data)
@@ -1324,12 +1324,12 @@ impl EncodeContext<'tcx> {
 
             _ => bug!("closure that is neither generator nor closure"),
         });
-        record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
-        record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
+        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]);
         self.encode_item_type(def_id);
         if let ty::Closure(def_id, substs) = ty.kind {
-            record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig());
+            record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
         }
         self.encode_generics(def_id);
         self.encode_optimized_mir(def_id);
@@ -1343,9 +1343,9 @@ impl EncodeContext<'tcx> {
         let const_data = self.encode_rendered_const_for_body(body_id);
         let qualifs = self.tcx.mir_const_qualif(def_id);
 
-        record!(self.per_def.kind[def_id] <- EntryKind::Const(qualifs, const_data));
-        record!(self.per_def.visibility[def_id] <- ty::Visibility::Public);
-        record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id));
+        record!(self.tables.kind[def_id] <- EntryKind::Const(qualifs, const_data));
+        record!(self.tables.visibility[def_id] <- ty::Visibility::Public);
+        record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
         self.encode_item_type(def_id);
         self.encode_generics(def_id);
         self.encode_explicit_predicates(def_id);
@@ -1516,7 +1516,7 @@ impl EncodeContext<'tcx> {
 
         debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
 
-        record!(self.per_def.kind[def_id] <- match nitem.kind {
+        record!(self.tables.kind[def_id] <- match nitem.kind {
             hir::ForeignItemKind::Fn(_, ref names, _) => {
                 let data = FnData {
                     asyncness: hir::IsAsync::NotAsync,
@@ -1533,17 +1533,17 @@ impl EncodeContext<'tcx> {
             hir::ForeignItemKind::Static(_, hir::Mutability::Not) => EntryKind::ForeignImmStatic,
             hir::ForeignItemKind::Type => EntryKind::ForeignType,
         });
-        record!(self.per_def.visibility[def_id] <-
+        record!(self.tables.visibility[def_id] <-
             ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx));
-        record!(self.per_def.span[def_id] <- nitem.span);
-        record!(self.per_def.attributes[def_id] <- nitem.attrs);
+        record!(self.tables.span[def_id] <- nitem.span);
+        record!(self.tables.attributes[def_id] <- nitem.attrs);
         self.encode_ident_span(def_id, nitem.ident);
         self.encode_stability(def_id);
         self.encode_const_stability(def_id);
         self.encode_deprecation(def_id);
         self.encode_item_type(def_id);
         if let hir::ForeignItemKind::Fn(..) = nitem.kind {
-            record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
+            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
             self.encode_variances_of(def_id);
         }
         self.encode_generics(def_id);
@@ -1630,7 +1630,7 @@ impl EncodeContext<'tcx> {
     }
 
     fn encode_ident_span(&mut self, def_id: DefId, ident: Ident) {
-        record!(self.per_def.ident_span[def_id] <- ident.span);
+        record!(self.tables.ident_span[def_id] <- ident.span);
     }
 
     /// In some cases, along with the item itself, we also
@@ -1846,7 +1846,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
     let mut ecx = EncodeContext {
         opaque: encoder,
         tcx,
-        per_def: Default::default(),
+        tables: Default::default(),
         lazy_state: LazyState::NoNode,
         type_shorthands: Default::default(),
         predicate_shorthands: Default::default(),
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index d0ad76b0fc7ea..8aa70293aab01 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -197,7 +197,7 @@ crate struct CrateRoot<'tcx> {
     impls: Lazy<[TraitImpls]>,
     interpret_alloc_index: Lazy<[u32]>,
 
-    per_def: LazyPerDefTables<'tcx>,
+    tables: LazyTables<'tcx>,
 
     /// The DefIndex's of any proc macros declared by this crate.
     proc_macro_data: Option<Lazy<[DefIndex]>>,
@@ -228,22 +228,22 @@ crate struct TraitImpls {
     impls: Lazy<[DefIndex]>,
 }
 
-/// Define `LazyPerDefTables` and `PerDefTableBuilders` at the same time.
-macro_rules! define_per_def_tables {
+/// Define `LazyTables` and `TableBuilders` at the same time.
+macro_rules! define_tables {
     ($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
         #[derive(RustcEncodable, RustcDecodable)]
-        crate struct LazyPerDefTables<'tcx> {
+        crate struct LazyTables<'tcx> {
             $($name: Lazy!(Table<DefIndex, $T>)),+
         }
 
         #[derive(Default)]
-        struct PerDefTableBuilders<'tcx> {
+        struct TableBuilders<'tcx> {
             $($name: TableBuilder<DefIndex, $T>),+
         }
 
-        impl PerDefTableBuilders<'tcx> {
-            fn encode(&self, buf: &mut Encoder) -> LazyPerDefTables<'tcx> {
-                LazyPerDefTables {
+        impl TableBuilders<'tcx> {
+            fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
+                LazyTables {
                     $($name: self.$name.encode(buf)),+
                 }
             }
@@ -251,7 +251,7 @@ macro_rules! define_per_def_tables {
     }
 }
 
-define_per_def_tables! {
+define_tables! {
     kind: Table<DefIndex, Lazy<EntryKind>>,
     visibility: Table<DefIndex, Lazy<ty::Visibility>>,
     span: Table<DefIndex, Lazy<Span>>,
diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs
index 5243e1fbf579b..99a6511b297ac 100644
--- a/src/librustc_middle/ty/flags.rs
+++ b/src/librustc_middle/ty/flags.rs
@@ -1,4 +1,4 @@
-use crate::ty::subst::{GenericArgKind, SubstsRef};
+use crate::ty::subst::{GenericArg, GenericArgKind};
 use crate::ty::{self, InferConst, Ty, TypeFlags};
 
 #[derive(Debug)]
@@ -81,6 +81,7 @@ impl FlagComputation {
 
             &ty::Param(_) => {
                 self.add_flags(TypeFlags::HAS_TY_PARAM);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
             &ty::Generator(_, ref substs, _) => {
@@ -99,14 +100,17 @@ impl FlagComputation {
 
             &ty::Bound(debruijn, _) => {
                 self.add_binder(debruijn);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
             &ty::Placeholder(..) => {
                 self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
             &ty::Infer(infer) => {
                 self.add_flags(TypeFlags::HAS_TY_INFER);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 match infer {
                     ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {}
 
@@ -218,17 +222,23 @@ impl FlagComputation {
             }
             ty::ConstKind::Infer(infer) => {
                 self.add_flags(TypeFlags::HAS_CT_INFER);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
                 match infer {
                     InferConst::Fresh(_) => {}
                     InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
                 }
             }
-            ty::ConstKind::Bound(debruijn, _) => self.add_binder(debruijn),
+            ty::ConstKind::Bound(debruijn, _) => {
+                self.add_binder(debruijn);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+            }
             ty::ConstKind::Param(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PARAM);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Placeholder(_) => {
                 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
+                self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Value(_) => {}
         }
@@ -243,7 +253,7 @@ impl FlagComputation {
         self.add_substs(projection_ty.substs);
     }
 
-    fn add_substs(&mut self, substs: SubstsRef<'_>) {
+    fn add_substs(&mut self, substs: &[GenericArg<'_>]) {
         for kind in substs {
             match kind.unpack() {
                 GenericArgKind::Type(ty) => self.add_ty(ty),
diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs
index 3f4f2407f1e6e..a3d611a132592 100644
--- a/src/librustc_middle/ty/fold.rs
+++ b/src/librustc_middle/ty/fold.rs
@@ -142,6 +142,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
         self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
     }
 
+    /// Indicates whether this value still has parameters/placeholders/inference variables
+    /// which could be replaced later, in a way that would change the results of `impl`
+    /// specialization.
+    fn still_further_specializable(&self) -> bool {
+        self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
+    }
+
     /// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
     fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
         pub struct Visitor<F>(F);
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 43982439d47c8..2585de07a5b4f 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -524,101 +524,106 @@ bitflags! {
         // Does this have parameters? Used to determine whether substitution is
         // required.
         /// Does this have [Param]?
-        const HAS_TY_PARAM              = 1 << 0;
+        const HAS_TY_PARAM                = 1 << 0;
         /// Does this have [ReEarlyBound]?
-        const HAS_RE_PARAM              = 1 << 1;
+        const HAS_RE_PARAM                = 1 << 1;
         /// Does this have [ConstKind::Param]?
-        const HAS_CT_PARAM              = 1 << 2;
+        const HAS_CT_PARAM                = 1 << 2;
 
-        const NEEDS_SUBST               = TypeFlags::HAS_TY_PARAM.bits
-                                        | TypeFlags::HAS_RE_PARAM.bits
-                                        | TypeFlags::HAS_CT_PARAM.bits;
+        const NEEDS_SUBST                 = TypeFlags::HAS_TY_PARAM.bits
+                                          | TypeFlags::HAS_RE_PARAM.bits
+                                          | TypeFlags::HAS_CT_PARAM.bits;
 
         /// Does this have [Infer]?
-        const HAS_TY_INFER              = 1 << 3;
+        const HAS_TY_INFER                = 1 << 3;
         /// Does this have [ReVar]?
-        const HAS_RE_INFER              = 1 << 4;
+        const HAS_RE_INFER                = 1 << 4;
         /// Does this have [ConstKind::Infer]?
-        const HAS_CT_INFER              = 1 << 5;
+        const HAS_CT_INFER                = 1 << 5;
 
         /// Does this have inference variables? Used to determine whether
         /// inference is required.
-        const NEEDS_INFER               = TypeFlags::HAS_TY_INFER.bits
-                                        | TypeFlags::HAS_RE_INFER.bits
-                                        | TypeFlags::HAS_CT_INFER.bits;
+        const NEEDS_INFER                 = TypeFlags::HAS_TY_INFER.bits
+                                          | TypeFlags::HAS_RE_INFER.bits
+                                          | TypeFlags::HAS_CT_INFER.bits;
 
         /// Does this have [Placeholder]?
-        const HAS_TY_PLACEHOLDER        = 1 << 6;
+        const HAS_TY_PLACEHOLDER          = 1 << 6;
         /// Does this have [RePlaceholder]?
-        const HAS_RE_PLACEHOLDER        = 1 << 7;
+        const HAS_RE_PLACEHOLDER          = 1 << 7;
         /// Does this have [ConstKind::Placeholder]?
-        const HAS_CT_PLACEHOLDER        = 1 << 8;
+        const HAS_CT_PLACEHOLDER          = 1 << 8;
 
         /// `true` if there are "names" of regions and so forth
         /// that are local to a particular fn/inferctxt
-        const HAS_FREE_LOCAL_REGIONS    = 1 << 9;
+        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;
 
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES      = TypeFlags::HAS_TY_PARAM.bits
-                                        | TypeFlags::HAS_CT_PARAM.bits
-                                        | TypeFlags::HAS_TY_INFER.bits
-                                        | TypeFlags::HAS_CT_INFER.bits
-                                        | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
+                                          | TypeFlags::HAS_CT_PARAM.bits
+                                          | TypeFlags::HAS_TY_INFER.bits
+                                          | TypeFlags::HAS_CT_INFER.bits
+                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
 
         /// Does this have [Projection] or [UnnormalizedProjection]?
-        const HAS_TY_PROJECTION         = 1 << 10;
+        const HAS_TY_PROJECTION           = 1 << 10;
         /// Does this have [Opaque]?
-        const HAS_TY_OPAQUE             = 1 << 11;
+        const HAS_TY_OPAQUE               = 1 << 11;
         /// Does this have [ConstKind::Unevaluated]?
-        const HAS_CT_PROJECTION         = 1 << 12;
+        const HAS_CT_PROJECTION           = 1 << 12;
 
         /// Could this type be normalized further?
-        const HAS_PROJECTION            = TypeFlags::HAS_TY_PROJECTION.bits
-                                        | TypeFlags::HAS_TY_OPAQUE.bits
-                                        | TypeFlags::HAS_CT_PROJECTION.bits;
+        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
+                                          | TypeFlags::HAS_TY_OPAQUE.bits
+                                          | TypeFlags::HAS_CT_PROJECTION.bits;
 
         /// Present if the type belongs in a local type context.
         /// Set for placeholders and inference variables that are not "Fresh".
-        const KEEP_IN_LOCAL_TCX         = 1 << 13;
+        const KEEP_IN_LOCAL_TCX           = 1 << 13;
 
         /// Is an error type reachable?
-        const HAS_TY_ERR                = 1 << 14;
+        const HAS_TY_ERR                  = 1 << 14;
 
         /// Does this have any region that "appears free" in the type?
         /// Basically anything but [ReLateBound] and [ReErased].
-        const HAS_FREE_REGIONS          = 1 << 15;
+        const HAS_FREE_REGIONS            = 1 << 15;
 
         /// Does this have any [ReLateBound] regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND         = 1 << 16;
+        const HAS_RE_LATE_BOUND           = 1 << 16;
 
         /// Does this have any [ReErased] regions?
-        const HAS_RE_ERASED             = 1 << 17;
+        const HAS_RE_ERASED               = 1 << 17;
+
+        /// Does this value have parameters/placeholders/inference variables which could be
+        /// replaced later, in a way that would change the results of `impl` specialization?
+        const STILL_FURTHER_SPECIALIZABLE = 1 << 18;
 
         /// Flags representing the nominal content of a type,
         /// computed by FlagsComputation. If you add a new nominal
         /// flag, it should be added here too.
-        const NOMINAL_FLAGS             = TypeFlags::HAS_TY_PARAM.bits
-                                        | TypeFlags::HAS_RE_PARAM.bits
-                                        | TypeFlags::HAS_CT_PARAM.bits
-                                        | TypeFlags::HAS_TY_INFER.bits
-                                        | TypeFlags::HAS_RE_INFER.bits
-                                        | TypeFlags::HAS_CT_INFER.bits
-                                        | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_RE_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                        | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
-                                        | TypeFlags::HAS_TY_PROJECTION.bits
-                                        | TypeFlags::HAS_TY_OPAQUE.bits
-                                        | TypeFlags::HAS_CT_PROJECTION.bits
-                                        | TypeFlags::KEEP_IN_LOCAL_TCX.bits
-                                        | TypeFlags::HAS_TY_ERR.bits
-                                        | TypeFlags::HAS_FREE_REGIONS.bits
-                                        | TypeFlags::HAS_RE_LATE_BOUND.bits
-                                        | TypeFlags::HAS_RE_ERASED.bits;
+        const NOMINAL_FLAGS               = TypeFlags::HAS_TY_PARAM.bits
+                                          | TypeFlags::HAS_RE_PARAM.bits
+                                          | TypeFlags::HAS_CT_PARAM.bits
+                                          | TypeFlags::HAS_TY_INFER.bits
+                                          | TypeFlags::HAS_RE_INFER.bits
+                                          | TypeFlags::HAS_CT_INFER.bits
+                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_RE_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
+                                          | TypeFlags::HAS_TY_PROJECTION.bits
+                                          | TypeFlags::HAS_TY_OPAQUE.bits
+                                          | TypeFlags::HAS_CT_PROJECTION.bits
+                                          | TypeFlags::KEEP_IN_LOCAL_TCX.bits
+                                          | TypeFlags::HAS_TY_ERR.bits
+                                          | TypeFlags::HAS_FREE_REGIONS.bits
+                                          | TypeFlags::HAS_RE_LATE_BOUND.bits
+                                          | TypeFlags::HAS_RE_ERASED.bits
+                                          | TypeFlags::STILL_FURTHER_SPECIALIZABLE.bits;
     }
 }
 
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 57df50dc1a05d..e98ea097c901e 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -1623,16 +1623,19 @@ impl RegionKind {
                 flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
                 flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
+                flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
             }
             ty::RePlaceholder(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
+                flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
             }
             ty::ReEarlyBound(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PARAM;
+                flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
             }
             ty::ReFree { .. } | ty::ReScope { .. } => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index aae0d46756331..3057b79547dc0 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -1028,7 +1028,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         // assume `poly_trait_ref` isn't monomorphic, if it contains any.
                         let poly_trait_ref =
                             selcx.infcx().resolve_vars_if_possible(&poly_trait_ref);
-                        !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst()
+                        !poly_trait_ref.still_further_specializable()
                     } else {
                         debug!(
                             "assemble_candidates_from_impls: not eligible due to default: \
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
index 47c4b1c41cdbd..e845cc9a15869 100644
--- a/src/librustc_ty/instance.rs
+++ b/src/librustc_ty/instance.rs
@@ -127,7 +127,11 @@ fn resolve_associated_item<'tcx>(
                 // and the obligation is monomorphic, otherwise passes such as
                 // transmute checking and polymorphic MIR optimizations could
                 // get a result which isn't correct for all monomorphizations.
-                if param_env.reveal == Reveal::All { !trait_ref.needs_subst() } else { false }
+                if param_env.reveal == Reveal::All {
+                    !trait_ref.still_further_specializable()
+                } else {
+                    false
+                }
             };
 
             if !eligible {
diff --git a/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs
new file mode 100644
index 0000000000000..bdfc29a3d57ab
--- /dev/null
+++ b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs
@@ -0,0 +1,5 @@
+// This won't actually panic because of the error comment -- the `"` needs to be
+// the last byte in the file (including not having a trailing newline)
+// Prior to the fix you get the error: 'expected item, found `r" ...`'
+// because the string being unterminated wasn't properly detected.
+r" //~ unterminated raw string
diff --git a/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr
new file mode 100644
index 0000000000000..3a7e2a4b14afb
--- /dev/null
+++ b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr
@@ -0,0 +1,9 @@
+error[E0748]: unterminated raw string
+  --> $DIR/issue-70677-panic-on-unterminated-raw-str-at-eof.rs:5:1
+   |
+LL | r"
+   | ^ unterminated raw string
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0748`.
diff --git a/src/tools/cargo b/src/tools/cargo
index 8a0d4d9c9abc7..6e07d2dfb7fc8 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 8a0d4d9c9abc74fd670353094387d62028b40ae9
+Subproject commit 6e07d2dfb7fc87b1c9489de41da4dafa239daf03