about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-12-13 20:12:35 +0000
committerbors <bors@rust-lang.org>2021-12-13 20:12:35 +0000
commit8f117a77d0880ed59afcc1a19c72ec5c1e44b97c (patch)
treec1df0a20824dcb0936f0a52051c2129e2d0e96c6
parent1796de7bb123df3f3d32124ededf1344434f672e (diff)
parentff214b745de20917b398510e78e7aba5afba9a72 (diff)
downloadrust-8f117a77d0880ed59afcc1a19c72ec5c1e44b97c.tar.gz
rust-8f117a77d0880ed59afcc1a19c72ec5c1e44b97c.zip
Auto merge of #91865 - matthiaskrgr:rollup-rai9ecq, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - #91699 (Add `-webkit-appearance: none` to search input)
 - #91846 (rustdoc: Reduce number of arguments for `run_test` a bit)
 - #91847 (Fix FIXME for `generic_arg_infer` in `create_substs_for_ast_path`)
 - #91849 (GATs outlives lint: Try to prove bounds)
 - #91855 (Stabilize const_cstr_unchecked)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_infer/src/infer/free_regions.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs88
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs54
-rw-r--r--library/std/src/ffi/c_str.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--src/librustdoc/doctest.rs95
-rw-r--r--src/librustdoc/doctest/tests.rs34
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/librustdoc/markdown.rs4
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/dont-use-defaults.rs15
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/issue-91614.rs8
-rw-r--r--src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr18
-rw-r--r--src/test/ui/generic-associated-types/issue-86787.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-86787.stderr7
-rw-r--r--src/test/ui/generic-associated-types/self-outlives-lint.rs45
-rw-r--r--src/test/ui/generic-associated-types/self-outlives-lint.stderr95
18 files changed, 300 insertions, 177 deletions
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 62c17e6a10f..1dfaae7a150 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -6,7 +6,6 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
-#![feature(const_cstr_unchecked)]
 #![feature(crate_visibility_modifier)]
 #![feature(extern_types)]
 #![feature(in_band_lifetimes)]
diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs
index 4814b65e320..e93cdf79421 100644
--- a/compiler/rustc_infer/src/infer/free_regions.rs
+++ b/compiler/rustc_infer/src/infer/free_regions.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt};
 ///
 /// This stuff is a bit convoluted and should be refactored, but as we
 /// transition to NLL, it'll all go away anyhow.
-pub struct RegionRelations<'a, 'tcx> {
+pub(crate) struct RegionRelations<'a, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
     /// The context used for debug messages
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 85ee6d2cdc2..a5ec84a4f14 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -28,7 +28,7 @@ use std::fmt;
 /// assuming such values can be found. It returns the final values of
 /// all the variables as well as a set of errors that must be reported.
 #[instrument(level = "debug", skip(region_rels, var_infos, data))]
-pub fn resolve<'tcx>(
+pub(crate) fn resolve<'tcx>(
     region_rels: &RegionRelations<'_, 'tcx>,
     var_infos: VarInfos,
     data: RegionConstraintData<'tcx>,
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 752183365d6..aad8dd2119f 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -414,34 +414,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 arg: &GenericArg<'_>,
             ) -> subst::GenericArg<'tcx> {
                 let tcx = self.astconv.tcx();
+
+                let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| {
+                    if has_default {
+                        tcx.check_optional_stability(
+                            param.def_id,
+                            Some(arg.id()),
+                            arg.span(),
+                            None,
+                            |_, _| {
+                                // Default generic parameters may not be marked
+                                // with stability attributes, i.e. when the
+                                // default parameter was defined at the same time
+                                // as the rest of the type. As such, we ignore missing
+                                // stability attributes.
+                            },
+                        )
+                    }
+                    if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
+                        self.inferred_params.push(ty.span);
+                        tcx.ty_error().into()
+                    } else {
+                        self.astconv.ast_ty_to_ty(ty).into()
+                    }
+                };
+
                 match (&param.kind, arg) {
                     (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
                         self.astconv.ast_region_to_region(lt, Some(param)).into()
                     }
                     (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
-                        if has_default {
-                            tcx.check_optional_stability(
-                                param.def_id,
-                                Some(arg.id()),
-                                arg.span(),
-                                None,
-                                |_, _| {
-                                    // Default generic parameters may not be marked
-                                    // with stability attributes, i.e. when the
-                                    // default parameter was defined at the same time
-                                    // as the rest of the type. As such, we ignore missing
-                                    // stability attributes.
-                                },
-                            )
-                        }
-                        if let (hir::TyKind::Infer, false) =
-                            (&ty.kind, self.astconv.allow_ty_infer())
-                        {
-                            self.inferred_params.push(ty.span);
-                            tcx.ty_error().into()
-                        } else {
-                            self.astconv.ast_ty_to_ty(ty).into()
-                        }
+                        handle_ty_args(has_default, ty)
+                    }
+                    (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
+                        handle_ty_args(has_default, &inf.to_ty())
                     }
                     (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
                         ty::Const::from_opt_const_arg_anon_const(
@@ -453,41 +459,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         )
                         .into()
                     }
-                    (&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => {
-                        if has_default {
-                            tcx.const_param_default(param.def_id).into()
-                        } else if self.astconv.allow_ty_infer() {
-                            // FIXME(const_generics): Actually infer parameter here?
-                            todo!()
-                        } else {
-                            self.inferred_params.push(inf.span);
-                            tcx.ty_error().into()
-                        }
-                    }
-                    (
-                        &GenericParamDefKind::Type { has_default, .. },
-                        hir::GenericArg::Infer(inf),
-                    ) => {
-                        if has_default {
-                            tcx.check_optional_stability(
-                                param.def_id,
-                                Some(arg.id()),
-                                arg.span(),
-                                None,
-                                |_, _| {
-                                    // Default generic parameters may not be marked
-                                    // with stability attributes, i.e. when the
-                                    // default parameter was defined at the same time
-                                    // as the rest of the type. As such, we ignore missing
-                                    // stability attributes.
-                                },
-                            );
-                        }
+                    (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
+                        let ty = tcx.at(self.span).type_of(param.def_id);
                         if self.astconv.allow_ty_infer() {
-                            self.astconv.ast_ty_to_ty(&inf.to_ty()).into()
+                            self.astconv.ct_infer(ty, Some(param), inf.span).into()
                         } else {
                             self.inferred_params.push(inf.span);
-                            tcx.ty_error().into()
+                            tcx.const_error(ty).into()
                         }
                     }
                     _ => unreachable!(),
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 3fd3284d8b1..1404bc27167 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -426,22 +426,48 @@ fn check_gat_where_clauses(
         }
     }
 
-    // If there are any missing clauses, emit an error
-    let mut clauses = clauses.unwrap_or_default();
+    // If there are any clauses that aren't provable, emit an error
+    let clauses = clauses.unwrap_or_default();
     debug!(?clauses);
     if !clauses.is_empty() {
-        let written_predicates: ty::GenericPredicates<'_> =
-            tcx.explicit_predicates_of(trait_item.def_id);
+        let param_env = tcx.param_env(trait_item.def_id);
+
         let mut clauses: Vec<_> = clauses
-            .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
+            .into_iter()
+            .filter(|clause| match clause.kind().skip_binder() {
+                ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+                    !region_known_to_outlive(
+                        tcx,
+                        trait_item.hir_id(),
+                        param_env,
+                        &FxHashSet::default(),
+                        a,
+                        b,
+                    )
+                }
+                ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
+                    !ty_known_to_outlive(
+                        tcx,
+                        trait_item.hir_id(),
+                        param_env,
+                        &FxHashSet::default(),
+                        a,
+                        b,
+                    )
+                }
+                _ => bug!("Unexpected PredicateKind"),
+            })
             .map(|clause| format!("{}", clause))
             .collect();
+
         // We sort so that order is predictable
         clauses.sort();
+
         if !clauses.is_empty() {
+            let plural = if clauses.len() > 1 { "s" } else { "" };
             let mut err = tcx.sess.struct_span_err(
                 trait_item.span,
-                &format!("Missing required bounds on {}", trait_item.ident),
+                &format!("missing required bound{} on `{}`", plural, trait_item.ident),
             );
 
             let suggestion = format!(
@@ -455,11 +481,22 @@ fn check_gat_where_clauses(
             );
             err.span_suggestion(
                 trait_item.generics.where_clause.tail_span_for_suggestion(),
-                "add the required where clauses",
+                &format!("add the required where clause{}", plural),
                 suggestion,
                 Applicability::MachineApplicable,
             );
 
+            let bound = if clauses.len() > 1 { "these bounds are" } else { "this bound is" };
+            err.note(&format!(
+                "{} currently required to ensure that impls have maximum flexibility",
+                bound
+            ));
+            err.note(
+                "we are soliciting feedback, see issue #87479 \
+                 <https://github.com/rust-lang/rust/issues/87479> \
+                 for more information",
+            );
+
             err.emit()
         }
     }
@@ -541,7 +578,8 @@ fn region_known_to_outlive<'tcx>(
         });
 
         use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
-        (&infcx).push_sub_region_constraint(origin, region_a, region_b);
+        // `region_a: region_b` -> `region_b <= region_a`
+        (&infcx).push_sub_region_constraint(origin, region_b, region_a);
 
         let errors = infcx.resolve_regions(
             id.expect_owner().to_def_id(),
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 465bbae8631..9c1b79d6966 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -1259,7 +1259,7 @@ impl CStr {
     #[inline]
     #[must_use]
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-    #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
+    #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
         // SAFETY: Casting to CStr is safe because its internal representation
         // is a [u8] too (safe only inside std).
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index d4ff642cd13..dabab667ee9 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -252,7 +252,6 @@
 #![feature(char_internals)]
 #![cfg_attr(not(bootstrap), feature(concat_bytes))]
 #![feature(concat_idents)]
-#![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
 #![feature(const_fn_trait_bound)]
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 56ccdfae1d8..ac24543929b 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -29,20 +29,21 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::{Arc, Mutex};
 
 use crate::clean::{types::AttributesExt, Attributes};
-use crate::config::Options;
+use crate::config::Options as RustdocOptions;
 use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
 use crate::lint::init_lints;
 use crate::passes::span_of_attrs;
 
+/// Options that apply to all doctests in a crate or Markdown file (for `rustdoc foo.md`).
 #[derive(Clone, Default)]
-crate struct TestOptions {
+crate struct GlobalTestOptions {
     /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     crate no_crate_inject: bool,
     /// Additional crate-level attributes to add to doctests.
     crate attrs: Vec<String>,
 }
 
-crate fn run(options: Options) -> Result<(), ErrorReported> {
+crate fn run(options: RustdocOptions) -> Result<(), ErrorReported> {
     let input = config::Input::File(options.input.clone());
 
     let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name;
@@ -214,10 +215,10 @@ crate fn run_tests(mut test_args: Vec<String>, nocapture: bool, tests: Vec<test:
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
-fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
+fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
     use rustc_ast_pretty::pprust;
 
-    let mut opts = TestOptions { no_crate_inject: false, attrs: Vec::new() };
+    let mut opts = GlobalTestOptions { no_crate_inject: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -292,16 +293,13 @@ fn run_test(
     test: &str,
     crate_name: &str,
     line: usize,
-    options: Options,
-    should_panic: bool,
+    rustdoc_options: RustdocOptions,
+    mut lang_string: LangString,
     no_run: bool,
-    as_test_harness: bool,
     runtool: Option<String>,
     runtool_args: Vec<String>,
     target: TargetTriple,
-    compile_fail: bool,
-    mut error_codes: Vec<String>,
-    opts: &TestOptions,
+    opts: &GlobalTestOptions,
     edition: Edition,
     outdir: DirState,
     path: PathBuf,
@@ -309,49 +307,49 @@ fn run_test(
     report_unused_externs: impl Fn(UnusedExterns),
 ) -> Result<(), TestFailure> {
     let (test, line_offset, supports_color) =
-        make_test(test, Some(crate_name), as_test_harness, opts, edition, Some(test_id));
+        make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id));
 
     let output_file = outdir.path().join("rust_out");
 
-    let rustc_binary = options
+    let rustc_binary = rustdoc_options
         .test_builder
         .as_deref()
         .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
     let mut compiler = Command::new(&rustc_binary);
     compiler.arg("--crate-type").arg("bin");
-    for cfg in &options.cfgs {
+    for cfg in &rustdoc_options.cfgs {
         compiler.arg("--cfg").arg(&cfg);
     }
-    if let Some(sysroot) = options.maybe_sysroot {
+    if let Some(sysroot) = rustdoc_options.maybe_sysroot {
         compiler.arg("--sysroot").arg(sysroot);
     }
     compiler.arg("--edition").arg(&edition.to_string());
     compiler.env("UNSTABLE_RUSTDOC_TEST_PATH", path);
     compiler.env("UNSTABLE_RUSTDOC_TEST_LINE", format!("{}", line as isize - line_offset as isize));
     compiler.arg("-o").arg(&output_file);
-    if as_test_harness {
+    if lang_string.test_harness {
         compiler.arg("--test");
     }
-    if options.json_unused_externs && !compile_fail {
+    if rustdoc_options.json_unused_externs && !lang_string.compile_fail {
         compiler.arg("--error-format=json");
         compiler.arg("--json").arg("unused-externs");
         compiler.arg("-Z").arg("unstable-options");
         compiler.arg("-W").arg("unused_crate_dependencies");
     }
-    for lib_str in &options.lib_strs {
+    for lib_str in &rustdoc_options.lib_strs {
         compiler.arg("-L").arg(&lib_str);
     }
-    for extern_str in &options.extern_strs {
+    for extern_str in &rustdoc_options.extern_strs {
         compiler.arg("--extern").arg(&extern_str);
     }
     compiler.arg("-Ccodegen-units=1");
-    for codegen_options_str in &options.codegen_options_strs {
+    for codegen_options_str in &rustdoc_options.codegen_options_strs {
         compiler.arg("-C").arg(&codegen_options_str);
     }
-    for debugging_option_str in &options.debugging_opts_strs {
+    for debugging_option_str in &rustdoc_options.debugging_opts_strs {
         compiler.arg("-Z").arg(&debugging_option_str);
     }
-    if no_run && !compile_fail && options.persist_doctests.is_none() {
+    if no_run && !lang_string.compile_fail && rustdoc_options.persist_doctests.is_none() {
         compiler.arg("--emit=metadata");
     }
     compiler.arg("--target").arg(match target {
@@ -360,7 +358,7 @@ fn run_test(
             path.to_str().expect("target path must be valid unicode").to_string()
         }
     });
-    if let ErrorOutputType::HumanReadable(kind) = options.error_format {
+    if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {
         let (short, color_config) = kind.unzip();
 
         if short {
@@ -418,20 +416,20 @@ fn run_test(
 
     let out = out_lines.join("\n");
     let _bomb = Bomb(&out);
-    match (output.status.success(), compile_fail) {
+    match (output.status.success(), lang_string.compile_fail) {
         (true, true) => {
             return Err(TestFailure::UnexpectedCompilePass);
         }
         (true, false) => {}
         (false, true) => {
-            if !error_codes.is_empty() {
+            if !lang_string.error_codes.is_empty() {
                 // We used to check if the output contained "error[{}]: " but since we added the
                 // colored output, we can't anymore because of the color escape characters before
                 // the ":".
-                error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
+                lang_string.error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
 
-                if !error_codes.is_empty() {
-                    return Err(TestFailure::MissingErrorCodes(error_codes));
+                if !lang_string.error_codes.is_empty() {
+                    return Err(TestFailure::MissingErrorCodes(lang_string.error_codes));
                 }
             }
         }
@@ -454,11 +452,11 @@ fn run_test(
     } else {
         cmd = Command::new(output_file);
     }
-    if let Some(run_directory) = options.test_run_directory {
+    if let Some(run_directory) = rustdoc_options.test_run_directory {
         cmd.current_dir(run_directory);
     }
 
-    let result = if options.nocapture {
+    let result = if rustdoc_options.nocapture {
         cmd.status().map(|status| process::Output {
             status,
             stdout: Vec::new(),
@@ -470,9 +468,9 @@ fn run_test(
     match result {
         Err(e) => return Err(TestFailure::ExecutionError(e)),
         Ok(out) => {
-            if should_panic && out.status.success() {
+            if lang_string.should_panic && out.status.success() {
                 return Err(TestFailure::UnexpectedRunPass);
-            } else if !should_panic && !out.status.success() {
+            } else if !lang_string.should_panic && !out.status.success() {
                 return Err(TestFailure::ExecutionFailure(out));
             }
         }
@@ -487,7 +485,7 @@ crate fn make_test(
     s: &str,
     crate_name: Option<&str>,
     dont_insert_main: bool,
-    opts: &TestOptions,
+    opts: &GlobalTestOptions,
     edition: Edition,
     test_id: Option<&str>,
 ) -> (String, usize, bool) {
@@ -804,11 +802,11 @@ crate struct Collector {
     // the `names` vector of that test will be `["Title", "Subtitle"]`.
     names: Vec<String>,
 
-    options: Options,
+    rustdoc_options: RustdocOptions,
     use_headers: bool,
     enable_per_target_ignores: bool,
     crate_name: Symbol,
-    opts: TestOptions,
+    opts: GlobalTestOptions,
     position: Span,
     source_map: Option<Lrc<SourceMap>>,
     filename: Option<PathBuf>,
@@ -820,9 +818,9 @@ crate struct Collector {
 impl Collector {
     crate fn new(
         crate_name: Symbol,
-        options: Options,
+        rustdoc_options: RustdocOptions,
         use_headers: bool,
-        opts: TestOptions,
+        opts: GlobalTestOptions,
         source_map: Option<Lrc<SourceMap>>,
         filename: Option<PathBuf>,
         enable_per_target_ignores: bool,
@@ -830,7 +828,7 @@ impl Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
-            options,
+            rustdoc_options,
             use_headers,
             enable_per_target_ignores,
             crate_name,
@@ -884,14 +882,14 @@ impl Tester for Collector {
         let name = self.generate_name(line, &filename);
         let crate_name = self.crate_name.to_string();
         let opts = self.opts.clone();
-        let edition = config.edition.unwrap_or(self.options.edition);
-        let options = self.options.clone();
-        let runtool = self.options.runtool.clone();
-        let runtool_args = self.options.runtool_args.clone();
-        let target = self.options.target.clone();
+        let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
+        let rustdoc_options = self.rustdoc_options.clone();
+        let runtool = self.rustdoc_options.runtool.clone();
+        let runtool_args = self.rustdoc_options.runtool_args.clone();
+        let target = self.rustdoc_options.target.clone();
         let target_str = target.to_string();
         let unused_externs = self.unused_extern_reports.clone();
-        let no_run = config.no_run || options.no_run;
+        let no_run = config.no_run || rustdoc_options.no_run;
         if !config.compile_fail {
             self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
         }
@@ -925,7 +923,7 @@ impl Tester for Collector {
                 self.visited_tests.entry((file.clone(), line)).and_modify(|v| *v += 1).or_insert(0)
             },
         );
-        let outdir = if let Some(mut path) = options.persist_doctests.clone() {
+        let outdir = if let Some(mut path) = rustdoc_options.persist_doctests.clone() {
             path.push(&test_id);
 
             std::fs::create_dir_all(&path)
@@ -965,15 +963,12 @@ impl Tester for Collector {
                     &test,
                     &crate_name,
                     line,
-                    options,
-                    config.should_panic,
+                    rustdoc_options,
+                    config,
                     no_run,
-                    config.test_harness,
                     runtool,
                     runtool_args,
                     target,
-                    config.compile_fail,
-                    config.error_codes,
                     &opts,
                     edition,
                     outdir,
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 099609d0f91..360d2259ea3 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -1,10 +1,10 @@
-use super::{make_test, TestOptions};
+use super::{make_test, GlobalTestOptions};
 use rustc_span::edition::DEFAULT_EDITION;
 
 #[test]
 fn make_test_basic() {
     //basic use: wraps with `fn main`, adds `#![allow(unused)]`
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() {
@@ -19,7 +19,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_name_no_use() {
     // If you give a crate name but *don't* use it within the test, it won't bother inserting
     // the `extern crate` statement.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() {
@@ -34,7 +34,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_name() {
     // If you give a crate name and use it within the test, it will insert an `extern crate`
     // statement before `fn main`.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -52,7 +52,7 @@ assert_eq!(2+2, 4);
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts = TestOptions { no_crate_inject: true, attrs: vec![] };
+    let opts = GlobalTestOptions { no_crate_inject: true, attrs: vec![] };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -70,7 +70,7 @@ fn make_test_ignore_std() {
     // Even if you include a crate name, and use it in the doctest, we still won't include an
     // `extern crate` statement if the crate is "std" -- that's included already by the
     // compiler!
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "use std::*;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -87,7 +87,7 @@ assert_eq!(2+2, 4);
 fn make_test_manual_extern_crate() {
     // When you manually include an `extern crate` statement in your doctest, `make_test`
     // assumes you've included one for your own crate too.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "extern crate asdf;
 use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -104,7 +104,7 @@ assert_eq!(2+2, 4);
 
 #[test]
 fn make_test_manual_extern_crate_with_macro_use() {
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "#[macro_use] extern crate asdf;
 use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -123,7 +123,7 @@ assert_eq!(2+2, 4);
 fn make_test_opts_attrs() {
     // If you supplied some doctest attributes with `#![doc(test(attr(...)))]`, it will use
     // those instead of the stock `#![allow(unused)]`.
-    let mut opts = TestOptions::default();
+    let mut opts = GlobalTestOptions::default();
     opts.attrs.push("feature(sick_rad)".to_string());
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
@@ -155,7 +155,7 @@ assert_eq!(2+2, 4);
 fn make_test_crate_attrs() {
     // Including inner attributes in your doctest will apply them to the whole "crate", pasting
     // them outside the generated main function.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "#![feature(sick_rad)]
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -171,7 +171,7 @@ assert_eq!(2+2, 4);
 #[test]
 fn make_test_with_main() {
     // Including your own `fn main` wrapper lets the test use it verbatim.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "fn main() {
     assert_eq!(2+2, 4);
 }";
@@ -187,7 +187,7 @@ fn main() {
 #[test]
 fn make_test_fake_main() {
     // ... but putting it in a comment will still provide a wrapper.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -203,7 +203,7 @@ assert_eq!(2+2, 4);
 #[test]
 fn make_test_dont_insert_main() {
     // Even with that, if you set `dont_insert_main`, it won't create the `fn main` wrapper.
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "//Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -216,7 +216,7 @@ assert_eq!(2+2, 4);"
 
 #[test]
 fn make_test_issues_21299_33731() {
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
 
     let input = "// fn main
 assert_eq!(2+2, 4);";
@@ -248,7 +248,7 @@ assert_eq!(asdf::foo, 4);
 
 #[test]
 fn make_test_main_in_macro() {
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "#[macro_use] extern crate my_crate;
 test_wrapper! {
     fn main() {}
@@ -267,7 +267,7 @@ test_wrapper! {
 #[test]
 fn make_test_returns_result() {
     // creates an inner function and unwraps it
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "use std::io;
 let mut input = String::new();
 io::stdin().read_line(&mut input)?;
@@ -287,7 +287,7 @@ Ok::<(), io:Error>(())
 #[test]
 fn make_test_named_wrapper() {
     // creates an inner function with a specific name
-    let opts = TestOptions::default();
+    let opts = GlobalTestOptions::default();
     let input = "assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
 fn main() { #[allow(non_snake_case)] fn _doctest_main__some_unique_name() {
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 79c7626ffc4..5751ec2cc02 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -892,6 +892,10 @@ h2.small-section-header > .anchor {
 	top: 10px;
 }
 .search-input {
+	/* Override Normalize.css: it has a rule that sets
+	   -webkit-appearance: textfield for search inputs. That
+	   causes rounded corners and no border on iOS Safari. */
+	-webkit-appearance: none;
 	/* Override Normalize.css: we have margins and do
 	 not want to overflow - the `moz` attribute is necessary
 	 until Firefox 29, too early to drop at this point */
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index abb4bec5ca1..906b8f8a245 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -7,7 +7,7 @@ use rustc_span::source_map::DUMMY_SP;
 use rustc_span::Symbol;
 
 use crate::config::{Options, RenderOptions};
-use crate::doctest::{Collector, TestOptions};
+use crate::doctest::{Collector, GlobalTestOptions};
 use crate::html::escape::Escape;
 use crate::html::markdown;
 use crate::html::markdown::{
@@ -129,7 +129,7 @@ crate fn render<P: AsRef<Path>>(
 crate fn test(options: Options) -> Result<(), String> {
     let input_str = read_to_string(&options.input)
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
-    let mut opts = TestOptions::default();
+    let mut opts = GlobalTestOptions::default();
     opts.no_crate_inject = true;
     let mut collector = Collector::new(
         Symbol::intern(&options.input.display().to_string()),
diff --git a/src/test/ui/const-generics/generic_arg_infer/dont-use-defaults.rs b/src/test/ui/const-generics/generic_arg_infer/dont-use-defaults.rs
new file mode 100644
index 00000000000..251160a0f5f
--- /dev/null
+++ b/src/test/ui/const-generics/generic_arg_infer/dont-use-defaults.rs
@@ -0,0 +1,15 @@
+// run-pass
+#![feature(generic_arg_infer)]
+
+// test that we dont use defaults to aide in type inference
+
+struct Foo<const N: usize = 2>;
+impl<const N: usize> Foo<N> {
+    fn make_arr() -> [(); N] {
+        [(); N]
+    }
+}
+
+fn main() {
+    let [(), (), ()] = Foo::<_>::make_arr();
+}
diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
new file mode 100644
index 00000000000..413cc153924
--- /dev/null
+++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs
@@ -0,0 +1,8 @@
+#![feature(portable_simd)]
+#![feature(generic_arg_infer)]
+use std::simd::Mask;
+
+fn main() {
+    let y = Mask::<_, _>::splat(false);
+    //~^ error: type annotations needed for `Mask<_, {_: usize}>`
+}
diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
new file mode 100644
index 00000000000..71a5ff79280
--- /dev/null
+++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr
@@ -0,0 +1,18 @@
+error[E0283]: type annotations needed for `Mask<_, {_: usize}>`
+  --> $DIR/issue-91614.rs:6:13
+   |
+LL |     let y = Mask::<_, _>::splat(false);
+   |         -   ^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+   |         |
+   |         consider giving `y` the explicit type `Mask<_, LANES>`, where the type parameter `T` is specified
+   |
+   = note: cannot satisfy `_: MaskElement`
+note: required by a bound in `Mask::<T, LANES>::splat`
+  --> $SRC_DIR/core/src/../../portable-simd/crates/core_simd/src/masks.rs:LL:COL
+   |
+LL |     T: MaskElement,
+   |        ^^^^^^^^^^^ required by this bound in `Mask::<T, LANES>::splat`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/generic-associated-types/issue-86787.rs b/src/test/ui/generic-associated-types/issue-86787.rs
index 0f62f83e256..5863bac2f9d 100644
--- a/src/test/ui/generic-associated-types/issue-86787.rs
+++ b/src/test/ui/generic-associated-types/issue-86787.rs
@@ -9,7 +9,7 @@ enum Either<L, R> {
 pub trait HasChildrenOf {
     type T;
     type TRef<'a>;
-    //~^ Missing required bounds
+    //~^ missing required
 
     fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
     fn take_children(self) -> Vec<Self::T>;
diff --git a/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr
index 87dcd875de7..d4b2267d3dd 100644
--- a/src/test/ui/generic-associated-types/issue-86787.stderr
+++ b/src/test/ui/generic-associated-types/issue-86787.stderr
@@ -1,10 +1,13 @@
-error: Missing required bounds on TRef
+error: missing required bound on `TRef`
   --> $DIR/issue-86787.rs:11:5
    |
 LL |     type TRef<'a>;
    |     ^^^^^^^^^^^^^-
    |                  |
-   |                  help: add the required where clauses: `where Self: 'a`
+   |                  help: add the required where clause: `where Self: 'a`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.rs b/src/test/ui/generic-associated-types/self-outlives-lint.rs
index af90d158855..37b3a6155d5 100644
--- a/src/test/ui/generic-associated-types/self-outlives-lint.rs
+++ b/src/test/ui/generic-associated-types/self-outlives-lint.rs
@@ -7,7 +7,7 @@ use std::fmt::Debug;
 // We have a `&'a self`, so we need a `Self: 'a`
 trait Iterable {
     type Item<'x>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn iter<'a>(&'a self) -> Self::Item<'a>;
 }
 
@@ -23,7 +23,7 @@ impl<T> Iterable for T {
 // We have a `&'a T`, so we need a `T: 'x`
 trait Deserializer<T> {
     type Out<'x>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
 }
 
@@ -37,14 +37,14 @@ impl<T> Deserializer<T> for () {
 // We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
 trait Deserializer2<T> {
     type Out<'x>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
 }
 
 // We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
 trait Deserializer3<T, U> {
     type Out<'x, 'y>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
 }
 
@@ -59,7 +59,7 @@ struct Wrap<T>(T);
 // We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
 trait Des {
     type Out<'x, D>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
 }
 /*
@@ -75,7 +75,7 @@ impl Des for () {
 // implied bound that `T: 'z`, so we require `D: 'x`
 trait Des2 {
     type Out<'x, D>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
 }
 /*
@@ -90,7 +90,7 @@ impl Des2 for () {
 // We see `&'z T`, so we require `D: 'x`
 trait Des3 {
     type Out<'x, D>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
 }
 /*
@@ -112,7 +112,7 @@ trait NoGat<'a> {
 // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
 trait TraitLifetime<'a> {
     type Bar<'b>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn method(&'a self) -> Self::Bar<'a>;
 }
 
@@ -120,14 +120,14 @@ trait TraitLifetime<'a> {
 // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
 trait TraitLifetimeWhere<'a> where Self: 'a {
     type Bar<'b>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn method(&'a self) -> Self::Bar<'a>;
 }
 
 // Explicit bound instead of implicit; we want to still error
 trait ExplicitBound {
     type Bar<'b>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
 }
 
@@ -141,14 +141,15 @@ trait NotInReturn {
 trait IterableTwo {
     type Item<'a>;
     type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn iter<'a>(&'a self) -> Self::Iterator<'a>;
 }
 
-// We also should report region outlives clauses
+// We also should report region outlives clauses. Here, we know that `'y: 'x`,
+// because of `&'x &'y`, so we require that `'b: 'a`.
 trait RegionOutlives {
     type Bar<'a, 'b>;
-    //~^ Missing required bounds
+    //~^ missing required
     fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
 }
 
@@ -161,6 +162,17 @@ impl Foo for () {
 }
 */
 
+// Similar to the above, except with explicit bounds
+trait ExplicitRegionOutlives<'ctx> {
+    type Fut<'out>;
+    //~^ missing required
+
+    fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out>
+    where
+        'ctx: 'out;
+}
+
+
 // If there are multiple methods that return the GAT, require a set of clauses
 // that can be satisfied by *all* methods
 trait MultipleMethods {
@@ -170,4 +182,11 @@ trait MultipleMethods {
     fn gimme_default(&self) -> Self::Bar<'static>;
 }
 
+// We would normally require `Self: 'a`, but we can prove that `Self: 'static`
+// because of the the bounds on the trait, so the bound is proven
+trait Trait: 'static {
+    type Assoc<'a>;
+    fn make_assoc(_: &u32) -> Self::Assoc<'_>;
+}
+
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/self-outlives-lint.stderr b/src/test/ui/generic-associated-types/self-outlives-lint.stderr
index bf85780f69f..3b9146ad875 100644
--- a/src/test/ui/generic-associated-types/self-outlives-lint.stderr
+++ b/src/test/ui/generic-associated-types/self-outlives-lint.stderr
@@ -1,98 +1,145 @@
-error: Missing required bounds on Item
+error: missing required bound on `Item`
   --> $DIR/self-outlives-lint.rs:9:5
    |
 LL |     type Item<'x>;
    |     ^^^^^^^^^^^^^-
    |                  |
-   |                  help: add the required where clauses: `where Self: 'x`
+   |                  help: add the required where clause: `where Self: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bound on `Out`
   --> $DIR/self-outlives-lint.rs:25:5
    |
 LL |     type Out<'x>;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: add the required where clauses: `where T: 'x`
+   |                 help: add the required where clause: `where T: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bound on `Out`
   --> $DIR/self-outlives-lint.rs:39:5
    |
 LL |     type Out<'x>;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: add the required where clauses: `where T: 'x`
+   |                 help: add the required where clause: `where T: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bounds on `Out`
   --> $DIR/self-outlives-lint.rs:46:5
    |
 LL |     type Out<'x, 'y>;
    |     ^^^^^^^^^^^^^^^^-
    |                     |
    |                     help: add the required where clauses: `where T: 'x, U: 'y`
+   |
+   = note: these bounds are currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bound on `Out`
   --> $DIR/self-outlives-lint.rs:61:5
    |
 LL |     type Out<'x, D>;
    |     ^^^^^^^^^^^^^^^-
    |                    |
-   |                    help: add the required where clauses: `where D: 'x`
+   |                    help: add the required where clause: `where D: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bound on `Out`
   --> $DIR/self-outlives-lint.rs:77:5
    |
 LL |     type Out<'x, D>;
    |     ^^^^^^^^^^^^^^^-
    |                    |
-   |                    help: add the required where clauses: `where D: 'x`
+   |                    help: add the required where clause: `where D: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Out
+error: missing required bound on `Out`
   --> $DIR/self-outlives-lint.rs:92:5
    |
 LL |     type Out<'x, D>;
    |     ^^^^^^^^^^^^^^^-
    |                    |
-   |                    help: add the required where clauses: `where D: 'x`
+   |                    help: add the required where clause: `where D: 'x`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Bar
+error: missing required bounds on `Bar`
   --> $DIR/self-outlives-lint.rs:114:5
    |
 LL |     type Bar<'b>;
    |     ^^^^^^^^^^^^-
    |                 |
    |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+   |
+   = note: these bounds are currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Bar
+error: missing required bound on `Bar`
   --> $DIR/self-outlives-lint.rs:122:5
    |
 LL |     type Bar<'b>;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: add the required where clauses: `where Self: 'a, Self: 'b`
+   |                 help: add the required where clause: `where Self: 'b`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Bar
+error: missing required bound on `Bar`
   --> $DIR/self-outlives-lint.rs:129:5
    |
 LL |     type Bar<'b>;
    |     ^^^^^^^^^^^^-
    |                 |
-   |                 help: add the required where clauses: `where Self: 'b`
+   |                 help: add the required where clause: `where Self: 'b`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Iterator
+error: missing required bound on `Iterator`
   --> $DIR/self-outlives-lint.rs:143:5
    |
 LL |     type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
    |                                                       |
-   |                                                       help: add the required where clauses: `where Self: 'a`
+   |                                                       help: add the required where clause: `where Self: 'a`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: Missing required bounds on Bar
-  --> $DIR/self-outlives-lint.rs:150:5
+error: missing required bound on `Bar`
+  --> $DIR/self-outlives-lint.rs:151:5
    |
 LL |     type Bar<'a, 'b>;
    |     ^^^^^^^^^^^^^^^^-
    |                     |
-   |                     help: add the required where clauses: `where 'a: 'b`
+   |                     help: add the required where clause: `where 'b: 'a`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
+
+error: missing required bound on `Fut`
+  --> $DIR/self-outlives-lint.rs:167:5
+   |
+LL |     type Fut<'out>;
+   |     ^^^^^^^^^^^^^^-
+   |                   |
+   |                   help: add the required where clause: `where 'ctx: 'out`
+   |
+   = note: this bound is currently required to ensure that impls have maximum flexibility
+   = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information
 
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors