about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-11-18 20:23:26 +0000
committerbors <bors@rust-lang.org>2021-11-18 20:23:26 +0000
commitcc946fcd326f7d85d4af096efdc73538622568e9 (patch)
treea23aec459469e926ba5133134d0f9864c1f9bb07
parentb6f580acc0ce233d5c4d1f9680d354fded88b824 (diff)
parent08c1639fd933d56d1b5e386eea887f5bbf3e93f1 (diff)
downloadrust-cc946fcd326f7d85d4af096efdc73538622568e9.tar.gz
rust-cc946fcd326f7d85d4af096efdc73538622568e9.zip
Auto merge of #91019 - JohnTitor:rollup-q95ra7r, r=JohnTitor
Rollup of 8 pull requests

Successful merges:

 - #90386 (Add `-Zassert-incr-state` to assert state of incremental cache)
 - #90438 (Clean up mess for --show-coverage documentation)
 - #90480 (Mention `Vec::remove` in `Vec::swap_remove`'s docs)
 - #90607 (Make slice->str conversion and related functions `const`)
 - #90750 (rustdoc: Replace where-bounded Clean impl with simple function)
 - #90895 (require full validity when determining the discriminant of a value)
 - #90989 (Avoid suggesting literal formatting that turns into member access)
 - #91002 (rustc: Remove `#[rustc_synthetic]`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs6
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir/src/hir.rs12
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs24
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs21
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs20
-rw-r--r--compiler/rustc_session/src/config.rs32
-rw-r--r--compiler/rustc_session/src/options.rs5
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs7
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs11
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs14
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs8
-rw-r--r--compiler/rustc_typeck/src/collect.rs6
-rw-r--r--library/alloc/src/vec/mod.rs5
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/str.rs64
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/str/converts.rs31
-rw-r--r--library/core/src/str/error.rs12
-rw-r--r--library/core/src/str/validations.rs19
-rw-r--r--src/doc/rustdoc/src/unstable-features.md73
-rw-r--r--src/librustdoc/clean/inline.rs1
-rw-r--r--src/librustdoc/clean/mod.rs56
-rw-r--r--src/librustdoc/clean/types.rs19
-rw-r--r--src/test/incremental/link_order/auxiliary/my_lib.rs4
-rw-r--r--src/test/incremental/struct_change_field_name.rs1
-rw-r--r--src/test/ui/suggestions/issue-90974.rs3
-rw-r--r--src/test/ui/suggestions/issue-90974.stderr14
-rw-r--r--src/test/ui/synthetic-param.rs28
-rw-r--r--src/test/ui/synthetic-param.stderr30
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs8
36 files changed, 310 insertions, 251 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 79464a75172..fef6e87bfdb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1338,10 +1338,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             pure_wrt_drop: false,
                             bounds: hir_bounds,
                             span: self.lower_span(span),
-                            kind: hir::GenericParamKind::Type {
-                                default: None,
-                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                            },
+                            kind: hir::GenericParamKind::Type { default: None, synthetic: true },
                         });
 
                         hir::TyKind::Path(hir::QPath::Resolved(
@@ -1954,12 +1951,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
                     }),
-                    synthetic: param
-                        .attrs
-                        .iter()
-                        .filter(|attr| attr.has_name(sym::rustc_synthetic))
-                        .map(|_| hir::SyntheticTyParamKind::FromAttr)
-                        .next(),
+                    synthetic: false,
                 };
 
                 (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 698742fe98c..5e7bbc01132 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -265,6 +265,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::discriminant_value => {
                 let place = self.deref_operand(&args[0])?;
+                if M::enforce_validity(self) {
+                    // This is 'using' the value, so make sure the validity invariant is satisfied.
+                    // (Also see https://github.com/rust-lang/rust/pull/89764.)
+                    self.validate_operand(&place.into())?;
+                }
+
                 let discr_val = self.read_discriminant(&place.into())?.0;
                 self.write_scalar(discr_val, dest)?;
             }
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index e6037d561de..2759a7d9d26 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -304,6 +304,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             Discriminant(place) => {
                 let op = self.eval_place_to_op(place, None)?;
+                if M::enforce_validity(self) {
+                    // This is 'using' the value, so make sure the validity invariant is satisfied.
+                    // (Also see https://github.com/rust-lang/rust/pull/89764.)
+                    self.validate_operand(&op)?;
+                }
+
                 let discr_val = self.read_discriminant(&op)?.0;
                 self.write_scalar(discr_val, &dest)?;
             }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 7212bbf38c7..74a637fde33 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -601,7 +601,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         TEST, rustc_expected_cgu_reuse, Normal,
         template!(List: r#"cfg = "...", module = "...", kind = "...""#),
     ),
-    rustc_attr!(TEST, rustc_synthetic, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e00c5789fe9..a4db57bfc11 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -504,7 +504,7 @@ pub enum GenericParamKind<'hir> {
     },
     Type {
         default: Option<&'hir Ty<'hir>>,
-        synthetic: Option<SyntheticTyParamKind>,
+        synthetic: bool,
     },
     Const {
         ty: &'hir Ty<'hir>,
@@ -577,16 +577,6 @@ impl Generics<'hir> {
     }
 }
 
-/// Synthetic type parameters are converted to another form during lowering; this allows
-/// us to track the original form they had, and is useful for error messages.
-#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
-#[derive(HashStable_Generic)]
-pub enum SyntheticTyParamKind {
-    ImplTrait,
-    // Created by the `#[rustc_synthetic]` attribute.
-    FromAttr,
-}
-
 /// A where-clause in a definition.
 #[derive(Debug, HashStable_Generic)]
 pub struct WhereClause<'hir> {
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 5f5e83774da..9c6e2aeb50a 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -6,6 +6,7 @@ use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::OnDiskCache;
 use rustc_serialize::opaque::Decoder;
 use rustc_serialize::Decodable;
+use rustc_session::config::IncrementalStateAssertion;
 use rustc_session::Session;
 use std::path::Path;
 
@@ -16,6 +17,7 @@ use super::work_product;
 
 type WorkProductMap = FxHashMap<WorkProductId, WorkProduct>;
 
+#[derive(Debug)]
 pub enum LoadResult<T> {
     Ok { data: T },
     DataOutOfDate,
@@ -24,6 +26,26 @@ pub enum LoadResult<T> {
 
 impl<T: Default> LoadResult<T> {
     pub fn open(self, sess: &Session) -> T {
+        // Check for errors when using `-Zassert-incremental-state`
+        match (sess.opts.assert_incr_state, &self) {
+            (Some(IncrementalStateAssertion::NotLoaded), LoadResult::Ok { .. }) => {
+                sess.fatal(
+                    "We asserted that the incremental cache should not be loaded, \
+                         but it was loaded.",
+                );
+            }
+            (
+                Some(IncrementalStateAssertion::Loaded),
+                LoadResult::Error { .. } | LoadResult::DataOutOfDate,
+            ) => {
+                sess.fatal(
+                    "We asserted that an existing incremental cache directory should \
+                         be successfully loaded, but it was not.",
+                );
+            }
+            _ => {}
+        };
+
         match self {
             LoadResult::Error { message } => {
                 sess.warn(&message);
@@ -33,7 +55,7 @@ impl<T: Default> LoadResult<T> {
                 if let Err(err) = delete_all_session_dir_contents(sess) {
                     sess.err(&format!(
                         "Failed to delete invalidated or incompatible \
-                                      incremental compilation session directory contents `{}`: {}.",
+                         incremental compilation session directory contents `{}`: {}.",
                         dep_graph_path(sess).display(),
                         err
                     ));
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 6b666d7c292..6b5c79a2d5d 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -636,6 +636,7 @@ fn test_debugging_options_tracking_hash() {
 
     // Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
     // This list is in alphabetical order.
+    untracked!(assert_incr_state, Some(String::from("loaded")));
     untracked!(ast_json, true);
     untracked!(ast_json_noexpand, true);
     untracked!(borrowck, String::from("other"));
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 0f89581ae66..f53f1871508 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -3,7 +3,6 @@ use crate::ty;
 use crate::ty::subst::{Subst, SubstsRef};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -13,14 +12,8 @@ use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predi
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum GenericParamDefKind {
     Lifetime,
-    Type {
-        has_default: bool,
-        object_lifetime_default: ObjectLifetimeDefault,
-        synthetic: Option<hir::SyntheticTyParamKind>,
-    },
-    Const {
-        has_default: bool,
-    },
+    Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool },
+    Const { has_default: bool },
 }
 
 impl GenericParamDefKind {
@@ -202,15 +195,7 @@ impl<'tcx> Generics {
     /// Returns `true` if `params` has `impl Trait`.
     pub fn has_impl_trait(&'tcx self) -> bool {
         self.params.iter().any(|param| {
-            matches!(
-                param.kind,
-                ty::GenericParamDefKind::Type {
-                    synthetic: Some(
-                        hir::SyntheticTyParamKind::ImplTrait | hir::SyntheticTyParamKind::FromAttr,
-                    ),
-                    ..
-                }
-            )
+            matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
         })
     }
 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 4acbb11b13f..d506931b516 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1810,12 +1810,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     let (span, sugg) = if let Some(param) = generics.params.iter().find(|p| {
                         !matches!(
                             p.kind,
-                            hir::GenericParamKind::Type {
-                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                                ..
-                            } | hir::GenericParamKind::Lifetime {
-                                kind: hir::LifetimeParamKind::Elided,
-                            }
+                            hir::GenericParamKind::Type { synthetic: true, .. }
+                                | hir::GenericParamKind::Lifetime {
+                                    kind: hir::LifetimeParamKind::Elided,
+                                }
                         )
                     }) {
                         (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref))
@@ -2042,12 +2040,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         if let Some(param) = generics.params.iter().find(|p| {
                             !matches!(
                                 p.kind,
-                                hir::GenericParamKind::Type {
-                                    synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                                    ..
-                                } | hir::GenericParamKind::Lifetime {
-                                    kind: hir::LifetimeParamKind::Elided
-                                }
+                                hir::GenericParamKind::Type { synthetic: true, .. }
+                                    | hir::GenericParamKind::Lifetime {
+                                        kind: hir::LifetimeParamKind::Elided
+                                    }
                             )
                         }) {
                             (param.span.shrink_to_lo(), "'a, ".to_string())
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 5e6bbe03918..3f0a6b0e2f6 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -165,6 +165,18 @@ pub enum LinkerPluginLto {
     Disabled,
 }
 
+/// Used with `-Z assert-incr-state`.
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum IncrementalStateAssertion {
+    /// Found and loaded an existing session directory.
+    ///
+    /// Note that this says nothing about whether any particular query
+    /// will be found to be red or green.
+    Loaded,
+    /// Did not load an existing session directory.
+    NotLoaded,
+}
+
 impl LinkerPluginLto {
     pub fn enabled(&self) -> bool {
         match *self {
@@ -704,6 +716,7 @@ pub fn host_triple() -> &'static str {
 impl Default for Options {
     fn default() -> Options {
         Options {
+            assert_incr_state: None,
             crate_types: Vec::new(),
             optimize: OptLevel::No,
             debuginfo: DebugInfo::None,
@@ -1626,6 +1639,21 @@ fn select_debuginfo(
     }
 }
 
+crate fn parse_assert_incr_state(
+    opt_assertion: &Option<String>,
+    error_format: ErrorOutputType,
+) -> Option<IncrementalStateAssertion> {
+    match opt_assertion {
+        Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
+        Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
+        Some(s) => early_error(
+            error_format,
+            &format!("unexpected incremental state assertion value: {}", s),
+        ),
+        None => None,
+    }
+}
+
 fn parse_native_lib_kind(
     matches: &getopts::Matches,
     kind: &str,
@@ -2015,6 +2043,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let incremental = cg.incremental.as_ref().map(PathBuf::from);
 
+    let assert_incr_state =
+        parse_assert_incr_state(&debugging_opts.assert_incr_state, error_format);
+
     if debugging_opts.profile && incremental.is_some() {
         early_error(
             error_format,
@@ -2179,6 +2210,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     };
 
     Options {
+        assert_incr_state,
         crate_types,
         optimize: opt_level,
         debuginfo,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 3f279a045f1..2c217e40aba 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -4,7 +4,6 @@ use crate::early_error;
 use crate::lint;
 use crate::search_paths::SearchPath;
 use crate::utils::NativeLib;
-
 use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
 use rustc_target::spec::{RelocModel, RelroLevel, SplitDebuginfo, TargetTriple, TlsModel};
 
@@ -150,6 +149,7 @@ top_level_options!(
         /// If `Some`, enable incremental compilation, using the given
         /// directory to store intermediate results.
         incremental: Option<PathBuf> [UNTRACKED],
+        assert_incr_state: Option<IncrementalStateAssertion> [UNTRACKED],
 
         debugging_opts: DebuggingOptions [SUBSTRUCT],
         prints: Vec<PrintRequest> [UNTRACKED],
@@ -1046,6 +1046,9 @@ options! {
         "make cfg(version) treat the current version as incomplete (default: no)"),
     asm_comments: bool = (false, parse_bool, [TRACKED],
         "generate comments into the assembly (may change behavior) (default: no)"),
+    assert_incr_state: Option<String> = (None, parse_opt_string, [UNTRACKED],
+        "assert that the incremental cache is in given state: \
+         either `loaded` or `not-loaded`."),
     ast_json: bool = (false, parse_bool, [UNTRACKED],
         "print the AST as JSON and halt (default: no)"),
     ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 99fa9f00094..9992b1f31fe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1148,7 +1148,6 @@ symbols! {
         rustc_std_internal_symbol,
         rustc_strict_coherence,
         rustc_symbol_name,
-        rustc_synthetic,
         rustc_test_marker,
         rustc_then_this_would_need,
         rustc_trivial_field_reads,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 0bf01afb575..1ff31ff04a2 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -290,9 +290,10 @@ fn suggest_restriction(
     } else {
         // Trivial case: `T` needs an extra bound: `T: Bound`.
         let (sp, suggestion) = match (
-            generics.params.iter().find(|p| {
-                !matches!(p.kind, hir::GenericParamKind::Type { synthetic: Some(_), .. })
-            }),
+            generics
+                .params
+                .iter()
+                .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
             super_traits,
         ) {
             (_, None) => predicate_constraint(
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 2f187997b55..e8bd038fed7 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -464,16 +464,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .params
                 .iter()
                 .filter(|param| {
-                    matches!(
-                        param.kind,
-                        ty::GenericParamDefKind::Type {
-                            synthetic: Some(
-                                hir::SyntheticTyParamKind::ImplTrait
-                                    | hir::SyntheticTyParamKind::FromAttr
-                            ),
-                            ..
-                        }
-                    )
+                    matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
                 })
                 .count()
         } else {
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index cbfd8747ecf..ef7c7096015 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -607,10 +607,7 @@ fn compare_number_of_generics<'tcx>(
                         .params
                         .iter()
                         .filter_map(|p| match p.kind {
-                            GenericParamKind::Type {
-                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                                ..
-                            } => Some(p.span),
+                            GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
                             _ => None,
                         })
                         .collect();
@@ -627,10 +624,7 @@ fn compare_number_of_generics<'tcx>(
                 .params
                 .iter()
                 .filter_map(|p| match p.kind {
-                    GenericParamKind::Type {
-                        synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
-                        ..
-                    } => Some(p.span),
+                    GenericParamKind::Type { synthetic: true, .. } => Some(p.span),
                     _ => None,
                 })
                 .collect();
@@ -823,7 +817,7 @@ fn compare_synthetic_generics<'tcx>(
             match (impl_synthetic, trait_synthetic) {
                 // The case where the impl method uses `impl Trait` but the trait method uses
                 // explicit generics
-                (Some(hir::SyntheticTyParamKind::ImplTrait), None) => {
+                (true, false) => {
                     err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
                     (|| {
                         // try taking the name from the trait impl
@@ -864,7 +858,7 @@ fn compare_synthetic_generics<'tcx>(
                 }
                 // The case where the trait method uses `impl Trait`, but the impl method uses
                 // explicit generics.
-                (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
+                (false, true) => {
                     err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
                     (|| {
                         let impl_m = impl_m.def_id.as_local()?;
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 5c79a067e9f..c9fa0fd72fc 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -2025,7 +2025,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) {
         let generics = self.tcx.generics_of(self.body_id.owner.to_def_id());
         let generic_param = generics.type_param(&param, self.tcx);
-        if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind {
+        if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param.kind {
             return;
         }
         let param_def_id = generic_param.def_id;
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 661ced952c7..6411c062fea 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -317,6 +317,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     .span_to_snippet(lit.span)
                                     .unwrap_or_else(|_| "<numeric literal>".to_owned());
 
+                                // If this is a floating point literal that ends with '.',
+                                // get rid of it to stop this from becoming a member access.
+                                let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
+
                                 err.span_suggestion(
                                     lit.span,
                                     &format!(
@@ -324,7 +328,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                          like `{}`",
                                         concrete_type
                                     ),
-                                    format!("{}_{}", snippet, concrete_type),
+                                    format!("{snippet}_{concrete_type}"),
                                     Applicability::MaybeIncorrect,
                                 );
                             }
@@ -1490,7 +1494,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Node::GenericParam(param) => {
                             let mut impl_trait = false;
                             let has_bounds =
-                                if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
+                                if let hir::GenericParamKind::Type { synthetic: true, .. } =
                                     &param.kind
                                 {
                                     // We've found `fn foo(x: impl Trait)` instead of
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 2f427305782..209690ec5fc 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1543,7 +1543,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                         kind: ty::GenericParamDefKind::Type {
                             has_default: false,
                             object_lifetime_default: rl::Set1::Empty,
-                            synthetic: None,
+                            synthetic: false,
                         },
                     });
 
@@ -1673,7 +1673,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             kind: ty::GenericParamDefKind::Type {
                 has_default: false,
                 object_lifetime_default: rl::Set1::Empty,
-                synthetic: None,
+                synthetic: false,
             },
         }));
     }
@@ -1690,7 +1690,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 kind: ty::GenericParamDefKind::Type {
                     has_default: false,
                     object_lifetime_default: rl::Set1::Empty,
-                    synthetic: None,
+                    synthetic: false,
                 },
             });
         }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 4989244b50e..85759917765 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1272,6 +1272,9 @@ impl<T, A: Allocator> Vec<T, A> {
     /// The removed element is replaced by the last element of the vector.
     ///
     /// This does not preserve ordering, but is *O*(1).
+    /// If you need to preserve the element order, use [`remove`] instead.
+    ///
+    /// [`remove`]: Vec::remove
     ///
     /// # Panics
     ///
@@ -1368,7 +1371,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// shifting all elements after it to the left.
     ///
     /// Note: Because this shifts over the remaining elements, it has a
-    /// worst-case performance of O(n). If you don't need the order of elements
+    /// worst-case performance of *O*(*n*). If you don't need the order of elements
     /// to be preserved, use [`swap_remove`] instead.
     ///
     /// [`swap_remove`]: Vec::swap_remove
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 8c57c804ad2..68e48348b07 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -25,6 +25,7 @@
 #![feature(const_btree_new)]
 #![feature(const_default_impls)]
 #![feature(const_trait_impl)]
+#![feature(const_str_from_utf8)]
 
 use std::collections::hash_map::DefaultHasher;
 use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index dc7d0bff9a4..1b741f174fb 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1,3 +1,4 @@
+use std::assert_matches::assert_matches;
 use std::borrow::Cow;
 use std::cmp::Ordering::{Equal, Greater, Less};
 use std::str::{from_utf8, from_utf8_unchecked};
@@ -884,6 +885,33 @@ fn test_is_utf8() {
 }
 
 #[test]
+fn test_const_is_utf8() {
+    const _: () = {
+        // deny overlong encodings
+        assert!(from_utf8(&[0xc0, 0x80]).is_err());
+        assert!(from_utf8(&[0xc0, 0xae]).is_err());
+        assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
+        assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
+        assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
+        assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
+        assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
+
+        // deny surrogates
+        assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
+        assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
+
+        assert!(from_utf8(&[0xC2, 0x80]).is_ok());
+        assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
+        assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
+        assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
+        assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
+        assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
+        assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
+        assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
+    };
+}
+
+#[test]
 fn from_utf8_mostly_ascii() {
     // deny invalid bytes embedded in long stretches of ascii
     for i in 32..64 {
@@ -896,12 +924,42 @@ fn from_utf8_mostly_ascii() {
 }
 
 #[test]
+fn const_from_utf8_mostly_ascii() {
+    const _: () = {
+        // deny invalid bytes embedded in long stretches of ascii
+        let mut i = 32;
+        while i < 64 {
+            let mut data = [0; 128];
+            data[i] = 0xC0;
+            assert!(from_utf8(&data).is_err());
+            data[i] = 0xC2;
+            assert!(from_utf8(&data).is_err());
+
+            i = i + 1;
+        }
+    };
+}
+
+#[test]
 fn from_utf8_error() {
     macro_rules! test {
-        ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
+        ($input: expr, $expected_valid_up_to:pat, $expected_error_len:pat) => {
             let error = from_utf8($input).unwrap_err();
-            assert_eq!(error.valid_up_to(), $expected_valid_up_to);
-            assert_eq!(error.error_len(), $expected_error_len);
+            assert_matches!(error.valid_up_to(), $expected_valid_up_to);
+            assert_matches!(error.error_len(), $expected_error_len);
+
+            const _: () = {
+                match from_utf8($input) {
+                    Err(error) => {
+                        let valid_up_to = error.valid_up_to();
+                        let error_len = error.error_len();
+
+                        assert!(matches!(valid_up_to, $expected_valid_up_to));
+                        assert!(matches!(error_len, $expected_error_len));
+                    }
+                    Ok(_) => unreachable!(),
+                }
+            };
         };
     }
     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e4a566f5895..3b0872378c6 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -97,6 +97,7 @@
 #![allow(explicit_outlives_requirements)]
 //
 // Library features for const fns:
+#![feature(const_align_offset)]
 #![feature(const_align_of_val)]
 #![feature(const_alloc_layout)]
 #![feature(const_arguments_as_str)]
@@ -130,6 +131,7 @@
 #![feature(const_size_of_val)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_slice_ptr_len)]
+#![feature(const_str_from_utf8_unchecked_mut)]
 #![feature(const_swap)]
 #![feature(const_trait_impl)]
 #![feature(const_type_id)]
@@ -138,6 +140,7 @@
 #![feature(duration_consts_2)]
 #![feature(ptr_metadata)]
 #![feature(slice_ptr_get)]
+#![feature(str_internals)]
 #![feature(variant_count)]
 #![feature(const_array_from_ref)]
 #![feature(const_slice_from_ref)]
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index ed9f49f1596..ef26cbfb640 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -82,10 +82,16 @@ use super::Utf8Error;
 /// assert_eq!("💖", sparkle_heart);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
-    run_utf8_validation(v)?;
-    // SAFETY: Just ran validation.
-    Ok(unsafe { from_utf8_unchecked(v) })
+#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
+    // This should use `?` again, once it's `const`
+    match run_utf8_validation(v) {
+        Ok(_) => {
+            // SAFETY: validation succeeded.
+            Ok(unsafe { from_utf8_unchecked(v) })
+        }
+        Err(err) => Err(err),
+    }
 }
 
 /// Converts a mutable slice of bytes to a mutable string slice.
@@ -119,10 +125,16 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 /// See the docs for [`Utf8Error`] for more details on the kinds of
 /// errors that can be returned.
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
-pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
-    run_utf8_validation(v)?;
-    // SAFETY: Just ran validation.
-    Ok(unsafe { from_utf8_unchecked_mut(v) })
+#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
+    // This should use `?` again, once it's `const`
+    match run_utf8_validation(v) {
+        Ok(_) => {
+            // SAFETY: validation succeeded.
+            Ok(unsafe { from_utf8_unchecked_mut(v) })
+        }
+        Err(err) => Err(err),
+    }
 }
 
 /// Converts a slice of bytes to a string slice without checking
@@ -184,7 +196,8 @@ pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 #[inline]
 #[must_use]
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
-pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
+#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked_mut", issue = "91005")]
+pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
     // SAFETY: the caller must guarantee that the bytes `v`
     // are valid UTF-8, thus the cast to `*mut str` is safe.
     // Also, the pointer dereference is safe because that pointer
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index b6460d72fef..a127dd57eee 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -72,9 +72,10 @@ impl Utf8Error {
     /// assert_eq!(1, error.valid_up_to());
     /// ```
     #[stable(feature = "utf8_error", since = "1.5.0")]
+    #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
     #[must_use]
     #[inline]
-    pub fn valid_up_to(&self) -> usize {
+    pub const fn valid_up_to(&self) -> usize {
         self.valid_up_to
     }
 
@@ -94,10 +95,15 @@ impl Utf8Error {
     ///
     /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
     #[stable(feature = "utf8_error_error_len", since = "1.20.0")]
+    #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
     #[must_use]
     #[inline]
-    pub fn error_len(&self) -> Option<usize> {
-        self.error_len.map(|len| len as usize)
+    pub const fn error_len(&self) -> Option<usize> {
+        // This should become `map` again, once it's `const`
+        match self.error_len {
+            Some(len) => Some(len as usize),
+            None => None,
+        }
     }
 }
 
diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs
index 9a1cf905e3b..e362d5c05c1 100644
--- a/library/core/src/str/validations.rs
+++ b/library/core/src/str/validations.rs
@@ -8,25 +8,25 @@ use super::Utf8Error;
 /// The first byte is special, only want bottom 5 bits for width 2, 4 bits
 /// for width 3, and 3 bits for width 4.
 #[inline]
-fn utf8_first_byte(byte: u8, width: u32) -> u32 {
+const fn utf8_first_byte(byte: u8, width: u32) -> u32 {
     (byte & (0x7F >> width)) as u32
 }
 
 /// Returns the value of `ch` updated with continuation byte `byte`.
 #[inline]
-fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 {
+const fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 {
     (ch << 6) | (byte & CONT_MASK) as u32
 }
 
 /// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the
 /// bits `10`).
 #[inline]
-pub(super) fn utf8_is_cont_byte(byte: u8) -> bool {
+pub(super) const fn utf8_is_cont_byte(byte: u8) -> bool {
     (byte as i8) < -64
 }
 
 #[inline]
-fn unwrap_or_0(opt: Option<&u8>) -> u8 {
+const fn unwrap_or_0(opt: Option<&u8>) -> u8 {
     match opt {
         Some(&byte) => byte,
         None => 0,
@@ -105,14 +105,15 @@ const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
 
 /// Returns `true` if any byte in the word `x` is nonascii (>= 128).
 #[inline]
-fn contains_nonascii(x: usize) -> bool {
+const fn contains_nonascii(x: usize) -> bool {
     (x & NONASCII_MASK) != 0
 }
 
 /// Walks through `v` checking that it's a valid UTF-8 sequence,
 /// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`.
 #[inline(always)]
-pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
+#[rustc_const_unstable(feature = "str_internals", issue = "none")]
+pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
     let mut index = 0;
     let len = v.len();
 
@@ -142,7 +143,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
 
         let first = v[index];
         if first >= 128 {
-            let w = UTF8_CHAR_WIDTH[first as usize];
+            let w = utf8_char_width(first);
             // 2-byte encoding is for codepoints  \u{0080} to  \u{07ff}
             //        first  C2 80        last DF BF
             // 3-byte encoding is for codepoints  \u{0800} to  \u{ffff}
@@ -230,7 +231,7 @@ pub(super) fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
 }
 
 // https://tools.ietf.org/html/rfc3629
-static UTF8_CHAR_WIDTH: [u8; 256] = [
+const UTF8_CHAR_WIDTH: &[u8; 256] = &[
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     1, // 0x1F
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -253,7 +254,7 @@ static UTF8_CHAR_WIDTH: [u8; 256] = [
 #[unstable(feature = "str_internals", issue = "none")]
 #[must_use]
 #[inline]
-pub fn utf8_char_width(b: u8) -> usize {
+pub const fn utf8_char_width(b: u8) -> usize {
     UTF8_CHAR_WIDTH[b as usize] as usize
 }
 
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index b3b6422afab..16532215c6f 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -348,6 +348,18 @@ Using this flag looks like this:
 $ rustdoc src/lib.rs -Z unstable-options --show-coverage
 ```
 
+It generates something like this:
+
+```bash
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| lib.rs                              |          4 |     100.0% |          1 |      25.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          4 |     100.0% |          1 |      25.0% |
++-------------------------------------+------------+------------+------------+------------+
+```
+
 If you want to determine how many items in your crate are documented, pass this flag to rustdoc.
 When it receives this flag, it will count the public items in your crate that have documentation,
 and print out the counts and a percentage instead of generating docs.
@@ -367,17 +379,25 @@ Some methodology notes about what rustdoc counts in this metric:
 Public items that are not documented can be seen with the built-in `missing_docs` lint. Private
 items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint.
 
-### `-w`/`--output-format`: output format
+Calculating code examples follows these rules:
 
-When using
-[`--show-coverage`](https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--show-coverage-get-statistics-about-code-documentation-coverage),
-passing `--output-format json` will display the coverage information in JSON format. For example,
-here is the JSON for a file with one documented item and one undocumented item:
+1. These items aren't accounted by default:
+  * struct/union field
+  * enum variant
+  * constant
+  * static
+  * typedef
+2. If one of the previously listed items has a code example, then it'll be counted.
+
+#### JSON output
+
+When using `--output-format json` with this option, it will display the coverage information in
+JSON format. For example, here is the JSON for a file with one documented item and one
+undocumented item:
 
 ```rust
 /// This item has documentation
 pub fn foo() {}
-
 pub fn no_documentation() {}
 ```
 
@@ -387,10 +407,16 @@ pub fn no_documentation() {}
 
 Note that the third item is the crate root, which in this case is undocumented.
 
-When not using `--show-coverage`, `--output-format json` emits documentation in the experimental
+### `-w`/`--output-format`: output format
+
+`--output-format json` emits documentation in the experimental
 [JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect,
 and is also accepted on stable toolchains.
 
+It can also be used with `--show-coverage`. Take a look at its
+[documentation](#--show-coverage-get-statistics-about-code-documentation-coverage) for more
+information.
+
 ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests
 
 Using this flag looks like this:
@@ -441,39 +467,6 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind
 
 Another use case would be to run a test inside an emulator, or through a Virtual Machine.
 
-### `--show-coverage`: get statistics about code documentation coverage
-
-This option allows you to get a nice overview over your code documentation coverage, including both
-doc-comments and code examples in the doc-comments. Example:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --show-coverage
-+-------------------------------------+------------+------------+------------+------------+
-| File                                | Documented | Percentage |   Examples | Percentage |
-+-------------------------------------+------------+------------+------------+------------+
-| lib.rs                              |          4 |     100.0% |          1 |      25.0% |
-+-------------------------------------+------------+------------+------------+------------+
-| Total                               |          4 |     100.0% |          1 |      25.0% |
-+-------------------------------------+------------+------------+------------+------------+
-```
-
-You can also use this option with the `--output-format` one:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --show-coverage --output-format json
-{"lib.rs":{"total":4,"with_docs":4,"total_examples":4,"with_examples":1}}
-```
-
-Calculating code examples follows these rules:
-
-1. These items aren't accounted by default:
-  * struct/union field
-  * enum variant
-  * constant
-  * static
-  * typedef
-2. If one of the previously listed items has a code example, then it'll be counted.
-
 ### `--with-examples`: include examples of uses of items as documentation
 
 This option, combined with `--scrape-examples-target-crate` and
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4a8a3160379..8f21fc5ba7f 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -229,6 +229,7 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi
     let asyncness = cx.tcx.asyncness(did);
     let predicates = cx.tcx.predicates_of(did);
     let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
+        // NOTE: generics need to be cleaned before the decl!
         ((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(cx))
     });
     clean::Function {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 70401065689..959dc545337 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -109,7 +109,10 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
                 };
 
                 GenericBound::TraitBound(
-                    PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] },
+                    PolyTrait {
+                        trait_: (trait_ref, &bindings[..]).clean(cx),
+                        generic_params: vec![],
+                    },
                     hir::TraitBoundModifier::None,
                 )
             }
@@ -456,9 +459,7 @@ impl Clean<Generics> for hir::Generics<'_> {
         // scans them first.
         fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
             match param.kind {
-                hir::GenericParamKind::Type { synthetic, .. } => {
-                    synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
-                }
+                hir::GenericParamKind::Type { synthetic, .. } => synthetic,
                 _ => false,
             }
         }
@@ -557,7 +558,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
                         assert_eq!(param.index, 0);
                         return None;
                     }
-                    if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
+                    if synthetic {
                         impl_trait.insert(param.index.into(), vec![]);
                         return None;
                     }
@@ -761,8 +762,13 @@ fn clean_fn_or_proc_macro(
 
 impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
     fn clean(&self, cx: &mut DocContext<'_>) -> Function {
-        let (generics, decl) =
-            enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
+        let (generics, decl) = enter_impl_trait(cx, |cx| {
+            // NOTE: generics must be cleaned before args
+            let generics = self.1.clean(cx);
+            let args = (self.0.decl.inputs, self.2).clean(cx);
+            let decl = clean_fn_decl_with_args(cx, self.0.decl, args);
+            (generics, decl)
+        });
         Function { decl, generics, header: self.0.header }
     }
 }
@@ -804,17 +810,12 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
     }
 }
 
-impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
-where
-    (&'a [hir::Ty<'a>], A): Clean<Arguments>,
-{
-    fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
-        FnDecl {
-            inputs: (self.0.inputs, self.1).clean(cx),
-            output: self.0.output.clean(cx),
-            c_variadic: self.0.c_variadic,
-        }
-    }
+fn clean_fn_decl_with_args(
+    cx: &mut DocContext<'_>,
+    decl: &hir::FnDecl<'_>,
+    args: Arguments,
+) -> FnDecl {
+    FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
 }
 
 impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
@@ -894,7 +895,11 @@ impl Clean<Item> for hir::TraitItem<'_> {
                 }
                 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
                     let (generics, decl) = enter_impl_trait(cx, |cx| {
-                        (self.generics.clean(cx), (sig.decl, names).clean(cx))
+                        // NOTE: generics must be cleaned before args
+                        let generics = self.generics.clean(cx);
+                        let args = (sig.decl.inputs, names).clean(cx);
+                        let decl = clean_fn_decl_with_args(cx, sig.decl, args);
+                        (generics, decl)
                     });
                     let mut t = Function { header: sig.header, decl, generics };
                     if t.header.constness == hir::Constness::Const
@@ -1727,8 +1732,10 @@ impl Clean<PathSegment> for hir::PathSegment<'_> {
 impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
         let (generic_params, decl) = enter_impl_trait(cx, |cx| {
+            // NOTE: generics must be cleaned before args
             let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
-            let decl = (self.decl, self.param_names).clean(cx);
+            let args = (self.decl.inputs, self.param_names).clean(cx);
+            let decl = clean_fn_decl_with_args(cx, self.decl, args);
             (generic_params, decl)
         });
         BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
@@ -2029,8 +2036,13 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
             let kind = match item.kind {
                 hir::ForeignItemKind::Fn(decl, names, ref generics) => {
                     let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
-                    let (generics, decl) =
-                        enter_impl_trait(cx, |cx| (generics.clean(cx), (decl, names).clean(cx)));
+                    let (generics, decl) = enter_impl_trait(cx, |cx| {
+                        // NOTE: generics must be cleaned before args
+                        let generics = generics.clean(cx);
+                        let args = (decl.inputs, names).clean(cx);
+                        let decl = clean_fn_decl_with_args(cx, decl, args);
+                        (generics, decl)
+                    });
                     ForeignFunctionItem(Function {
                         decl,
                         generics,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2dba52afcd9..fb08ced205d 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1238,20 +1238,9 @@ impl WherePredicate {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericParamDefKind {
-    Lifetime {
-        outlives: Vec<Lifetime>,
-    },
-    Type {
-        did: DefId,
-        bounds: Vec<GenericBound>,
-        default: Option<Box<Type>>,
-        synthetic: Option<hir::SyntheticTyParamKind>,
-    },
-    Const {
-        did: DefId,
-        ty: Box<Type>,
-        default: Option<Box<String>>,
-    },
+    Lifetime { outlives: Vec<Lifetime> },
+    Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
+    Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
 }
 
 impl GenericParamDefKind {
@@ -1285,7 +1274,7 @@ impl GenericParamDef {
     crate fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
             GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
-            GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
+            GenericParamDefKind::Type { synthetic, .. } => synthetic,
         }
     }
 
diff --git a/src/test/incremental/link_order/auxiliary/my_lib.rs b/src/test/incremental/link_order/auxiliary/my_lib.rs
index 57cde5f7c6e..1e7d823050c 100644
--- a/src/test/incremental/link_order/auxiliary/my_lib.rs
+++ b/src/test/incremental/link_order/auxiliary/my_lib.rs
@@ -1,3 +1,3 @@
 // no-prefer-dynamic
-//[cfail1] compile-flags: -lbar -lfoo --crate-type lib
-//[cfail2] compile-flags: -lfoo -lbar --crate-type lib
+//[cfail1] compile-flags: -lbar -lfoo --crate-type lib -Zassert-incr-state=not-loaded
+//[cfail2] compile-flags: -lfoo -lbar --crate-type lib -Zassert-incr-state=not-loaded
diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs
index 7498d0305e0..a7c79e9d751 100644
--- a/src/test/incremental/struct_change_field_name.rs
+++ b/src/test/incremental/struct_change_field_name.rs
@@ -3,6 +3,7 @@
 
 // revisions:rpass1 cfail2
 // compile-flags: -Z query-dep-graph
+// [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/ui/suggestions/issue-90974.rs b/src/test/ui/suggestions/issue-90974.rs
new file mode 100644
index 00000000000..83590dbf7ac
--- /dev/null
+++ b/src/test/ui/suggestions/issue-90974.rs
@@ -0,0 +1,3 @@
+fn main() {
+    println!("{}", (3.).recip()); //~ERROR
+}
diff --git a/src/test/ui/suggestions/issue-90974.stderr b/src/test/ui/suggestions/issue-90974.stderr
new file mode 100644
index 00000000000..e1fb479a3a7
--- /dev/null
+++ b/src/test/ui/suggestions/issue-90974.stderr
@@ -0,0 +1,14 @@
+error[E0689]: can't call method `recip` on ambiguous numeric type `{float}`
+  --> $DIR/issue-90974.rs:2:25
+   |
+LL |     println!("{}", (3.).recip());
+   |                         ^^^^^
+   |
+help: you must specify a concrete type for this numeric value, like `f32`
+   |
+LL |     println!("{}", (3_f32).recip());
+   |                     ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/synthetic-param.rs b/src/test/ui/synthetic-param.rs
deleted file mode 100644
index e14697f5c3e..00000000000
--- a/src/test/ui/synthetic-param.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![feature(rustc_attrs)]
-
-fn func<#[rustc_synthetic] T>(_: T) {}
-
-struct Foo;
-
-impl Foo {
-    pub fn func<#[rustc_synthetic] T>(_: T) {}
-}
-
-struct Bar<S> {
-    t: S
-}
-
-impl<S> Bar<S> {
-    pub fn func<#[rustc_synthetic] T>(_: T) {}
-}
-
-fn main() {
-    func::<u8>(42); //~ ERROR cannot provide explicit generic arguments
-    func(42); // Ok
-
-    Foo::func::<u8>(42); //~ ERROR cannot provide explicit generic arguments
-    Foo::func(42); // Ok
-
-    Bar::<i8>::func::<u8>(42); //~ ERROR cannot provide explicit generic arguments
-    Bar::<i8>::func(42); // Ok
-}
diff --git a/src/test/ui/synthetic-param.stderr b/src/test/ui/synthetic-param.stderr
deleted file mode 100644
index 5cb9ad31fbf..00000000000
--- a/src/test/ui/synthetic-param.stderr
+++ /dev/null
@@ -1,30 +0,0 @@
-error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:20:12
-   |
-LL |     func::<u8>(42);
-   |            ^^ explicit generic argument not allowed
-   |
-   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
-   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
-
-error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:23:17
-   |
-LL |     Foo::func::<u8>(42);
-   |                 ^^ explicit generic argument not allowed
-   |
-   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
-   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
-
-error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/synthetic-param.rs:26:23
-   |
-LL |     Bar::<i8>::func::<u8>(42);
-   |                       ^^ explicit generic argument not allowed
-   |
-   = note: see issue #83701 <https://github.com/rust-lang/rust/issues/83701> for more information
-   = help: add `#![feature(explicit_generic_args_with_impl_trait)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0632`.
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index bdeff035e5e..63ad65b8afd 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -3,10 +3,8 @@ use clippy_utils::source::snippet;
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{
-    self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath,
-    SyntheticTyParamKind, TyKind,
-};
+use rustc_hir::{self as hir, GenericArg, GenericBounds, GenericParamKind};
+use rustc_hir::{HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind};
 use rustc_lint::LateContext;
 
 use super::BORROWED_BOX;
@@ -105,7 +103,7 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id:
         if let Some(did) = cx.qpath_res(qpath, id).opt_def_id();
         if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
         if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
-        if synthetic == Some(SyntheticTyParamKind::ImplTrait);
+        if synthetic;
         then {
             Some(generic_param.bounds)
         } else {