From 6d2bd541e0066ba8ea429fb2e25a1d080e2e2d99 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 17 Jul 2022 10:56:12 -0700
Subject: [PATCH 01/14] use body's param-env when checking if type needs drop

---
 .../rustc_mir_build/src/check_unsafety.rs     |  4 ++--
 .../rustc_mir_transform/src/check_unsafety.rs |  7 ++-----
 src/test/ui/union/issue-99375.rs              | 21 +++++++++++++++++++
 3 files changed, 25 insertions(+), 7 deletions(-)
 create mode 100644 src/test/ui/union/issue-99375.rs

diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 89f60902cf9..1f0d0ce04aa 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -431,9 +431,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 let lhs = &self.thir[lhs];
                 if let ty::Adt(adt_def, _) = lhs.ty.kind() && adt_def.is_union() {
                     if let Some((assigned_ty, assignment_span)) = self.assignment_info {
-                        if assigned_ty.needs_drop(self.tcx, self.tcx.param_env(adt_def.did())) {
+                        if assigned_ty.needs_drop(self.tcx, self.param_env) {
                             // This would be unsafe, but should be outright impossible since we reject such unions.
-                            self.tcx.sess.delay_span_bug(assignment_span, "union fields that need dropping should be impossible");
+                            self.tcx.sess.delay_span_bug(assignment_span, format!("union fields that need dropping should be impossible: {assigned_ty}"));
                         }
                     } else {
                         self.requires_unsafe(expr.span, AccessToUnionField);
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index ded1f0462cb..a2ad96cfc16 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -219,14 +219,11 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
                     // We have to check the actual type of the assignment, as that determines if the
                     // old value is being dropped.
                     let assigned_ty = place.ty(&self.body.local_decls, self.tcx).ty;
-                    if assigned_ty.needs_drop(
-                        self.tcx,
-                        self.tcx.param_env(base_ty.ty_adt_def().unwrap().did()),
-                    ) {
+                    if assigned_ty.needs_drop(self.tcx, self.param_env) {
                         // This would be unsafe, but should be outright impossible since we reject such unions.
                         self.tcx.sess.delay_span_bug(
                             self.source_info.span,
-                            "union fields that need dropping should be impossible",
+                            format!("union fields that need dropping should be impossible: {assigned_ty}")
                         );
                     }
                 } else {
diff --git a/src/test/ui/union/issue-99375.rs b/src/test/ui/union/issue-99375.rs
new file mode 100644
index 00000000000..175018a7d71
--- /dev/null
+++ b/src/test/ui/union/issue-99375.rs
@@ -0,0 +1,21 @@
+// check-pass
+
+union URes<R: Copy> {
+    uninit: (),
+    init: R,
+}
+
+struct Params<F, R: Copy> {
+    function: F,
+    result: URes<R>,
+}
+
+unsafe extern "C" fn do_call<F, R>(params: *mut Params<F, R>)
+where
+    R: Copy,
+    F: Fn() -> R,
+{
+    (*params).result.init = ((*params).function)();
+}
+
+fn main() {}

From a22934bea1d02870cda58eb6297ff9332fcc2104 Mon Sep 17 00:00:00 2001
From: Takayuki Maeda <takoyaki0316@gmail.com>
Date: Mon, 18 Jul 2022 14:25:34 +0900
Subject: [PATCH 02/14] avoid `Symbol` to `&str` conversions

---
 compiler/rustc_ast_lowering/src/asm.rs        |  4 ++--
 compiler/rustc_ast_passes/src/feature_gate.rs |  4 ++--
 .../rustc_codegen_llvm/src/debuginfo/gdb.rs   |  2 +-
 .../nice_region_error/different_lifetimes.rs  |  2 +-
 compiler/rustc_passes/src/entry.rs            |  2 +-
 compiler/rustc_resolve/src/diagnostics.rs     |  2 +-
 .../rustc_resolve/src/late/diagnostics.rs     | 21 ++++++++++++-------
 compiler/rustc_resolve/src/macros.rs          |  4 ++--
 compiler/rustc_span/src/symbol.rs             |  1 +
 .../src/traits/error_reporting/mod.rs         |  4 ++--
 compiler/rustc_typeck/src/check/_match.rs     |  2 +-
 compiler/rustc_typeck/src/check/op.rs         |  3 +--
 12 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 0e395d70335..cd77dbca3c4 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -145,7 +145,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     InlineAsmRegOrRegClass::Reg(s) => {
                         asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
                             asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| {
-                                let msg = format!("invalid register `{}`: {}", s.as_str(), e);
+                                let msg = format!("invalid register `{}`: {}", s, e);
                                 sess.struct_span_err(*op_sp, &msg).emit();
                                 asm::InlineAsmReg::Err
                             })
@@ -156,7 +156,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     InlineAsmRegOrRegClass::RegClass(s) => {
                         asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
                             asm::InlineAsmRegClass::parse(asm_arch, s).unwrap_or_else(|e| {
-                                let msg = format!("invalid register class `{}`: {}", s.as_str(), e);
+                                let msg = format!("invalid register class `{}`: {}", s, e);
                                 sess.struct_span_err(*op_sp, &msg).emit();
                                 asm::InlineAsmRegClass::Err
                             })
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index fd2dd6cf6c7..d6b0ac158df 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -62,9 +62,9 @@ impl<'a> PostExpansionVisitor<'a> {
         let ast::StrLit { symbol_unescaped, span, .. } = abi;
 
         if let ast::Const::Yes(_) = constness {
-            match symbol_unescaped.as_str() {
+            match symbol_unescaped {
                 // Stable
-                "Rust" | "C" => {}
+                sym::Rust | sym::C => {}
                 abi => gate_feature_post!(
                     &self,
                     const_extern_fn,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 5186aee57fb..80fd9726fc7 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -55,7 +55,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '
             // The initial byte `4` instructs GDB that the following pretty printer
             // is defined inline as opposed to in a standalone file.
             section_contents.extend_from_slice(b"\x04");
-            let vis_name = format!("pretty-printer-{}-{}\n", crate_name.as_str(), index);
+            let vis_name = format!("pretty-printer-{}-{}\n", crate_name, index);
             section_contents.extend_from_slice(vis_name.as_bytes());
             section_contents.extend_from_slice(&visualizer.src);
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index b744594ddb7..9a2ab3e3224 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -228,7 +228,7 @@ pub fn suggest_adding_lifetime_params<'tcx>(
     if is_impl {
         sugg.push_str(" and update trait if needed");
     }
-    err.multipart_suggestion(sugg.as_str(), suggestions, Applicability::MaybeIncorrect);
+    err.multipart_suggestion(sugg, suggestions, Applicability::MaybeIncorrect);
 
     true
 }
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 1add91fc9c5..7381019a620 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -77,7 +77,7 @@ fn err_if_attr_found(ctxt: &EntryContext<'_>, attrs: &[Attribute], sym: Symbol)
             .sess
             .struct_span_err(
                 attr.span,
-                &format!("`{}` attribute can only be used on functions", sym.as_str()),
+                &format!("`{}` attribute can only be used on functions", sym),
             )
             .emit();
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 18ffe9528f5..cc3c74d4276 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1630,7 +1630,7 @@ impl<'a> Resolver<'a> {
                     "{}{} `{}` defined here",
                     prefix,
                     suggestion.res.descr(),
-                    suggestion.candidate.as_str(),
+                    suggestion.candidate,
                 ),
             );
         }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 03cb1cfcfc9..c82fd07035e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -80,7 +80,7 @@ impl ForLifetimeSpanType {
         }
     }
 
-    pub(crate) fn suggestion(&self, sugg: &str) -> String {
+    pub(crate) fn suggestion(&self, sugg: impl std::fmt::Display) -> String {
         match self {
             Self::BoundEmpty | Self::TypeEmpty => format!("for<{}> ", sugg),
             Self::BoundTail | Self::TypeTail => format!(", {}", sugg),
@@ -2311,8 +2311,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
 
         let suggest_existing =
             |err: &mut Diagnostic,
-             name: &str,
-             formatters: Vec<Option<Box<dyn Fn(&str) -> String>>>| {
+             name: Symbol,
+             formatters: Vec<Option<Box<dyn Fn(Symbol) -> String>>>| {
                 if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) =
                     self.missing_named_lifetime_spots.iter().rev().next()
                 {
@@ -2332,7 +2332,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     // If all single char lifetime names are present, we wrap around and double the chars.
                     let lt_name = (1..)
                         .flat_map(a_to_z_repeat_n)
-                        .find(|lt| !lifetime_names.contains(&Symbol::intern(&lt)))
+                        .map(|lt| Symbol::intern(&lt))
+                        .find(|lt| !lifetime_names.contains(lt))
                         .unwrap();
                     let msg = format!(
                         "consider making the {} lifetime-generic with a new `{}` lifetime",
@@ -2359,7 +2360,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     introduce_suggestion.push((*for_span, for_sugg));
                     for ((span, _), formatter) in spans_with_counts.iter().zip(formatters.iter()) {
                         if let Some(formatter) = formatter {
-                            introduce_suggestion.push((*span, formatter(&lt_name)));
+                            introduce_suggestion.push((*span, formatter(lt_name)));
                         }
                     }
                     err.multipart_suggestion_verbose(
@@ -2582,7 +2583,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         let lifetime_names: Vec<_> = lifetime_names.iter().collect();
         match &lifetime_names[..] {
             [name] => {
-                let mut suggs: Vec<Option<Box<dyn Fn(&str) -> String>>> = Vec::new();
+                let mut suggs: Vec<Option<Box<dyn Fn(Symbol) -> String>>> = Vec::new();
                 for (snippet, (_, count)) in snippets.iter().zip(spans_with_counts.iter().copied())
                 {
                     suggs.push(match snippet.as_deref() {
@@ -2590,7 +2591,11 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         Some("'_") => Some(Box::new(|n| n.to_string())),
                         Some("") => Some(Box::new(move |n| format!("{}, ", n).repeat(count))),
                         Some("<") => Some(Box::new(move |n| {
-                            std::iter::repeat(n).take(count).collect::<Vec<_>>().join(", ")
+                            std::iter::repeat(n)
+                                .take(count)
+                                .map(|n| n.to_string())
+                                .collect::<Vec<_>>()
+                                .join(", ")
                         })),
                         Some(snippet) if !snippet.ends_with('>') => Some(Box::new(move |name| {
                             format!(
@@ -2605,7 +2610,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         _ => None,
                     });
                 }
-                suggest_existing(err, name.as_str(), suggs);
+                suggest_existing(err, **name, suggs);
             }
             [] => {
                 let mut suggs = Vec::new();
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 4210560f531..54dd15270a1 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -325,7 +325,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
                 UNUSED_MACROS,
                 node_id,
                 ident.span,
-                &format!("unused macro definition: `{}`", ident.as_str()),
+                &format!("unused macro definition: `{}`", ident.name),
             );
         }
         for (&(def_id, arm_i), &(ident, rule_span)) in self.unused_macro_rules.iter() {
@@ -341,7 +341,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
                 &format!(
                     "{} rule of macro `{}` is never used",
                     crate::diagnostics::ordinalize(arm_i + 1),
-                    ident.as_str()
+                    ident.name
                 ),
             );
         }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9b6967621f1..5e26809142d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -257,6 +257,7 @@ symbols! {
         Result,
         Return,
         Right,
+        Rust,
         RustcDecodable,
         RustcEncodable,
         Send,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index aa1c9136289..5dcd6e585e8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -474,7 +474,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         if let Some(ref s) = label {
                             // If it has a custom `#[rustc_on_unimplemented]`
                             // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
+                            err.span_label(span, s);
                             if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
                                 // When the self type is a type param We don't need to "the trait
                                 // `std::marker::Sized` is not implemented for `T`" as we will point
@@ -531,7 +531,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             let enclosing_scope_span =
                                 tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(body));
 
-                            err.span_label(enclosing_scope_span, s.as_str());
+                            err.span_label(enclosing_scope_span, s);
                         }
 
                         self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref);
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs
index deaadf0e5c8..09808ce0dda 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_typeck/src/check/_match.rs
@@ -259,7 +259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             &cause,
             &mut |err| {
                 if let Some((span, msg)) = &ret_reason {
-                    err.span_label(*span, msg.as_str());
+                    err.span_label(*span, msg);
                 } else if let ExprKind::Block(block, _) = &then_expr.kind
                     && let Some(expr) = &block.expr
                 {
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index 42893789957..b054d94aa33 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -395,8 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 false,
                             ),
                         };
-                        let mut err =
-                            struct_span_err!(self.tcx.sess, op.span, E0369, "{}", message.as_str());
+                        let mut err = struct_span_err!(self.tcx.sess, op.span, E0369, "{message}");
                         if !lhs_expr.span.eq(&rhs_expr.span) {
                             self.add_type_neq_err_label(
                                 &mut err,

From 454313fe83dc27df2508cbd82e6f2a2221d7f8d3 Mon Sep 17 00:00:00 2001
From: Yoshua Wuyts <2467194+yoshuawuyts@users.noreply.github.com>
Date: Mon, 18 Jul 2022 16:04:52 +0200
Subject: [PATCH 03/14] stabilize `core::task::ready!`

---
 library/core/src/task/mod.rs   | 2 +-
 library/core/src/task/ready.rs | 5 +----
 2 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index 71a67a2793a..c5f89b9a2c6 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -11,7 +11,7 @@ mod wake;
 pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
 
 mod ready;
-#[unstable(feature = "ready_macro", issue = "70922")]
+#[stable(feature = "ready_macro", since = "1.64.0")]
 pub use ready::ready;
 #[unstable(feature = "poll_ready", issue = "89780")]
 pub use ready::Ready;
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index 174ca675460..b1daf545fbe 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -13,8 +13,6 @@ use core::task::Poll;
 /// # Examples
 ///
 /// ```
-/// #![feature(ready_macro)]
-///
 /// use std::task::{ready, Context, Poll};
 /// use std::future::{self, Future};
 /// use std::pin::Pin;
@@ -34,7 +32,6 @@ use core::task::Poll;
 /// The `ready!` call expands to:
 ///
 /// ```
-/// # #![feature(ready_macro)]
 /// # use std::task::{Context, Poll};
 /// # use std::future::{self, Future};
 /// # use std::pin::Pin;
@@ -53,7 +50,7 @@ use core::task::Poll;
 ///     # Poll::Ready(())
 /// # }
 /// ```
-#[unstable(feature = "ready_macro", issue = "70922")]
+#[stable(feature = "ready_macro", since = "1.64.0")]
 #[rustc_macro_transparency = "semitransparent"]
 pub macro ready($e:expr) {
     match $e {

From 37c21d6fc714748bb41bb1b9a53152632849a3f3 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Mon, 18 Jul 2022 21:55:47 +0400
Subject: [PATCH 04/14] Do not suggest "wrapping the expression in
 `std::num::NonZeroU64`"

---
 compiler/rustc_typeck/src/check/demand.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 740261cfe74..867570b42da 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -19,6 +19,7 @@ use rustc_span::{BytePos, Span};
 use super::method::probe;
 
 use std::iter;
+use std::ops::Bound;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -347,6 +348,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
 
+            // Avoid suggesting wrapping in `NonZeroU64` and alike
+            if self.tcx.layout_scalar_valid_range(expected_adt.did())
+                != (Bound::Unbounded, Bound::Unbounded)
+            {
+                return;
+            }
+
             let compatible_variants: Vec<String> = expected_adt
                 .variants()
                 .iter()

From c0569f2aa7311d295cb273f66fbe365f2b5ad893 Mon Sep 17 00:00:00 2001
From: Christopher Durham <cad97@cad97.com>
Date: Mon, 18 Jul 2022 15:22:01 -0400
Subject: [PATCH 05/14] Revert "Stabilize $$ in Rust 1.63.0"

This reverts commit 9edaa76adce4de737db54194eb13d6c298827b37.
---
 compiler/rustc_expand/src/mbe/quoted.rs       |  2 +
 .../rfc-3086-metavar-expr/allowed-features.rs | 12 -----
 ...quired-features.rs => required-feature.rs} | 12 +++++
 ...eatures.stderr => required-feature.stderr} | 50 ++++++++++++++++---
 4 files changed, 57 insertions(+), 19 deletions(-)
 delete mode 100644 src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs
 rename src/test/ui/macros/rfc-3086-metavar-expr/{required-features.rs => required-feature.rs} (65%)
 rename src/test/ui/macros/rfc-3086-metavar-expr/{required-features.stderr => required-feature.stderr} (52%)

diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index d4b8563a036..707cb73f097 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -234,6 +234,8 @@ fn parse_tree(
                             sess,
                             &Token { kind: token::Dollar, span },
                         );
+                    } else {
+                        maybe_emit_macro_metavar_expr_feature(features, sess, span);
                     }
                     TokenTree::token(token::Dollar, span)
                 }
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs b/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs
deleted file mode 100644
index c248c46f52c..00000000000
--- a/src/test/ui/macros/rfc-3086-metavar-expr/allowed-features.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// check-pass
-
-macro_rules! dollar_dollar {
-    () => {
-        macro_rules! bar {
-            ( $$( $$any:tt )* ) => { $$( $$any )* };
-        }
-    };
-}
-
-fn main() {
-}
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
similarity index 65%
rename from src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs
rename to src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
index cce3e578aea..b4fef11f1e2 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.rs
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.rs
@@ -5,6 +5,18 @@ macro_rules! count {
     };
 }
 
+macro_rules! dollar_dollar {
+    () => {
+        macro_rules! bar {
+            ( $$( $$any:tt )* ) => { $$( $$any )* };
+            //~^ ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+            //~| ERROR meta-variable expressions are unstable
+        }
+    };
+}
+
 macro_rules! index {
     ( $( $e:stmt ),* ) => {
         $( ${ignore(e)} ${index()} )*
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
similarity index 52%
rename from src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr
rename to src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
index 5efd3b10442..ecf598b104d 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/required-features.stderr
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/required-feature.stderr
@@ -1,5 +1,5 @@
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:3:10
+  --> $DIR/required-feature.rs:3:10
    |
 LL |         ${ count(e) }
    |          ^^^^^^^^^^^^
@@ -8,7 +8,43 @@ LL |         ${ count(e) }
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:10:13
+  --> $DIR/required-feature.rs:11:16
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:20
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                    ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:39
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                                       ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:11:43
+   |
+LL |             ( $$( $$any:tt )* ) => { $$( $$any )* };
+   |                                           ^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
+
+error[E0658]: meta-variable expressions are unstable
+  --> $DIR/required-feature.rs:22:13
    |
 LL |         $( ${ignore(e)} ${index()} )*
    |             ^^^^^^^^^^^
@@ -17,7 +53,7 @@ LL |         $( ${ignore(e)} ${index()} )*
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:10:26
+  --> $DIR/required-feature.rs:22:26
    |
 LL |         $( ${ignore(e)} ${index()} )*
    |                          ^^^^^^^^^
@@ -26,7 +62,7 @@ LL |         $( ${ignore(e)} ${index()} )*
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:18:19
+  --> $DIR/required-feature.rs:30:19
    |
 LL |         0 $( + 1 ${ignore(i)} )*
    |                   ^^^^^^^^^^^
@@ -35,7 +71,7 @@ LL |         0 $( + 1 ${ignore(i)} )*
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:25:13
+  --> $DIR/required-feature.rs:37:13
    |
 LL |         $( ${ignore(e)} ${length()} )*
    |             ^^^^^^^^^^^
@@ -44,7 +80,7 @@ LL |         $( ${ignore(e)} ${length()} )*
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
 error[E0658]: meta-variable expressions are unstable
-  --> $DIR/required-features.rs:25:26
+  --> $DIR/required-feature.rs:37:26
    |
 LL |         $( ${ignore(e)} ${length()} )*
    |                          ^^^^^^^^^^
@@ -52,6 +88,6 @@ LL |         $( ${ignore(e)} ${length()} )*
    = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
    = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable
 
-error: aborting due to 6 previous errors
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0658`.

From 7163e7ff6542b200971a783dc2a720a0ff676e70 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Tue, 19 Jul 2022 00:11:21 +0400
Subject: [PATCH 06/14] Suggest a fix for `NonZero*` <- `*` coercion error

---
 compiler/rustc_span/src/symbol.rs             | 10 ++++
 compiler/rustc_typeck/src/check/demand.rs     | 54 +++++++++++++++++++
 library/core/src/num/nonzero.rs               |  1 +
 .../non_zero_assigned_something.rs            |  9 ++++
 .../non_zero_assigned_something.stderr        | 31 +++++++++++
 5 files changed, 105 insertions(+)
 create mode 100644 src/test/ui/mismatched_types/non_zero_assigned_something.rs
 create mode 100644 src/test/ui/mismatched_types/non_zero_assigned_something.stderr

diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d5e65c0b442..6ddcfbb05dc 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -223,6 +223,16 @@ symbols! {
         LintPass,
         Mutex,
         N,
+        NonZeroI128,
+        NonZeroI16,
+        NonZeroI32,
+        NonZeroI64,
+        NonZeroI8,
+        NonZeroU128,
+        NonZeroU16,
+        NonZeroU32,
+        NonZeroU64,
+        NonZeroU8,
         None,
         Ok,
         Option,
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 867570b42da..31da5cfe7fa 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.annotate_expected_due_to_let_ty(err, expr, error);
         self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
         self.suggest_compatible_variants(err, expr, expected, expr_ty);
+        self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty);
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
             return;
         }
@@ -418,6 +419,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn suggest_non_zero_new_unwrap(
+        &self,
+        err: &mut Diagnostic,
+        expr: &hir::Expr<'_>,
+        expected: Ty<'tcx>,
+        expr_ty: Ty<'tcx>,
+    ) {
+        let tcx = self.tcx;
+        let (adt, unwrap) = match expected.kind() {
+            // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
+            ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
+                // Unwrap option
+                let Some(fst) = substs.first() else { return };
+                let ty::Adt(adt, _) = fst.expect_ty().kind() else { return };
+
+                (adt, "")
+            }
+            // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
+            ty::Adt(adt, _) => (adt, ".unwrap()"),
+            _ => return,
+        };
+
+        let map = [
+            (sym::NonZeroU8, tcx.types.u8),
+            (sym::NonZeroU16, tcx.types.u16),
+            (sym::NonZeroU32, tcx.types.u32),
+            (sym::NonZeroU64, tcx.types.u64),
+            (sym::NonZeroU128, tcx.types.u128),
+            (sym::NonZeroI8, tcx.types.i8),
+            (sym::NonZeroI16, tcx.types.i16),
+            (sym::NonZeroI32, tcx.types.i32),
+            (sym::NonZeroI64, tcx.types.i64),
+            (sym::NonZeroI128, tcx.types.i128),
+        ];
+
+        let Some((s, _)) = map
+            .iter()
+            .find(|&&(s, _)| self.tcx.is_diagnostic_item(s, adt.did()))
+            .filter(|&&(_, t)| { self.can_coerce(expr_ty, t) })
+            else { return };
+
+        let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
+
+        err.multipart_suggestion(
+            format!("consider calling `{s}::new`"),
+            vec![
+                (expr.span.shrink_to_lo(), format!("{path}::new(")),
+                (expr.span.shrink_to_hi(), format!("){unwrap}")),
+            ],
+            Applicability::MaybeIncorrect,
+        );
+    }
+
     pub fn get_conversion_methods(
         &self,
         span: Span,
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 92d03b724b4..4de0a0cf564 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -39,6 +39,7 @@ macro_rules! nonzero_integers {
             #[repr(transparent)]
             #[rustc_layout_scalar_valid_range_start(1)]
             #[rustc_nonnull_optimization_guaranteed]
+            #[rustc_diagnostic_item = stringify!($Ty)]
             pub struct $Ty($Int);
 
             impl $Ty {
diff --git a/src/test/ui/mismatched_types/non_zero_assigned_something.rs b/src/test/ui/mismatched_types/non_zero_assigned_something.rs
new file mode 100644
index 00000000000..d2adbe01c18
--- /dev/null
+++ b/src/test/ui/mismatched_types/non_zero_assigned_something.rs
@@ -0,0 +1,9 @@
+fn main() {
+    let _: std::num::NonZeroU64 = 1;
+    //~^ ERROR mismatched types
+    //~| HELP  consider calling `NonZeroU64::new`
+
+    let _: Option<std::num::NonZeroU64> = 1;
+    //~^ ERROR mismatched types
+    //~| HELP  consider calling `NonZeroU64::new`
+}
diff --git a/src/test/ui/mismatched_types/non_zero_assigned_something.stderr b/src/test/ui/mismatched_types/non_zero_assigned_something.stderr
new file mode 100644
index 00000000000..d4b2c902f9b
--- /dev/null
+++ b/src/test/ui/mismatched_types/non_zero_assigned_something.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/non_zero_assigned_something.rs:2:35
+   |
+LL |     let _: std::num::NonZeroU64 = 1;
+   |            --------------------   ^ expected struct `NonZeroU64`, found integer
+   |            |
+   |            expected due to this
+   |
+help: consider calling `NonZeroU64::new`
+   |
+LL |     let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap();
+   |                                   ++++++++++++++++ ++++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/non_zero_assigned_something.rs:6:43
+   |
+LL |     let _: Option<std::num::NonZeroU64> = 1;
+   |            ----------------------------   ^ expected enum `Option`, found integer
+   |            |
+   |            expected due to this
+   |
+   = note: expected enum `Option<NonZeroU64>`
+              found type `{integer}`
+help: consider calling `NonZeroU64::new`
+   |
+LL |     let _: Option<std::num::NonZeroU64> = NonZeroU64::new(1);
+   |                                           ++++++++++++++++ +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.

From da2752e00f0139fb13282b2bd97aa0f8c665aee9 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Tue, 19 Jul 2022 01:16:25 +0400
Subject: [PATCH 07/14] check accessibility before suggesting wrapping
 expressions

---
 compiler/rustc_typeck/src/check/demand.rs     | 18 +++---
 .../wrap-suggestion-privacy.rs                | 24 ++++++++
 .../wrap-suggestion-privacy.stderr            | 59 +++++++++++++++++++
 3 files changed, 93 insertions(+), 8 deletions(-)
 create mode 100644 src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
 create mode 100644 src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr

diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 31da5cfe7fa..30d7cc2e5fc 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -19,7 +19,6 @@ use rustc_span::{BytePos, Span};
 use super::method::probe;
 
 use std::iter;
-use std::ops::Bound;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -349,13 +348,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
 
-            // Avoid suggesting wrapping in `NonZeroU64` and alike
-            if self.tcx.layout_scalar_valid_range(expected_adt.did())
-                != (Bound::Unbounded, Bound::Unbounded)
-            {
-                return;
-            }
-
             let compatible_variants: Vec<String> = expected_adt
                 .variants()
                 .iter()
@@ -364,6 +356,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 })
                 .filter_map(|variant| {
                     let sole_field = &variant.fields[0];
+
+                    if !sole_field.did.is_local()
+                        && !sole_field.vis.is_accessible_from(
+                            self.tcx.parent_module(expr.hir_id).to_def_id(),
+                            self.tcx,
+                        )
+                    {
+                        return None;
+                    }
+
                     let sole_field_ty = sole_field.ty(self.tcx, substs);
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
new file mode 100644
index 00000000000..63cb1a12991
--- /dev/null
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.rs
@@ -0,0 +1,24 @@
+mod inner {
+    pub struct Wrapper<T>(T);
+}
+
+fn needs_wrapper(t: inner::Wrapper<i32>) {}
+fn needs_wrapping(t: std::num::Wrapping<i32>) {}
+fn needs_ready(t: std::future::Ready<i32>) {}
+
+fn main() {
+    // Suggest wrapping expression because type is local
+    // and its privacy can be easily changed
+    needs_wrapper(0);
+    //~^ ERROR mismatched types
+    //~| HELP  try wrapping the expression in `inner::Wrapper`
+
+    // Suggest wrapping expression because field is accessible
+    needs_wrapping(0);
+    //~^ ERROR mismatched types
+    //~| HELP  try wrapping the expression in `std::num::Wrapping`
+
+    // Do not suggest wrapping expression
+    needs_ready(Some(0));
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
new file mode 100644
index 00000000000..536638632de
--- /dev/null
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:12:19
+   |
+LL |     needs_wrapper(0);
+   |     ------------- ^ expected struct `Wrapper`, found integer
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Wrapper<i32>`
+                found type `{integer}`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:5:4
+   |
+LL | fn needs_wrapper(t: inner::Wrapper<i32>) {}
+   |    ^^^^^^^^^^^^^ ----------------------
+help: try wrapping the expression in `inner::Wrapper`
+   |
+LL |     needs_wrapper(inner::Wrapper(0));
+   |                   +++++++++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:17:20
+   |
+LL |     needs_wrapping(0);
+   |     -------------- ^ expected struct `Wrapping`, found integer
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Wrapping<i32>`
+                found type `{integer}`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:6:4
+   |
+LL | fn needs_wrapping(t: std::num::Wrapping<i32>) {}
+   |    ^^^^^^^^^^^^^^ --------------------------
+help: try wrapping the expression in `std::num::Wrapping`
+   |
+LL |     needs_wrapping(std::num::Wrapping(0));
+   |                    +++++++++++++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/wrap-suggestion-privacy.rs:22:17
+   |
+LL |     needs_ready(Some(0));
+   |     ----------- ^^^^^^^ expected struct `std::future::Ready`, found enum `Option`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `std::future::Ready<i32>`
+                found enum `Option<{integer}>`
+note: function defined here
+  --> $DIR/wrap-suggestion-privacy.rs:7:4
+   |
+LL | fn needs_ready(t: std::future::Ready<i32>) {}
+   |    ^^^^^^^^^^^ --------------------------
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.

From 821e9d56ae14a27048e1e60a4fd75376a0839829 Mon Sep 17 00:00:00 2001
From: Eric Huss <eric@huss.org>
Date: Mon, 18 Jul 2022 14:41:10 -0700
Subject: [PATCH 08/14] Update mdbook

---
 Cargo.lock | 45 +++++++--------------------------------------
 1 file changed, 7 insertions(+), 38 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 3a0bff2ee4d..db8e3d5adbb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -634,7 +634,7 @@ version = "3.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
 dependencies = [
- "heck 0.4.0",
+ "heck",
  "proc-macro-error",
  "proc-macro2",
  "quote",
@@ -1202,17 +1202,14 @@ checksum = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
 
 [[package]]
 name = "elasticlunr-rs"
-version = "2.3.9"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35622eb004c8f0c5e7e2032815f3314a93df0db30a1ce5c94e62c1ecc81e22b9"
+checksum = "e6dae5cac90640734ee881bc5f21b6e5123f4e5235e52428db114abffc2391d6"
 dependencies = [
- "lazy_static",
  "regex",
  "serde",
  "serde_derive",
  "serde_json",
- "strum",
- "strum_macros",
 ]
 
 [[package]]
@@ -1735,15 +1732,6 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
-[[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
 [[package]]
 name = "heck"
 version = "0.4.0"
@@ -2360,9 +2348,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.18"
+version = "0.4.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74612ae81a3e5ee509854049dfa4c7975ae033c06f5fc4735c7dfbe60ee2a39d"
+checksum = "13cdad8057b09a519c6c63e6d7c93ea854f5d7fbfe284df864d5e1140d215a2d"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -2370,7 +2358,7 @@ dependencies = [
  "clap",
  "clap_complete",
  "elasticlunr-rs",
- "env_logger 0.7.1",
+ "env_logger 0.9.0",
  "handlebars",
  "lazy_static",
  "log",
@@ -2379,7 +2367,6 @@ dependencies = [
  "pulldown-cmark",
  "regex",
  "serde",
- "serde_derive",
  "serde_json",
  "shlex",
  "tempfile",
@@ -3335,7 +3322,7 @@ dependencies = [
  "difference",
  "env_logger 0.9.0",
  "futures 0.3.19",
- "heck 0.4.0",
+ "heck",
  "home",
  "itertools",
  "jsonrpc-core",
@@ -5134,24 +5121,6 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
-[[package]]
-name = "strum"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
-
-[[package]]
-name = "strum_macros"
-version = "0.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
-dependencies = [
- "heck 0.3.1",
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "syn"
 version = "1.0.91"

From 2edad7d77c91145b594ac80c3dc7906998b7674a Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Tue, 19 Jul 2022 02:15:56 +0400
Subject: [PATCH 09/14] Apply suggestions from the review

- Use `expr.hir_id.owner` instead of `self.tcx.parent_module(expr.hir_id)`
- Use `.type_at()` instead of `.first()` + `.expect_ty()`
- Use single `.find()` with `&&` condition

Co-authored-by: Michael Goulet <michael@errs.io>
---
 compiler/rustc_typeck/src/check/demand.rs | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 30d7cc2e5fc..e5f8b6b5f1e 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -358,10 +358,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let sole_field = &variant.fields[0];
 
                     if !sole_field.did.is_local()
-                        && !sole_field.vis.is_accessible_from(
-                            self.tcx.parent_module(expr.hir_id).to_def_id(),
-                            self.tcx,
-                        )
+                        && !sole_field
+                            .vis
+                            .is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx)
                     {
                         return None;
                     }
@@ -433,8 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
             ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
                 // Unwrap option
-                let Some(fst) = substs.first() else { return };
-                let ty::Adt(adt, _) = fst.expect_ty().kind() else { return };
+                let ty::Adt(adt, _) = substs.type_at(0).kind() else { return };
 
                 (adt, "")
             }
@@ -458,8 +456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let Some((s, _)) = map
             .iter()
-            .find(|&&(s, _)| self.tcx.is_diagnostic_item(s, adt.did()))
-            .filter(|&&(_, t)| { self.can_coerce(expr_ty, t) })
+            .find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t))
             else { return };
 
         let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);

From 5bd88dfa8a0b5d5bcdd84d21e2f465719ce8c328 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Tue, 19 Jul 2022 02:33:36 +0400
Subject: [PATCH 10/14] Add a note about privacy to wrapping suggestion

---
 compiler/rustc_typeck/src/check/demand.rs     | 28 +++++++++++--------
 .../wrap-suggestion-privacy.stderr            |  2 +-
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index e5f8b6b5f1e..a2d8765289c 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -348,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
 
-            let compatible_variants: Vec<String> = expected_adt
+            let compatible_variants: Vec<(String, Option<String>)> = expected_adt
                 .variants()
                 .iter()
                 .filter(|variant| {
@@ -357,14 +357,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .filter_map(|variant| {
                     let sole_field = &variant.fields[0];
 
-                    if !sole_field.did.is_local()
-                        && !sole_field
-                            .vis
-                            .is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx)
-                    {
+                    let field_is_local = sole_field.did.is_local();
+                    let field_is_accessible =
+                        sole_field.vis.is_accessible_from(expr.hir_id.owner.to_def_id(), self.tcx);
+
+                    if !field_is_local && !field_is_accessible {
                         return None;
                     }
 
+                    let note_about_variant_field_privacy = (field_is_local && !field_is_accessible)
+                        .then(|| format!(" (its field is private, but it's local to this crate and its privacy can be changed)"));
+
                     let sole_field_ty = sole_field.ty(self.tcx, substs);
                     if self.can_coerce(expr_ty, sole_field_ty) {
                         let variant_path =
@@ -373,9 +376,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if let Some(path) = variant_path.strip_prefix("std::prelude::")
                             && let Some((_, path)) = path.split_once("::")
                         {
-                            return Some(path.to_string());
+                            return Some((path.to_string(), note_about_variant_field_privacy));
                         }
-                        Some(variant_path)
+                        Some((variant_path, note_about_variant_field_privacy))
                     } else {
                         None
                     }
@@ -389,10 +392,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             match &compatible_variants[..] {
                 [] => { /* No variants to format */ }
-                [variant] => {
+                [(variant, note)] => {
                     // Just a single matching variant.
                     err.multipart_suggestion_verbose(
-                        &format!("try wrapping the expression in `{variant}`"),
+                        &format!(
+                            "try wrapping the expression in `{variant}`{note}",
+                            note = note.as_deref().unwrap_or("")
+                        ),
                         vec![
                             (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
                             (expr.span.shrink_to_hi(), ")".to_string()),
@@ -407,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             "try wrapping the expression in a variant of `{}`",
                             self.tcx.def_path_str(expected_adt.did())
                         ),
-                        compatible_variants.into_iter().map(|variant| {
+                        compatible_variants.into_iter().map(|(variant, _)| {
                             vec![
                                 (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")),
                                 (expr.span.shrink_to_hi(), ")".to_string()),
diff --git a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
index 536638632de..e8eb8d263ec 100644
--- a/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
+++ b/src/test/ui/mismatched_types/wrap-suggestion-privacy.stderr
@@ -13,7 +13,7 @@ note: function defined here
    |
 LL | fn needs_wrapper(t: inner::Wrapper<i32>) {}
    |    ^^^^^^^^^^^^^ ----------------------
-help: try wrapping the expression in `inner::Wrapper`
+help: try wrapping the expression in `inner::Wrapper` (its field is private, but it's local to this crate and its privacy can be changed)
    |
 LL |     needs_wrapper(inner::Wrapper(0));
    |                   +++++++++++++++ +

From 959c215001378f770b2a5faa058f591d2d5f9081 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= <lnicola@dend.ro>
Date: Tue, 19 Jul 2022 10:16:45 +0300
Subject: [PATCH 11/14] :arrow_up: rust-analyzer

---
 src/tools/rust-analyzer | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
index 5342f47f427..897a7ec4b82 160000
--- a/src/tools/rust-analyzer
+++ b/src/tools/rust-analyzer
@@ -1 +1 @@
-Subproject commit 5342f47f4276641ddb5f0a5e08fb307742d6cdc4
+Subproject commit 897a7ec4b826f85ec1626870e734490701138097

From 1cbacc0c8aa3c4d99a073108d4ec7a535ff79102 Mon Sep 17 00:00:00 2001
From: aticu <15schnic@gmail.com>
Date: Sun, 12 Jun 2022 17:46:57 +0200
Subject: [PATCH 12/14] Add E0790 as more specific variant of E0283

---
 compiler/rustc_error_codes/src/error_codes.rs |  1 +
 .../src/error_codes/E0283.md                  | 41 +++------
 .../src/error_codes/E0790.md                  | 51 ++++++++++
 compiler/rustc_middle/src/ty/trait_def.rs     |  4 +
 .../src/traits/error_reporting/mod.rs         | 92 +++++++++++++++++++
 src/test/ui/associated-consts/issue-63496.rs  |  4 +-
 .../ui/associated-consts/issue-63496.stderr   | 28 +++---
 src/test/ui/associated-item/issue-48027.rs    |  2 +-
 .../ui/associated-item/issue-48027.stderr     | 14 +--
 .../associated-types-unconstrained.rs         |  2 +-
 .../associated-types-unconstrained.stderr     | 11 ++-
 src/test/ui/error-codes/E0283.rs              |  2 +-
 src/test/ui/error-codes/E0283.stderr          | 15 ++-
 src/test/ui/error-codes/E0790.rs              | 53 +++++++++++
 src/test/ui/error-codes/E0790.stderr          | 73 +++++++++++++++
 src/test/ui/issues/issue-54954.rs             |  2 +-
 src/test/ui/issues/issue-54954.stderr         | 16 ++--
 src/test/ui/issues/issue-58022.rs             |  2 +-
 src/test/ui/issues/issue-58022.stderr         | 17 ++--
 .../traits/static-method-generic-inference.rs |  2 +-
 .../static-method-generic-inference.stderr    | 14 ++-
 21 files changed, 354 insertions(+), 92 deletions(-)
 create mode 100644 compiler/rustc_error_codes/src/error_codes/E0790.md
 create mode 100644 src/test/ui/error-codes/E0790.rs
 create mode 100644 src/test/ui/error-codes/E0790.stderr

diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 977318b8589..97766b8368a 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -492,6 +492,7 @@ E0785: include_str!("./error_codes/E0785.md"),
 E0786: include_str!("./error_codes/E0786.md"),
 E0787: include_str!("./error_codes/E0787.md"),
 E0788: include_str!("./error_codes/E0788.md"),
+E0790: include_str!("./error_codes/E0790.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md
index 6885f9a486d..e5a3179aabf 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0283.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0283.md
@@ -3,48 +3,31 @@ An implementation cannot be chosen unambiguously because of lack of information.
 Erroneous code example:
 
 ```compile_fail,E0283
-trait Generator {
-    fn create() -> u32;
-}
+struct Foo;
 
-struct Impl;
-
-impl Generator for Impl {
-    fn create() -> u32 { 1 }
-}
-
-struct AnotherImpl;
-
-impl Generator for AnotherImpl {
-    fn create() -> u32 { 2 }
+impl Into<u32> for Foo {
+    fn into(self) -> u32 { 1 }
 }
 
 fn main() {
-    let cont: u32 = Generator::create();
-    // error, impossible to choose one of Generator trait implementation
-    // Should it be Impl or AnotherImpl, maybe something else?
+    let foo = Foo;
+    let bar: u32 = foo.into() * 1u32;
 }
 ```
 
 This error can be solved by adding type annotations that provide the missing
-information to the compiler. In this case, the solution is to use a concrete
-type:
+information to the compiler. In this case, the solution is to specify the
+fully-qualified method:
 
 ```
-trait Generator {
-    fn create() -> u32;
-}
+struct Foo;
 
-struct AnotherImpl;
-
-impl Generator for AnotherImpl {
-    fn create() -> u32 { 2 }
+impl Into<u32> for Foo {
+    fn into(self) -> u32 { 1 }
 }
 
 fn main() {
-    let gen1 = AnotherImpl::create();
-
-    // if there are multiple methods with same name (different traits)
-    let gen2 = <AnotherImpl as Generator>::create();
+    let foo = Foo;
+    let bar: u32 = <Foo as Into<u32>>::into(foo) * 1u32;
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md
new file mode 100644
index 00000000000..93d9636626d
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0790.md
@@ -0,0 +1,51 @@
+You need to specify a specific implementation of the trait in order to call the
+method.
+
+Erroneous code example:
+
+```compile_fail,E0790
+trait Generator {
+    fn create() -> u32;
+}
+
+struct Impl;
+
+impl Generator for Impl {
+    fn create() -> u32 { 1 }
+}
+
+struct AnotherImpl;
+
+impl Generator for AnotherImpl {
+    fn create() -> u32 { 2 }
+}
+
+fn main() {
+    let cont: u32 = Generator::create();
+    // error, impossible to choose one of Generator trait implementation
+    // Should it be Impl or AnotherImpl, maybe something else?
+}
+```
+
+This error can be solved by adding type annotations that provide the missing
+information to the compiler. In this case, the solution is to use a concrete
+type:
+
+```
+trait Generator {
+    fn create() -> u32;
+}
+
+struct AnotherImpl;
+
+impl Generator for AnotherImpl {
+    fn create() -> u32 { 2 }
+}
+
+fn main() {
+    let gen1 = AnotherImpl::create();
+
+    // if there are multiple methods with same name (different traits)
+    let gen2 = <AnotherImpl as Generator>::create();
+}
+```
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 826c16dda4a..541dace5cc2 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -74,6 +74,10 @@ impl TraitImpls {
     pub fn blanket_impls(&self) -> &[DefId] {
         self.blanket_impls.as_slice()
     }
+
+    pub fn non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>> {
+        &self.non_blanket_impls
+    }
 }
 
 impl<'tcx> TraitDef {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 8a679ca005f..585159e309f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2104,6 +2104,98 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                         );
                     }
                 }
+
+                if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
+                    (body_id, subst.map(|subst| subst.unpack()))
+                {
+                    struct FindExprBySpan<'hir> {
+                        span: Span,
+                        result: Option<&'hir hir::Expr<'hir>>,
+                    }
+
+                    impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> {
+                        fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                            if self.span == ex.span {
+                                self.result = Some(ex);
+                            } else {
+                                hir::intravisit::walk_expr(self, ex);
+                            }
+                        }
+                    }
+
+                    let mut expr_finder = FindExprBySpan { span, result: None };
+
+                    expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
+
+                    if let Some(hir::Expr {
+                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }
+                    ) = expr_finder.result
+                        && let [
+                            ..,
+                            trait_path_segment @ hir::PathSegment {
+                                res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)),
+                                ..
+                            },
+                            hir::PathSegment {
+                                ident: assoc_item_name,
+                                res: Some(rustc_hir::def::Res::Def(_, item_id)),
+                                ..
+                            }
+                        ] = path.segments
+                        && data.trait_ref.def_id == *trait_id
+                        && self.tcx.trait_of_item(item_id) == Some(*trait_id)
+                        && !self.is_tainted_by_errors()
+                    {
+                        let (verb, noun) = match self.tcx.associated_item(item_id).kind {
+                            ty::AssocKind::Const => ("refer to the", "constant"),
+                            ty::AssocKind::Fn => ("call", "function"),
+                            ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
+                        };
+
+                        // Replace the more general E0283 with a more specific error
+                        err.cancel();
+                        err = self.tcx.sess.struct_span_err_with_code(
+                            span,
+                            &format!(
+                                "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
+                             ),
+                            rustc_errors::error_code!(E0790),
+                        );
+
+                        if let Some(local_def_id) = data.trait_ref.def_id.as_local()
+                            && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
+                            && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
+                            err.span_label(method_ref.span, format!("`{}::{}` defined here", trait_name, assoc_item_name));
+                        }
+
+                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
+
+                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
+
+                        if trait_impls.blanket_impls().is_empty()
+                            && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
+                            && let Some(impl_def_id) = impl_ty.def() {
+                            let message = if trait_impls.non_blanket_impls().len() == 1 {
+                                "use the fully-qualified path to the only available implementation".to_string()
+                            } else {
+                                format!(
+                                    "use a fully-qualified path to a specific available implementation ({} found)",
+                                    trait_impls.non_blanket_impls().len()
+                                )
+                            };
+
+                            err.multipart_suggestion(
+                                message,
+                                vec![
+                                    (trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
+                                    (trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
+                                ],
+                                Applicability::MaybeIncorrect
+                            );
+                        }
+                    }
+                };
+
                 err
             }
 
diff --git a/src/test/ui/associated-consts/issue-63496.rs b/src/test/ui/associated-consts/issue-63496.rs
index f9f663af5e2..67ef4e74cf2 100644
--- a/src/test/ui/associated-consts/issue-63496.rs
+++ b/src/test/ui/associated-consts/issue-63496.rs
@@ -2,8 +2,8 @@ trait A {
     const C: usize;
 
     fn f() -> ([u8; A::C], [u8; A::C]);
-    //~^ ERROR: type annotations needed
-    //~| ERROR: type annotations needed
+    //~^ ERROR: E0790
+    //~| ERROR: E0790
 }
 
 fn main() {}
diff --git a/src/test/ui/associated-consts/issue-63496.stderr b/src/test/ui/associated-consts/issue-63496.stderr
index db39fd762c3..f2a4e01adea 100644
--- a/src/test/ui/associated-consts/issue-63496.stderr
+++ b/src/test/ui/associated-consts/issue-63496.stderr
@@ -1,27 +1,21 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-63496.rs:4:21
    |
+LL |     const C: usize;
+   |     --------------- `A::C` defined here
+LL |
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                     ^^^^
-   |                     |
-   |                     cannot infer type
-   |                     help: use the fully qualified path to an implementation: `<Type as A>::C`
-   |
-   = note: cannot satisfy `_: A`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                     ^^^^ cannot refer to the associated constant of trait
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-63496.rs:4:33
    |
+LL |     const C: usize;
+   |     --------------- `A::C` defined here
+LL |
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                                 ^^^^
-   |                                 |
-   |                                 cannot infer type
-   |                                 help: use the fully qualified path to an implementation: `<Type as A>::C`
-   |
-   = note: cannot satisfy `_: A`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                                 ^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/associated-item/issue-48027.rs b/src/test/ui/associated-item/issue-48027.rs
index c9b4ccd3e8a..d2b51184c99 100644
--- a/src/test/ui/associated-item/issue-48027.rs
+++ b/src/test/ui/associated-item/issue-48027.rs
@@ -1,6 +1,6 @@
 trait Bar {
     const X: usize;
-    fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed
+    fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790
 }
 
 impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 5487af1a835..45ea419336b 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -13,19 +13,15 @@ LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-48027.rs:3:32
    |
+LL |     const X: usize;
+   |     --------------- `Bar::X` defined here
 LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^
-   |                                |
-   |                                cannot infer type
-   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
-   |
-   = note: cannot satisfy `_: Bar`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                                ^^^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0038, E0283.
+Some errors have detailed explanations: E0038, E0790.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.rs b/src/test/ui/associated-types/associated-types-unconstrained.rs
index b97d4af184f..2fb27bf3cd1 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.rs
+++ b/src/test/ui/associated-types/associated-types-unconstrained.rs
@@ -12,5 +12,5 @@ impl Foo for isize {
 
 pub fn main() {
     let x: isize = Foo::bar();
-    //~^ ERROR type annotations needed
+    //~^ ERROR E0790
 }
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr
index 60ec23cf655..e51a8f3bd1a 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.stderr
+++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr
@@ -1,11 +1,12 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/associated-types-unconstrained.rs:14:20
    |
+LL |     fn bar() -> isize;
+   |     ------------------ `Foo::bar` defined here
+...
 LL |     let x: isize = Foo::bar();
-   |                    ^^^^^^^^ cannot infer type
-   |
-   = note: cannot satisfy `_: Foo`
+   |                    ^^^^^^^^ cannot call associated function of trait
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/error-codes/E0283.rs b/src/test/ui/error-codes/E0283.rs
index 4d7c2f2396d..0643af4b7e8 100644
--- a/src/test/ui/error-codes/E0283.rs
+++ b/src/test/ui/error-codes/E0283.rs
@@ -27,7 +27,7 @@ impl Generator for AnotherImpl {
 }
 
 fn main() {
-    let cont: u32 = Generator::create(); //~ ERROR E0283
+    let cont: u32 = Generator::create(); //~ ERROR E0790
 }
 
 fn buzz() {
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index a107160d11a..90a28874ead 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -1,10 +1,16 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/E0283.rs:30:21
    |
+LL |     fn create() -> u32;
+   |     ------------------- `Generator::create` defined here
+...
 LL |     let cont: u32 = Generator::create();
-   |                     ^^^^^^^^^^^^^^^^^ cannot infer type
+   |                     ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
    |
-   = note: cannot satisfy `_: Generator`
+help: use a fully-qualified path to a specific available implementation (2 found)
+   |
+LL |     let cont: u32 = <::Impl as Generator>::create();
+   |                     ++++++++++          +
 
 error[E0283]: type annotations needed
   --> $DIR/E0283.rs:35:24
@@ -27,4 +33,5 @@ LL |     let bar = <Impl as Into<T>>::into(foo_impl) * 1u32;
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0283, E0790.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/src/test/ui/error-codes/E0790.rs b/src/test/ui/error-codes/E0790.rs
new file mode 100644
index 00000000000..d99006d2df7
--- /dev/null
+++ b/src/test/ui/error-codes/E0790.rs
@@ -0,0 +1,53 @@
+mod inner {
+    pub trait MyTrait {
+        const MY_ASSOC_CONST: ();
+
+        fn my_fn();
+    }
+
+    pub struct MyStruct;
+
+    impl MyTrait for MyStruct {
+        const MY_ASSOC_CONST: () = ();
+
+        fn my_fn() {}
+    }
+
+    fn call() {
+        MyTrait::my_fn(); //~ ERROR E0790
+    }
+
+    fn use_const() {
+        let _ = MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
+    }
+}
+
+fn call_inner() {
+    inner::MyTrait::my_fn(); //~ ERROR E0790
+}
+
+fn use_const_inner() {
+    let _ = inner::MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
+}
+
+trait MyTrait2 {
+    fn my_fn();
+}
+
+struct Impl1;
+
+impl MyTrait2 for Impl1 {
+    fn my_fn() {}
+}
+
+struct Impl2;
+
+impl MyTrait2 for Impl2 {
+    fn my_fn() {}
+}
+
+fn call_multiple_impls() {
+    MyTrait2::my_fn(); //~ ERROR E0790
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr
new file mode 100644
index 00000000000..6e173a9682a
--- /dev/null
+++ b/src/test/ui/error-codes/E0790.stderr
@@ -0,0 +1,73 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:17:9
+   |
+LL |         fn my_fn();
+   |         ----------- `MyTrait::my_fn` defined here
+...
+LL |         MyTrait::my_fn();
+   |         ^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |         <::inner::MyStruct as MyTrait>::my_fn();
+   |         +++++++++++++++++++++        +
+
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:21:17
+   |
+LL |         const MY_ASSOC_CONST: ();
+   |         ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
+...
+LL |         let _ = MyTrait::MY_ASSOC_CONST;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |         let _ = <::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
+   |                 +++++++++++++++++++++        +
+
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:26:5
+   |
+LL |         fn my_fn();
+   |         ----------- `MyTrait::my_fn` defined here
+...
+LL |     inner::MyTrait::my_fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     inner::<::inner::MyStruct as MyTrait>::my_fn();
+   |            +++++++++++++++++++++        +
+
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:30:13
+   |
+LL |         const MY_ASSOC_CONST: ();
+   |         ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
+...
+LL |     let _ = inner::MyTrait::MY_ASSOC_CONST;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let _ = inner::<::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
+   |                    +++++++++++++++++++++        +
+
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:50:5
+   |
+LL |     fn my_fn();
+   |     ----------- `MyTrait2::my_fn` defined here
+...
+LL |     MyTrait2::my_fn();
+   |     ^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use a fully-qualified path to a specific available implementation (2 found)
+   |
+LL |     <::Impl1 as MyTrait2>::my_fn();
+   |     +++++++++++         +
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs
index ddd39141541..d4e1df22770 100644
--- a/src/test/ui/issues/issue-54954.rs
+++ b/src/test/ui/issues/issue-54954.rs
@@ -1,5 +1,5 @@
 const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-//~^ ERROR type annotations needed
+//~^ ERROR E0790
 
 trait Tt {
     const fn const_val<T: Sized>() -> usize {
diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr
index 6e8d3cac9a7..668985c2b59 100644
--- a/src/test/ui/issues/issue-54954.stderr
+++ b/src/test/ui/issues/issue-54954.stderr
@@ -4,13 +4,17 @@ error[E0379]: functions in traits cannot be declared const
 LL |     const fn const_val<T: Sized>() -> usize {
    |     ^^^^^ functions in traits cannot be const
 
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/issue-54954.rs:1:24
    |
-LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
-   |
-   = note: cannot satisfy `_: Tt`
+LL |   const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+...
+LL | /     const fn const_val<T: Sized>() -> usize {
+LL | |
+LL | |         core::mem::size_of::<T>()
+LL | |     }
+   | |_____- `Tt::const_val` defined here
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-54954.rs:11:15
@@ -26,5 +30,5 @@ LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0080, E0283, E0379.
+Some errors have detailed explanations: E0080, E0379, E0790.
 For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs
index e4b9b3b53a6..2a8a1eaa6d3 100644
--- a/src/test/ui/issues/issue-58022.rs
+++ b/src/test/ui/issues/issue-58022.rs
@@ -2,7 +2,7 @@ pub trait Foo: Sized {
     const SIZE: usize;
 
     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-    //~^ ERROR: type annotations needed
+    //~^ ERROR: E0790
 }
 
 pub struct Bar<T: ?Sized>(T);
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index 0128b70e216..6d24209ad3c 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -4,19 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo
 LL |         Foo(Box::new(*slice))
    |         ^^^ not a function, tuple struct or tuple variant
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-58022.rs:4:25
    |
+LL |     const SIZE: usize;
+   |     ------------------ `Foo::SIZE` defined here
+LL |
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-   |                         ^^^^^^^^^
-   |                         |
-   |                         cannot infer type
-   |                         help: use the fully qualified path to an implementation: `<Type as Foo>::SIZE`
-   |
-   = note: cannot satisfy `_: Foo`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                         ^^^^^^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0283, E0423.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0423, E0790.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/traits/static-method-generic-inference.rs b/src/test/ui/traits/static-method-generic-inference.rs
index 759416d1901..f4e94c4f786 100644
--- a/src/test/ui/traits/static-method-generic-inference.rs
+++ b/src/test/ui/traits/static-method-generic-inference.rs
@@ -22,7 +22,7 @@ mod base {
 
 pub fn foo() {
     let _f: base::Foo = base::HasNew::new();
-    //~^ ERROR type annotations needed
+    //~^ ERROR E0790
 }
 
 fn main() { }
diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr
index 1a0bcf00a67..f1b8f23ecc7 100644
--- a/src/test/ui/traits/static-method-generic-inference.stderr
+++ b/src/test/ui/traits/static-method-generic-inference.stderr
@@ -1,11 +1,17 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/static-method-generic-inference.rs:24:25
    |
+LL |         fn new() -> T;
+   |         -------------- `HasNew::new` defined here
+...
 LL |     let _f: base::Foo = base::HasNew::new();
-   |                         ^^^^^^^^^^^^^^^^^ cannot infer type
+   |                         ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
    |
-   = note: cannot satisfy `_: HasNew<Foo>`
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let _f: base::Foo = base::<::base::Foo as HasNew>::new();
+   |                               +++++++++++++++       +
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.

From 38ea23558eca629d668208e368dfa711b8229192 Mon Sep 17 00:00:00 2001
From: aticu <15schnic@gmail.com>
Date: Mon, 13 Jun 2022 09:32:54 +0200
Subject: [PATCH 13/14] Don't use main; improve example

---
 .../rustc_error_codes/src/error_codes/E0283.md   | 14 +++++---------
 .../rustc_error_codes/src/error_codes/E0790.md   | 16 ++++++----------
 2 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md
index e5a3179aabf..79d2c8204f9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0283.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0283.md
@@ -9,15 +9,13 @@ impl Into<u32> for Foo {
     fn into(self) -> u32 { 1 }
 }
 
-fn main() {
-    let foo = Foo;
-    let bar: u32 = foo.into() * 1u32;
-}
+let foo = Foo;
+let bar: u32 = foo.into() * 1u32;
 ```
 
 This error can be solved by adding type annotations that provide the missing
 information to the compiler. In this case, the solution is to specify the
-fully-qualified method:
+trait's type parameter:
 
 ```
 struct Foo;
@@ -26,8 +24,6 @@ impl Into<u32> for Foo {
     fn into(self) -> u32 { 1 }
 }
 
-fn main() {
-    let foo = Foo;
-    let bar: u32 = <Foo as Into<u32>>::into(foo) * 1u32;
-}
+let foo = Foo;
+let bar: u32 = Into::<u32>::into(foo) * 1u32;
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md
index 93d9636626d..2aee9dfbdbd 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0790.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0790.md
@@ -20,11 +20,9 @@ impl Generator for AnotherImpl {
     fn create() -> u32 { 2 }
 }
 
-fn main() {
-    let cont: u32 = Generator::create();
-    // error, impossible to choose one of Generator trait implementation
-    // Should it be Impl or AnotherImpl, maybe something else?
-}
+let cont: u32 = Generator::create();
+// error, impossible to choose one of Generator trait implementation
+// Should it be Impl or AnotherImpl, maybe something else?
 ```
 
 This error can be solved by adding type annotations that provide the missing
@@ -42,10 +40,8 @@ impl Generator for AnotherImpl {
     fn create() -> u32 { 2 }
 }
 
-fn main() {
-    let gen1 = AnotherImpl::create();
+let gen1 = AnotherImpl::create();
 
-    // if there are multiple methods with same name (different traits)
-    let gen2 = <AnotherImpl as Generator>::create();
-}
+// if there are multiple methods with same name (different traits)
+let gen2 = <AnotherImpl as Generator>::create();
 ```

From e2ecb68a0eeee6db4d8f605374e656822186f8b4 Mon Sep 17 00:00:00 2001
From: SparrowLii <liyuan179@huawei.com>
Date: Tue, 19 Jul 2022 17:00:51 +0800
Subject: [PATCH 14/14] use `par_for_each_in` in `par_body_owners` and
 `collect_crate_mono_items`

---
 compiler/rustc_data_structures/src/sync.rs   |  2 +-
 compiler/rustc_middle/src/hir/map/mod.rs     |  4 +---
 compiler/rustc_monomorphize/src/collector.rs |  4 ++--
 src/test/ui/privacy/privacy2.stderr          |  8 +++++++-
 src/test/ui/privacy/privacy3.stderr          |  8 +++++++-
 src/test/ui/type_length_limit.stderr         | 11 ++++++++++-
 6 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index cf0940df9e4..52952a7932d 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -146,7 +146,7 @@ cfg_if! {
             t.into_iter()
         }
 
-        pub fn par_for_each_in<T: IntoIterator>(t: T, for_each: impl Fn(T::Item) + Sync + Send) {
+        pub fn par_for_each_in<T: IntoIterator>(t: T, mut for_each: impl FnMut(T::Item) + Sync + Send) {
             // We catch panics here ensuring that all the loop iterations execute.
             // This makes behavior consistent with the parallel compiler.
             let mut panic = None;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 3a59b2069b3..0001e1aa53e 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -491,9 +491,7 @@ impl<'hir> Map<'hir> {
     }
 
     pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
-        use rustc_data_structures::sync::{par_iter, ParallelIterator};
-
-        par_iter(&self.tcx.hir_crate_items(()).body_owners[..]).for_each(|&def_id| f(def_id));
+        par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
     }
 
     pub fn ty_param_owner(self, def_id: LocalDefId) -> LocalDefId {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index d9fa4d65b3a..e3cfb034e40 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -180,7 +180,7 @@
 //! regardless of whether it is actually needed or not.
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
+use rustc_data_structures::sync::{par_for_each_in, MTLock, MTRef};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@@ -346,7 +346,7 @@ pub fn collect_crate_mono_items(
         let inlining_map: MTRef<'_, _> = &mut inlining_map;
 
         tcx.sess.time("monomorphization_collector_graph_walk", || {
-            par_iter(roots).for_each(|root| {
+            par_for_each_in(roots, |root| {
                 let mut recursion_depths = DefIdMap::default();
                 collect_items_rec(
                     tcx,
diff --git a/src/test/ui/privacy/privacy2.stderr b/src/test/ui/privacy/privacy2.stderr
index c2a33ce1f59..882f314655d 100644
--- a/src/test/ui/privacy/privacy2.stderr
+++ b/src/test/ui/privacy/privacy2.stderr
@@ -23,7 +23,13 @@ LL | pub fn foo() {}
 
 error: requires `sized` lang_item
 
-error: aborting due to 3 previous errors
+error: requires `sized` lang_item
+
+error: requires `sized` lang_item
+
+error: requires `sized` lang_item
+
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0432, E0603.
 For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/privacy/privacy3.stderr b/src/test/ui/privacy/privacy3.stderr
index 22c1e48b07d..42ce456d962 100644
--- a/src/test/ui/privacy/privacy3.stderr
+++ b/src/test/ui/privacy/privacy3.stderr
@@ -6,6 +6,12 @@ LL |     use bar::gpriv;
 
 error: requires `sized` lang_item
 
-error: aborting due to 2 previous errors
+error: requires `sized` lang_item
+
+error: requires `sized` lang_item
+
+error: requires `sized` lang_item
+
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr
index a2ddffff997..1508b84c1b6 100644
--- a/src/test/ui/type_length_limit.stderr
+++ b/src/test/ui/type_length_limit.stderr
@@ -7,5 +7,14 @@ LL | pub fn drop<T>(_x: T) {}
    = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
    = help: consider adding a `#![type_length_limit="8"]` attribute to your crate
 
-error: aborting due to previous error
+error: reached the type-length limit while instantiating `<[closure@std::rt::lang_start<()...e<()>>::call_once - shim(vtable)`
+  --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit/type_length_limit.long-type.txt'
+   = help: consider adding a `#![type_length_limit="8"]` attribute to your crate
+
+error: aborting due to 2 previous errors