From 7fda86249fd37e5ff148427771423bfefc0b1e4a Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Thu, 30 Jun 2022 10:26:17 -0400
Subject: [PATCH 1/7] promote placeholder bounds to 'static obligations

In NLL, when we are promoting a bound out from a closure,
if we have a requirement that `T: 'a` where `'a` is in a
higher universe, we were previously ignoring that, which is
totally wrong. We should be promoting those constraints to `'static`,
since universes are not expressible across closure boundaries.
---
 .../rustc_borrowck/src/region_infer/mod.rs    | 38 ++++++++++++++++---
 .../generic-associated-types/issue-91139.rs   |  1 +
 .../issue-91139.stderr                        | 14 ++++++-
 src/test/ui/nll/issue-98693.rs                | 21 ++++++++++
 src/test/ui/nll/issue-98693.stderr            | 17 +++++++++
 5 files changed, 85 insertions(+), 6 deletions(-)
 create mode 100644 src/test/ui/nll/issue-98693.rs
 create mode 100644 src/test/ui/nll/issue-98693.stderr

diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f5c9392948b24..aa0af86fbf500 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -916,6 +916,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// The idea then is to lower the `T: 'X` constraint into multiple
     /// bounds -- e.g., if `'X` is the union of two free lifetimes,
     /// `'1` and `'2`, then we would create `T: '1` and `T: '2`.
+    #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))]
     fn try_promote_type_test(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
@@ -933,11 +934,41 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             return false;
         };
 
+        debug!("subject = {:?}", subject);
+
+        let r_scc = self.constraint_sccs.scc(*lower_bound);
+
+        debug!(
+            "lower_bound = {:?} r_scc={:?} universe={:?}",
+            lower_bound, r_scc, self.scc_universes[r_scc]
+        );
+
+        // If the type test requires that `T: 'a` where `'a` is a
+        // placeholder from another universe, that effectively requires
+        // `T: 'static`, so we have to propagate that requirement.
+        //
+        // It doesn't matter *what* universe because the promoted `T` will
+        // always be in the root universe.
+        if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() {
+            debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p);
+            let static_r = self.universal_regions.fr_static;
+            propagated_outlives_requirements.push(ClosureOutlivesRequirement {
+                subject,
+                outlived_free_region: static_r,
+                blame_span: locations.span(body),
+                category: ConstraintCategory::Boring,
+            });
+
+            // we can return here -- the code below might push add'l constraints
+            // but they would all be weaker than this one.
+            return true;
+        }
+
         // For each region outlived by lower_bound find a non-local,
         // universal region (it may be the same region) and add it to
         // `ClosureOutlivesRequirement`.
-        let r_scc = self.constraint_sccs.scc(*lower_bound);
         for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
+            debug!("universal_region_outlived_by ur={:?}", ur);
             // Check whether we can already prove that the "subject" outlives `ur`.
             // If so, we don't have to propagate this requirement to our caller.
             //
@@ -962,8 +993,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 continue;
             }
 
-            debug!("try_promote_type_test: ur={:?}", ur);
-
             let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur);
             debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub);
 
@@ -1000,6 +1029,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// will use it's *external name*, which will be a `RegionKind`
     /// variant that can be used in query responses such as
     /// `ReEarlyBound`.
+    #[instrument(level = "debug", skip(self, infcx))]
     fn try_promote_type_test_subject(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
@@ -1007,8 +1037,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> Option<ClosureOutlivesSubject<'tcx>> {
         let tcx = infcx.tcx;
 
-        debug!("try_promote_type_test_subject(ty = {:?})", ty);
-
         let ty = tcx.fold_regions(ty, |r, _depth| {
             let region_vid = self.to_region_vid(r);
 
diff --git a/src/test/ui/generic-associated-types/issue-91139.rs b/src/test/ui/generic-associated-types/issue-91139.rs
index 092fa939c308d..40eef11f058e1 100644
--- a/src/test/ui/generic-associated-types/issue-91139.rs
+++ b/src/test/ui/generic-associated-types/issue-91139.rs
@@ -22,6 +22,7 @@ fn foo<T>() {
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` does not live long enough
     //~| ERROR `T` does not live long enough
+    //~| ERROR `T` may not live long enough
     //
     // FIXME: This error is bogus, but it arises because we try to validate
     // that `<() as Foo<T>>::Type<'a>` is valid, which requires proving
diff --git a/src/test/ui/generic-associated-types/issue-91139.stderr b/src/test/ui/generic-associated-types/issue-91139.stderr
index 6c5092978c84b..b789b3a42f330 100644
--- a/src/test/ui/generic-associated-types/issue-91139.stderr
+++ b/src/test/ui/generic-associated-types/issue-91139.stderr
@@ -34,6 +34,17 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |                                                          ^^^^^^^^^
 
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue-91139.rs:16:58
+   |
+LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
+   |                                                          ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn foo<T: 'static>() {
+   |         +++++++++
+
 error: `T` does not live long enough
   --> $DIR/issue-91139.rs:16:58
    |
@@ -46,5 +57,6 @@ error: `T` does not live long enough
 LL |     let _: for<'a> fn(<() as Foo<T>>::Type<'a>, &'a T) = |_, _| ();
    |                                                          ^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/nll/issue-98693.rs b/src/test/ui/nll/issue-98693.rs
new file mode 100644
index 0000000000000..18e6ec6304646
--- /dev/null
+++ b/src/test/ui/nll/issue-98693.rs
@@ -0,0 +1,21 @@
+// Regression test for #98693.
+//
+// The closure encounters an obligation that `T` must outlive `!U1`,
+// a placeholder from universe U1. We were ignoring this placeholder
+// when promoting the constraint to the enclosing function, and
+// thus incorrectly judging the closure to be safe.
+
+fn assert_static<T>()
+where
+    for<'a> T: 'a,
+{
+}
+
+fn test<T>() {
+    || {
+        //~^ ERROR the parameter type `T` may not live long enough
+        assert_static::<T>();
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-98693.stderr b/src/test/ui/nll/issue-98693.stderr
new file mode 100644
index 0000000000000..31689620c6414
--- /dev/null
+++ b/src/test/ui/nll/issue-98693.stderr
@@ -0,0 +1,17 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue-98693.rs:15:5
+   |
+LL | /     || {
+LL | |
+LL | |         assert_static::<T>();
+LL | |     };
+   | |_____^ ...so that the type `T` will meet its required lifetime bounds
+   |
+help: consider adding an explicit lifetime bound...
+   |
+LL | fn test<T: 'static>() {
+   |          +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.

From 415028d8912fcdbdbdf9c75850ed85afb8e458d2 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Fri, 8 Jul 2022 15:37:44 +0200
Subject: [PATCH 2/7] Fix rustdoc -Zhelp and -Chelp options

---
 src/librustdoc/config.rs | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 272188f82994c..1f30c7006f5af 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -329,6 +329,17 @@ impl Options {
             return Err(0);
         }
 
+        let z_flags = matches.opt_strs("Z");
+        if z_flags.iter().any(|x| *x == "help") {
+            print_flag_list("-Z", config::DB_OPTIONS);
+            return Err(0);
+        }
+        let c_flags = matches.opt_strs("C");
+        if c_flags.iter().any(|x| *x == "help") {
+            print_flag_list("-C", config::CG_OPTIONS);
+            return Err(0);
+        }
+
         let color = config::parse_color(matches);
         let config::JsonConfig { json_rendered, json_unused_externs, .. } =
             config::parse_json(matches);
@@ -343,17 +354,6 @@ impl Options {
         // check for deprecated options
         check_deprecated_options(matches, &diag);
 
-        let z_flags = matches.opt_strs("Z");
-        if z_flags.iter().any(|x| *x == "help") {
-            print_flag_list("-Z", config::DB_OPTIONS);
-            return Err(0);
-        }
-        let c_flags = matches.opt_strs("C");
-        if c_flags.iter().any(|x| *x == "help") {
-            print_flag_list("-C", config::CG_OPTIONS);
-            return Err(0);
-        }
-
         if matches.opt_strs("passes") == ["list"] {
             println!("Available passes for running rustdoc:");
             for pass in passes::PASSES {

From 91fced8d400209a3316a94b51ec32d72e2b76e3d Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Fri, 8 Jul 2022 17:35:47 +0200
Subject: [PATCH 3/7] Add regex-error-pattern ui check

---
 src/tools/compiletest/src/header.rs  | 11 ++++
 src/tools/compiletest/src/runtest.rs | 76 ++++++++++++++++++++--------
 2 files changed, 67 insertions(+), 20 deletions(-)

diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 7cf4a88c47043..f037e08b18cf9 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -60,6 +60,8 @@ impl EarlyProps {
 pub struct TestProps {
     // Lines that should be expected, in order, on standard out
     pub error_patterns: Vec<String>,
+    // Regexes that should be expected, in order, on standard out
+    pub regex_error_patterns: Vec<String>,
     // Extra flags to pass to the compiler
     pub compile_flags: Vec<String>,
     // Extra flags to pass when the compiled code is run (such as --bench)
@@ -163,6 +165,7 @@ pub struct TestProps {
 
 mod directives {
     pub const ERROR_PATTERN: &'static str = "error-pattern";
+    pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
     pub const COMPILE_FLAGS: &'static str = "compile-flags";
     pub const RUN_FLAGS: &'static str = "run-flags";
     pub const SHOULD_ICE: &'static str = "should-ice";
@@ -200,6 +203,7 @@ impl TestProps {
     pub fn new() -> Self {
         TestProps {
             error_patterns: vec![],
+            regex_error_patterns: vec![],
             compile_flags: vec![],
             run_flags: None,
             pp_exact: None,
@@ -286,6 +290,13 @@ impl TestProps {
                     |r| r,
                 );
 
+                config.push_name_value_directive(
+                    ln,
+                    REGEX_ERROR_PATTERN,
+                    &mut self.regex_error_patterns,
+                    |r| r,
+                );
+
                 if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
                     self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
                 }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index dd9e2a6687e7a..f0ca1390223c2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -323,12 +323,13 @@ impl<'test> TestCx<'test> {
         let output_to_check = self.get_output(&proc_res);
         let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
         if !expected_errors.is_empty() {
-            if !self.props.error_patterns.is_empty() {
+            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
+            {
                 self.fatal("both error pattern and expected errors specified");
             }
             self.check_expected_errors(expected_errors, &proc_res);
         } else {
-            self.check_error_patterns(&output_to_check, &proc_res, pm);
+            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
         }
         if self.props.should_ice {
             match proc_res.status.code() {
@@ -363,7 +364,7 @@ impl<'test> TestCx<'test> {
 
         let output_to_check = self.get_output(&proc_res);
         self.check_correct_failure_status(&proc_res);
-        self.check_error_patterns(&output_to_check, &proc_res, pm);
+        self.check_all_error_patterns(&output_to_check, &proc_res, pm);
     }
 
     fn get_output(&self, proc_res: &ProcRes) -> String {
@@ -1222,14 +1223,13 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn check_error_patterns(
+    fn check_all_error_patterns(
         &self,
         output_to_check: &str,
         proc_res: &ProcRes,
         pm: Option<PassMode>,
     ) {
-        debug!("check_error_patterns");
-        if self.props.error_patterns.is_empty() {
+        if self.props.error_patterns.is_empty() && self.props.regex_error_patterns.is_empty() {
             if pm.is_some() {
                 // FIXME(#65865)
                 return;
@@ -1240,16 +1240,10 @@ impl<'test> TestCx<'test> {
                 ));
             }
         }
-
         let mut missing_patterns: Vec<String> = Vec::new();
 
-        for pattern in &self.props.error_patterns {
-            if output_to_check.contains(pattern.trim()) {
-                debug!("found error pattern {}", pattern);
-            } else {
-                missing_patterns.push(pattern.to_string());
-            }
-        }
+        self.check_error_patterns(output_to_check, &mut missing_patterns);
+        self.check_regex_error_patterns(output_to_check, proc_res, &mut missing_patterns);
 
         if missing_patterns.is_empty() {
             return;
@@ -1268,6 +1262,44 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn check_error_patterns(&self, output_to_check: &str, missing_patterns: &mut Vec<String>) {
+        debug!("check_error_patterns");
+        for pattern in &self.props.error_patterns {
+            if output_to_check.contains(pattern.trim()) {
+                debug!("found error pattern {}", pattern);
+            } else {
+                missing_patterns.push(pattern.to_string());
+            }
+        }
+    }
+
+    fn check_regex_error_patterns(
+        &self,
+        output_to_check: &str,
+        proc_res: &ProcRes,
+        missing_patterns: &mut Vec<String>,
+    ) {
+        debug!("check_regex_error_patterns");
+
+        for pattern in &self.props.regex_error_patterns {
+            let pattern = pattern.trim();
+            let re = match Regex::new(pattern) {
+                Ok(re) => re,
+                Err(err) => {
+                    self.fatal_proc_rec(
+                        &format!("invalid regex error pattern '{}': {:?}", pattern, err),
+                        proc_res,
+                    );
+                }
+            };
+            if re.is_match(output_to_check) {
+                debug!("found regex error pattern {}", pattern);
+            } else {
+                missing_patterns.push(pattern.to_string());
+            }
+        }
+    }
+
     fn check_no_compiler_crash(&self, proc_res: &ProcRes, should_ice: bool) {
         match proc_res.status.code() {
             Some(101) if !should_ice => {
@@ -1892,7 +1924,9 @@ impl<'test> TestCx<'test> {
                 // If we are extracting and matching errors in the new
                 // fashion, then you want JSON mode. Old-skool error
                 // patterns still match the raw compiler output.
-                if self.props.error_patterns.is_empty() {
+                if self.props.error_patterns.is_empty()
+                    && self.props.regex_error_patterns.is_empty()
+                {
                     rustc.args(&["--error-format", "json"]);
                     rustc.args(&["--json", "future-incompat"]);
                 }
@@ -3268,10 +3302,11 @@ impl<'test> TestCx<'test> {
                 self.fatal_proc_rec("test run succeeded!", &proc_res);
             }
 
-            if !self.props.error_patterns.is_empty() {
+            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
+            {
                 // "// error-pattern" comments
                 let output_to_check = self.get_output(&proc_res);
-                self.check_error_patterns(&output_to_check, &proc_res, pm);
+                self.check_all_error_patterns(&output_to_check, &proc_res, pm);
             }
         }
 
@@ -3285,15 +3320,16 @@ impl<'test> TestCx<'test> {
             self.props.error_patterns
         );
         if !explicit && self.config.compare_mode.is_none() {
-            let check_patterns =
-                should_run == WillExecute::No && !self.props.error_patterns.is_empty();
+            let check_patterns = should_run == WillExecute::No
+                && (!self.props.error_patterns.is_empty()
+                    || !self.props.regex_error_patterns.is_empty());
 
             let check_annotations = !check_patterns || !expected_errors.is_empty();
 
             if check_patterns {
                 // "// error-pattern" comments
                 let output_to_check = self.get_output(&proc_res);
-                self.check_error_patterns(&output_to_check, &proc_res, pm);
+                self.check_all_error_patterns(&output_to_check, &proc_res, pm);
             }
 
             if check_annotations {

From 53edb1efc1a97c4c6af74520ec787ca19854835e Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Fri, 8 Jul 2022 15:38:09 +0200
Subject: [PATCH 4/7] Add tests for -Chelp and -Zhelp

---
 src/test/rustdoc-ui/c-help.rs     |   6 +
 src/test/rustdoc-ui/c-help.stdout |  51 ++++++++
 src/test/rustdoc-ui/z-help.rs     |   6 +
 src/test/rustdoc-ui/z-help.stdout | 193 ++++++++++++++++++++++++++++++
 4 files changed, 256 insertions(+)
 create mode 100644 src/test/rustdoc-ui/c-help.rs
 create mode 100644 src/test/rustdoc-ui/c-help.stdout
 create mode 100644 src/test/rustdoc-ui/z-help.rs
 create mode 100644 src/test/rustdoc-ui/z-help.stdout

diff --git a/src/test/rustdoc-ui/c-help.rs b/src/test/rustdoc-ui/c-help.rs
new file mode 100644
index 0000000000000..e166edf8b619c
--- /dev/null
+++ b/src/test/rustdoc-ui/c-help.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Chelp
+// check-stdout
+// regex-error-pattern: -C\s+incremental
+
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/c-help.stdout b/src/test/rustdoc-ui/c-help.stdout
new file mode 100644
index 0000000000000..75b2e2a2a43f4
--- /dev/null
+++ b/src/test/rustdoc-ui/c-help.stdout
@@ -0,0 +1,51 @@
+    -C                       ar=val -- this option is deprecated and does nothing
+    -C               code-model=val -- choose the code model to use (`rustc --print code-models` for details)
+    -C            codegen-units=val -- divide crate into N units to optimize in parallel
+    -C       control-flow-guard=val -- use Windows Control Flow Guard (default: no)
+    -C         debug-assertions=val -- explicitly enable the `cfg(debug_assertions)` directive
+    -C                debuginfo=val -- debug info emission level (0 = no debug info, 1 = line tables only, 2 = full debug info with variable and type information; default: 0)
+    -C default-linker-libraries=val -- allow the linker to link its default libraries (default: no)
+    -C            embed-bitcode=val -- emit bitcode in rlibs (default: yes)
+    -C           extra-filename=val -- extra data to put in each output filename
+    -C     force-frame-pointers=val -- force use of the frame pointers
+    -C      force-unwind-tables=val -- force use of unwind tables
+    -C              incremental=val -- enable incremental compilation
+    -C         inline-threshold=val -- set the threshold for inlining a function
+    -C      instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+        `=all` (implicit value)
+        `=except-unused-generics`
+        `=except-unused-functions`
+        `=off` (default)
+    -C                 link-arg=val -- a single extra argument to append to the linker invocation (can be used several times)
+    -C                link-args=val -- extra arguments to append to the linker invocation (space separated)
+    -C           link-dead-code=val -- keep dead code at link time (useful for code coverage) (default: no)
+    -C      link-self-contained=val -- control whether to link Rust provided C objects/libraries or rely
+        on C toolchain installed in the system
+    -C                   linker=val -- system linker to link outputs with
+    -C            linker-flavor=val -- linker flavor
+    -C        linker-plugin-lto=val -- generate build artifacts that are compatible with linker-based LTO
+    -C                llvm-args=val -- a list of arguments to pass to LLVM (space separated)
+    -C                      lto=val -- perform LLVM link-time optimizations
+    -C                 metadata=val -- metadata to mangle symbol names with
+    -C    no-prepopulate-passes=val -- give an empty list of passes to the pass manager
+    -C               no-redzone=val -- disable the use of the redzone
+    -C           no-stack-check=val -- this option is deprecated and does nothing
+    -C       no-vectorize-loops=val -- disable loop vectorization optimization passes
+    -C         no-vectorize-slp=val -- disable LLVM's SLP vectorization pass
+    -C                opt-level=val -- optimization level (0-3, s, or z; default: 0)
+    -C          overflow-checks=val -- use overflow checks for integer arithmetic
+    -C                    panic=val -- panic strategy to compile crate with
+    -C                   passes=val -- a list of extra LLVM passes to run (space separated)
+    -C           prefer-dynamic=val -- prefer dynamic linking to static linking (default: no)
+    -C         profile-generate=val -- compile the program with profiling instrumentation
+    -C              profile-use=val -- use the given `.profdata` file for profile-guided optimization
+    -C         relocation-model=val -- control generation of position-independent code (PIC) (`rustc --print relocation-models` for details)
+    -C                   remark=val -- print remarks for these optimization passes (space separated, or "all")
+    -C                    rpath=val -- set rpath values in libs/exes (default: no)
+    -C               save-temps=val -- save all temporary output files during compilation (default: no)
+    -C               soft-float=val -- use soft float ABI (*eabihf targets only) (default: no)
+    -C          split-debuginfo=val -- how to handle split-debuginfo, a platform-specific option
+    -C                    strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+    -C  symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+    -C               target-cpu=val -- select target processor (`rustc --print target-cpus` for details)
+    -C           target-feature=val -- target specific attributes. (`rustc --print target-features` for details). This feature is unsafe.
diff --git a/src/test/rustdoc-ui/z-help.rs b/src/test/rustdoc-ui/z-help.rs
new file mode 100644
index 0000000000000..c7cf841b93707
--- /dev/null
+++ b/src/test/rustdoc-ui/z-help.rs
@@ -0,0 +1,6 @@
+// check-pass
+// compile-flags: -Zhelp
+// check-stdout
+// regex-error-pattern: -Z\s+self-profile
+
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
new file mode 100644
index 0000000000000..5859cbb80540c
--- /dev/null
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -0,0 +1,193 @@
+    -Z                          allow-features=val -- only allow the listed language features to be enabled in code (space separated)
+    -Z                       always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
+    -Z               assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (default: no)
+    -Z                            asm-comments=val -- generate comments into the assembly (may change behavior) (default: no)
+    -Z                       assert-incr-state=val -- assert that the incremental cache is in given state: either `loaded` or `not-loaded`.
+    -Z                      binary-dep-depinfo=val -- include artifacts (sysroot, crate dependencies) used during compilation in dep-info (default: no)
+    -Z                       branch-protection=val -- set options for branch target identification and pointer authentication on AArch64
+    -Z                           cf-protection=val -- instrument control-flow architecture protection
+    -Z               cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use
+    -Z                                   chalk=val -- enable the experimental Chalk-based trait solving engine
+    -Z                         codegen-backend=val -- the backend to use
+    -Z                             combine-cgu=val -- combine CGUs into a single one
+    -Z                              crate-attr=val -- inject the given attribute in the crate
+    -Z                debug-info-for-profiling=val -- emit discriminators and other data necessary for AutoFDO
+    -Z                            debug-macros=val -- emit line numbers debug info inside macros (default: no)
+    -Z                 deduplicate-diagnostics=val -- deduplicate identical diagnostics (default: yes)
+    -Z                  dep-info-omit-d-target=val -- in dep-info output, omit targets for tracking dependencies of the dep-info files themselves (default: no)
+    -Z                               dep-tasks=val -- print tasks that execute and the color their dep node gets (requires debug build) (default: no)
+    -Z                                 dlltool=val -- import library generation tool (windows-gnu only)
+    -Z                 dont-buffer-diagnostics=val -- emit diagnostics rather than buffering (breaks NLL error downgrading, sorting) (default: no)
+    -Z                           drop-tracking=val -- enables drop tracking in generators (default: no)
+    -Z                        dual-proc-macros=val -- load proc macros for both target and host, but only link to the target (default: no)
+    -Z                          dump-dep-graph=val -- dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv) (default: no)
+    -Z                                dump-mir=val -- dump MIR state to file.
+        `val` is used to select which passes and functions to dump. For example:
+        `all` matches all passes and functions,
+        `foo` matches all passes for functions whose name contains 'foo',
+        `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
+        `foo | bar` all passes for function names containing 'foo' or 'bar'.
+    -Z                       dump-mir-dataflow=val -- in addition to `.mir` files, create graphviz `.dot` files with dataflow results (default: no)
+    -Z                            dump-mir-dir=val -- the directory the MIR is dumped into (default: `mir_dump`)
+    -Z            dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no)
+    -Z                       dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no)
+    -Z                       dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans.
+    -Z                        emit-stack-sizes=val -- emit a section containing stack size metadata (default: no)
+    -Z                             fewer-names=val -- reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR) (default: no)
+    -Z              force-unstable-if-unmarked=val -- force all crates to be `rustc_private` unstable (default: no)
+    -Z                                    fuel=val -- set the optimization fuel quota for a crate
+    -Z                       function-sections=val -- whether each function should go in its own section
+    -Z                    future-incompat-test=val -- forces all lints to be future incompatible, used for internal testing (default: no)
+    -Z                                  gcc-ld=val -- implementation of ld used by cc
+    -Z                      graphviz-dark-mode=val -- use dark-themed colors in graphviz output (default: no)
+    -Z                           graphviz-font=val -- use the given `fontname` in graphviz output; can be overridden by setting environment variable `RUSTC_GRAPHVIZ_FONT` (default: `Courier, monospace`)
+    -Z                               hir-stats=val -- print some statistics about AST and HIR (default: no)
+    -Z                human-readable-cgu-names=val -- generate human-readable, predictable names for codegen units (default: no)
+    -Z                        identify-regions=val -- display unnamed regions as `'<id>`, using a non-ident unique id (default: no)
+    -Z                incremental-ignore-spans=val -- ignore spans during ICH computation -- used for testing (default: no)
+    -Z                        incremental-info=val -- print high-level information about incremental reuse (or the lack thereof) (default: no)
+    -Z              incremental-relative-spans=val -- hash spans relative to their parent item for incr. comp. (default: no)
+    -Z                  incremental-verify-ich=val -- verify incr. comp. hashes of green query instances (default: no)
+    -Z                              inline-mir=val -- enable MIR inlining (default: no)
+    -Z                    inline-mir-threshold=val -- a default MIR inlining threshold (default: 50)
+    -Z               inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
+    -Z                      inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+    -Z                             input-stats=val -- gather statistics about the input (default: no)
+    -Z                     instrument-coverage=val -- instrument the generated code to support LLVM source-based code coverage reports (note, the compiler build config must include `profiler = true`); implies `-C symbol-mangling-version=v0`. Optional values are:
+        `=all` (implicit value)
+        `=except-unused-generics`
+        `=except-unused-functions`
+        `=off` (default)
+    -Z                       instrument-mcount=val -- insert function instrument code for mcount-based tracing (default: no)
+    -Z                       keep-hygiene-data=val -- keep hygiene data after analysis (default: no)
+    -Z                   link-native-libraries=val -- link native libraries in the linker invocation (default: yes)
+    -Z                               link-only=val -- link the `.rlink` file generated by `-Z no-link` (default: no)
+    -Z                            llvm-plugins=val -- a list LLVM plugins to enable (space separated)
+    -Z                         llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
+    -Z                         location-detail=val -- comma separated list of location details to be tracked when using caller_location valid options are `file`, `line`, and `column` (default: all)
+    -Z                                      ls=val -- list the symbols defined by a library crate (default: no)
+    -Z                         macro-backtrace=val -- show macro backtraces (default: no)
+    -Z                         merge-functions=val -- control the operation of the MergeFunctions LLVM pass, taking the same values as the target option of the same name
+    -Z                              meta-stats=val -- gather metadata statistics (default: no)
+    -Z                          mir-emit-retag=val -- emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 (default: no)
+    -Z                       mir-enable-passes=val -- use like `-Zmir-enable-passes=+DestProp,-InstCombine`. Forces the specified passes to be enabled, overriding all other checks. Passes that are not specified are enabled or disabled by other flags as usual.
+    -Z                           mir-opt-level=val -- MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)
+    -Z                         move-size-limit=val -- the size at which the `large_assignments` lint starts to be emitted
+    -Z                         mutable-noalias=val -- emit noalias metadata for mutable references (default: yes)
+    -Z                   new-llvm-pass-manager=val -- use new LLVM pass manager (default: no)
+    -Z                               nll-facts=val -- dump facts from NLL analysis into side files (default: no)
+    -Z                           nll-facts-dir=val -- the directory the NLL facts are dumped into (default: `nll-facts`)
+    -Z                             no-analysis=val -- parse and expand the source, but run no analysis
+    -Z                              no-codegen=val -- run all passes except codegen; no output
+    -Z              no-generate-arange-section=val -- omit DWARF address ranges that give faster lookups
+    -Z                     no-interleave-lints=val -- execute lints separately; allows benchmarking individual lints
+    -Z                           no-leak-check=val -- disable the 'leak check' for subtyping; unsound, but useful for tests
+    -Z                                 no-link=val -- compile without linking
+    -Z                        no-parallel-llvm=val -- run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)
+    -Z                 no-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
+    -Z                     no-profiler-runtime=val -- prevent automatic injection of the profiler_builtins crate
+    -Z                          normalize-docs=val -- normalize associated items in rustdoc when generating documentation
+    -Z                                     oom=val -- panic strategy for out-of-memory handling
+    -Z                  osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no)
+    -Z                        diagnostic-width=val -- set the current output width for diagnostic truncation
+    -Z                       panic-abort-tests=val -- support compiling tests with panic=abort (default: no)
+    -Z                           panic-in-drop=val -- panic strategy for panics in drops
+    -Z                              parse-only=val -- parse only; do not compile, assemble, or link (default: no)
+    -Z                              perf-stats=val -- print some performance-related statistics (default: no)
+    -Z pick-stable-methods-before-any-unstable=val -- try to pick stable methods first before picking any unstable methods (default: yes)
+    -Z                                     plt=val -- whether to use the PLT when calling into shared libraries;
+        only has effect for PIC code on systems with ELF binaries
+        (default: PLT is disabled if full relro is enabled)
+    -Z                                polonius=val -- enable polonius-based borrow-checker (default: no)
+    -Z                            polymorphize=val -- perform polymorphization analysis
+    -Z                            pre-link-arg=val -- a single extra argument to prepend the linker invocation (can be used several times)
+    -Z                           pre-link-args=val -- extra arguments to prepend to the linker invocation (space separated)
+    -Z           precise-enum-drop-elaboration=val -- use a more precise version of drop elaboration for matches on enums (default: yes). This results in better codegen, but has caused miscompilations on some tier 2 platforms. See #77382 and #74551.
+    -Z                              print-fuel=val -- make rustc print the total optimization fuel used by a crate
+    -Z                       print-llvm-passes=val -- print the LLVM optimization passes being run (default: no)
+    -Z                        print-mono-items=val -- print the result of the monomorphization collection pass
+    -Z                        print-type-sizes=val -- print layout information for each type encountered (default: no)
+    -Z                    proc-macro-backtrace=val -- show backtraces for panics during proc-macro execution (default: no)
+    -Z                                 profile=val -- insert profiling code (default: no)
+    -Z                        profile-closures=val -- profile size of closures
+    -Z                            profile-emit=val -- file path to emit profiling data at runtime when using 'profile' (default based on relative source path)
+    -Z                        profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
+    -Z                      profile-sample-use=val -- use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)
+    -Z                         query-dep-graph=val -- enable queries of the dependency graph for regression testing (default: no)
+    -Z                        randomize-layout=val -- randomize the layout of types (default: no)
+    -Z                             layout-seed=val -- seed layout randomization
+    -Z                   relax-elf-relocations=val -- whether ELF relocations can be relaxed
+    -Z                             relro-level=val -- choose which RELRO level to use
+    -Z                        remap-cwd-prefix=val -- remap paths under the current working directory to this path prefix
+    -Z         simulate-remapped-rust-src-base=val -- simulate the effect of remap-debuginfo = true at bootstrapping by remapping path to rust's source base directory. only meant for testing purposes
+    -Z                     report-delayed-bugs=val -- immediately print bugs registered with `delay_span_bug` (default: no)
+    -Z                               sanitizer=val -- use a sanitizer
+    -Z          sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
+    -Z                       sanitizer-recover=val -- enable recovery for selected sanitizers
+    -Z                  saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
+    -Z                           save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
+    -Z                            self-profile=val -- run the self profiler and output the raw event data
+    -Z                     self-profile-events=val -- specify the events recorded by the self profiler;
+        for example: `-Z self-profile-events=default,query-keys`
+        all options: none, all, default, generic-activity, query-provider, query-cache-hit
+                     query-blocked, incr-cache-load, incr-result-hashing, query-keys, function-args, args, llvm, artifact-sizes
+    -Z                    self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
+        `wall-time` (monotonic clock, i.e. `std::time::Instant`)
+        `instructions:u` (retired instructions, userspace-only)
+        `instructions-minus-irqs:u` (subtracting hardware interrupt counts for extra accuracy)
+    -Z                          share-generics=val -- make the current crate share its generic instantiations
+    -Z                               show-span=val -- show spans for compiler debugging (expr|pat|ty)
+    -Z                              span-debug=val -- forward proc_macro::Span's `Debug` impl to `Span`
+    -Z                       span-free-formats=val -- exclude spans when debug-printing compiler state (default: no)
+    -Z                      src-hash-algorithm=val -- hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)
+    -Z                         stack-protector=val -- control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)
+    -Z                      strict-init-checks=val -- control if mem::uninitialized and mem::zeroed panic on more UB
+    -Z                                   strip=val -- tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)
+    -Z                        split-dwarf-kind=val -- split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform)
+        (default: `split`)
+
+        `split`: sections which do not require relocation are written into a DWARF object (`.dwo`)
+                 file which is ignored by the linker
+        `single`: sections which do not require relocation are written into object file but ignored
+                  by the linker
+    -Z                    split-dwarf-inlining=val -- provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF
+    -Z                 symbol-mangling-version=val -- which mangling version to use for symbol names ('legacy' (default) or 'v0')
+    -Z                                   teach=val -- show extended diagnostic help (default: no)
+    -Z                               temps-dir=val -- the directory the intermediate files are written to
+    -Z                          translate-lang=val -- language identifier for diagnostic output
+    -Z                translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation)
+    -Z        translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics
+    -Z                                tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
+    -Z                                 thinlto=val -- enable ThinLTO when possible
+    -Z                           thir-unsafeck=val -- use the THIR unsafety checker (default: no)
+    -Z                                 threads=val -- use a thread pool with N threads
+    -Z                                    time=val -- measure time of rustc processes (default: no)
+    -Z                        time-llvm-passes=val -- measure time of each LLVM pass (default: no)
+    -Z                             time-passes=val -- measure time of each rustc pass (default: no)
+    -Z                               tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details)
+    -Z                            trace-macros=val -- for every macro invocation, print its name and arguments (default: no)
+    -Z   translate-remapped-path-to-local-path=val -- translate remapped paths into local paths when possible (default: yes)
+    -Z                        trap-unreachable=val -- generate trap instructions for unreachable intrinsics (default: use target setting, usually yes)
+    -Z                        treat-err-as-bug=val -- treat error number `val` that occurs as bug
+    -Z                   trim-diagnostic-paths=val -- in diagnostics, use heuristics to shorten paths referring to items
+    -Z                              ui-testing=val -- emit compiler diagnostics in a form suitable for UI testing (default: no)
+    -Z            uninit-const-chunk-threshold=val -- allow generating const initializers with mixed init/uninit chunks, and set the maximum number of chunks for which this is allowed (default: 16)
+    -Z          unleash-the-miri-inside-of-you=val -- take the brakes off const evaluation. NOTE: this is unsound (default: no)
+    -Z                                unpretty=val -- present the input source, unstable (and less-pretty) variants;
+        `normal`, `identified`,
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
+        `ast-tree` (raw AST before expansion),
+        `ast-tree,expanded` (raw AST after expansion),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)
+    -Z                        unsound-mir-opts=val -- enable unsound and buggy MIR optimizations (default: no)
+    -Z                        unstable-options=val -- adds unstable command line options to rustc interface (default: no)
+    -Z                       use-ctors-section=val -- use legacy .ctors section for initializers rather than .init_array
+    -Z                            validate-mir=val -- validate MIR after each transformation
+    -Z                                 verbose=val -- in general, enable more debug printouts (default: no)
+    -Z                          verify-llvm-ir=val -- verify LLVM IR (default: no)
+    -Z            virtual-function-elimination=val -- enables dead virtual function elimination optimization. Requires `-Clto[=[fat,yes]]`
+    -Z                         wasi-exec-model=val -- whether to build a wasi command or reactor

From 4944b5769bca72b51c0ceb04f6f68530c3209818 Mon Sep 17 00:00:00 2001
From: Jeron Aldaron Lau <aldaronlau@gmail.com>
Date: Sat, 9 Jul 2022 14:20:34 -0500
Subject: [PATCH 5/7] Remove extra space in AtomicPtr::new docs

---
 library/core/src/sync/atomic.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index b32dcfefacda8..f5eb1c8b9dcbd 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -991,7 +991,7 @@ impl<T> AtomicPtr<T> {
     /// use std::sync::atomic::AtomicPtr;
     ///
     /// let ptr = &mut 5;
-    /// let atomic_ptr  = AtomicPtr::new(ptr);
+    /// let atomic_ptr = AtomicPtr::new(ptr);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]

From d5aed20f4712010585532b4de51918bd66ac4797 Mon Sep 17 00:00:00 2001
From: rhysd <lin90162@yahoo.co.jp>
Date: Sun, 10 Jul 2022 02:48:53 +0900
Subject: [PATCH 6/7] Remove duplicate notes from error on inter-crate
 ambiguous impl of traits (fix #99092)

---
 .../src/traits/coherence.rs                   |  4 ++--
 .../src/traits/select/candidate_assembly.rs   |  2 +-
 .../src/traits/select/mod.rs                  | 14 +++++++-------
 .../src/traits/specialize/mod.rs              |  4 ++--
 ...oherence-projection-conflict-orphan.stderr |  1 -
 .../inter-crate-ambiguity-causes-notes.rs     | 19 +++++++++++++++++++
 .../inter-crate-ambiguity-causes-notes.stderr | 14 ++++++++++++++
 7 files changed, 45 insertions(+), 13 deletions(-)
 create mode 100644 src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs
 create mode 100644 src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index f933f1c3c94a7..52ca23c4b303e 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -13,7 +13,7 @@ use crate::traits::{
     self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation,
     PredicateObligations, SelectionContext,
 };
-//use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -44,7 +44,7 @@ pub enum Conflict {
 
 pub struct OverlapResult<'tcx> {
     pub impl_header: ty::ImplHeader<'tcx>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+    pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>,
 
     /// `true` if the overlap might've been permitted before the shift
     /// to universes.
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 21e14eae0ee27..96d83deeeb7ab 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -110,7 +110,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
                         };
                         debug!(?cause, "evaluate_stack: pushing cause");
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
                     }
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b205ca8fa1169..2bb53a466caa4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -24,7 +24,7 @@ use crate::traits::error_reporting::InferCtxtExt;
 use crate::traits::project::ProjectAndUnifyResult;
 use crate::traits::project::ProjectionCacheKeyExt;
 use crate::traits::ProjectionCacheKey;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -52,7 +52,7 @@ pub use rustc_middle::traits::select::*;
 mod candidate_assembly;
 mod confirmation;
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
 pub enum IntercrateAmbiguityCause {
     DownstreamCrate { trait_desc: String, self_desc: Option<String> },
     UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> },
@@ -128,7 +128,7 @@ pub struct SelectionContext<'cx, 'tcx> {
     /// We don't do his until we detect a coherence error because it can
     /// lead to false overflow results (#47139) and because always
     /// computing it may negatively impact performance.
-    intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
+    intercrate_ambiguity_causes: Option<FxIndexSet<IntercrateAmbiguityCause>>,
 
     /// The mode that trait queries run in, which informs our error handling
     /// policy. In essence, canonicalized queries need their errors propagated
@@ -254,14 +254,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
         assert!(self.intercrate);
         assert!(self.intercrate_ambiguity_causes.is_none());
-        self.intercrate_ambiguity_causes = Some(vec![]);
+        self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
         debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
     }
 
     /// Gets the intercrate ambiguity causes collected since tracking
     /// was enabled and disables tracking at the same time. If
     /// tracking is not enabled, just returns an empty vector.
-    pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
+    pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
         assert!(self.intercrate);
         self.intercrate_ambiguity_causes.take().unwrap_or_default()
     }
@@ -960,7 +960,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             });
 
                             debug!(?cause, "evaluate_stack: pushing cause");
-                            self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                            self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
                         }
                     }
                 }
@@ -1252,7 +1252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                  reservation impl ambiguity on {:?}",
                             def_id
                         );
-                        intercrate_ambiguity_clauses.push(
+                        intercrate_ambiguity_clauses.insert(
                             IntercrateAmbiguityCause::ReservationImpl {
                                 message: value.to_string(),
                             },
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index a80354897d618..fdd282d47a901 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -15,7 +15,7 @@ use specialization_graph::GraphExt;
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
@@ -33,7 +33,7 @@ pub struct OverlapError {
     pub with_impl: DefId,
     pub trait_desc: String,
     pub self_desc: Option<String>,
-    pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+    pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>,
     pub involves_placeholder: bool,
 }
 
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr
index 8e7d4589e6140..b1ee0795b2eb3 100644
--- a/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.stderr
@@ -8,7 +8,6 @@ LL | impl<A:Iterator> Foo<A::Item> for A { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
    |
    = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
-   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs
new file mode 100644
index 0000000000000..5b11c78ab2605
--- /dev/null
+++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.rs
@@ -0,0 +1,19 @@
+struct S;
+
+impl From<()> for S {
+    fn from(x: ()) -> Self {
+        S
+    }
+}
+
+impl<I> From<I> for S
+//~^ ERROR conflicting implementations of trait
+where
+    I: Iterator<Item = ()>,
+{
+    fn from(x: I) -> Self {
+        S
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
new file mode 100644
index 0000000000000..038a0199a8f27
--- /dev/null
+++ b/src/test/ui/coherence/inter-crate-ambiguity-causes-notes.stderr
@@ -0,0 +1,14 @@
+error[E0119]: conflicting implementations of trait `std::convert::From<()>` for type `S`
+  --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1
+   |
+LL | impl From<()> for S {
+   | ------------------- first implementation here
+...
+LL | impl<I> From<I> for S
+   | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S`
+   |
+   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0119`.

From 2f3624ccb6c7185306606098110dc91cdccc3b2e Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Sun, 10 Jul 2022 12:48:11 +0200
Subject: [PATCH 7/7] Group .test-arrow CSS rules and fix rgb/rgba property

---
 src/librustdoc/html/static/css/themes/dark.css  | 4 +---
 src/librustdoc/html/static/css/themes/light.css | 6 ++----
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index a678ec1e1c108..184d0e77a90b8 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -178,9 +178,6 @@ a {
 	color: #D2991D;
 }
 
-a.test-arrow {
-	color: #dedede;
-}
 body.source .example-wrap pre.rust a {
 	background: #333;
 }
@@ -255,6 +252,7 @@ pre.rust .question-mark {
 }
 
 a.test-arrow {
+	color: #dedede;
 	background-color: rgba(78, 139, 202, 0.2);
 }
 
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index e8770ac212426..c6ba13fe1d6fb 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -175,9 +175,6 @@ a {
 	color: #3873AD;
 }
 
-a.test-arrow {
-	color: #f5f5f5;
-}
 body.source .example-wrap pre.rust a {
 	background: #eee;
 }
@@ -239,7 +236,8 @@ pre.rust .question-mark {
 }
 
 a.test-arrow {
-	background-color: rgb(78, 139, 202, 0.2);
+	color: #f5f5f5;
+	background-color: rgba(78, 139, 202, 0.2);
 }
 
 a.test-arrow:hover{