about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-06 00:03:50 +0000
committerbors <bors@rust-lang.org>2024-03-06 00:03:50 +0000
commit62415e2a95a3b0f137636f86f6a904b8ed85798e (patch)
tree07a480ebc35421328f331256dba81121844d484f /compiler
parentb6d2d841bcf4b77343b159f134c7d39c2dd4ceaa (diff)
parent3d6b3d0f59311578a7c8aa36862947774067e0aa (diff)
downloadrust-62415e2a95a3b0f137636f86f6a904b8ed85798e.tar.gz
rust-62415e2a95a3b0f137636f86f6a904b8ed85798e.zip
Auto merge of #122041 - matthiaskrgr:rollup-imsmdke, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #121202 (Limit the number of names and values in check-cfg diagnostics)
 - #121301 (errors: share `SilentEmitter` between rustc and rustfmt)
 - #121658 (Hint user to update nightly on ICEs produced from outdated nightly)
 - #121846 (only compare ambiguity item that have hard error)
 - #121961 (add test for #78894 #71450)
 - #121975 (hir_analysis: enums return `None` in `find_field`)
 - #121978 (Fix duplicated path in the "not found dylib" error)
 - #121991 (Merge impl_trait_in_assoc_types_defined_by query back into `opaque_types_defined_by`)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml2
-rw-r--r--compiler/rustc_driver_impl/messages.ftl4
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs35
-rw-r--r--compiler/rustc_driver_impl/src/session_diagnostics.rs11
-rw-r--r--compiler/rustc_errors/src/emitter.rs32
-rw-r--r--compiler/rustc_errors/src/lib.rs95
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs28
-rw-r--r--compiler/rustc_interface/src/interface.rs14
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs71
-rw-r--r--compiler/rustc_metadata/src/creader.rs8
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_resolve/src/imports.rs10
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs18
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs21
16 files changed, 234 insertions, 133 deletions
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 242aa06fe3e..fcc0afd3488 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -50,7 +50,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
 serde_json = "1.0.59"
 shlex = "1.0"
-time = { version = "0.3", default-features = false, features = ["alloc", "formatting"] }
+time = { version = "0.3", default-features = false, features = ["alloc", "formatting", "parsing", "macros"] }
 tracing = { version = "0.1.35" }
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl
index 39462112dc2..1b69a6e2fbe 100644
--- a/compiler/rustc_driver_impl/messages.ftl
+++ b/compiler/rustc_driver_impl/messages.ftl
@@ -1,6 +1,10 @@
 driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
 driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly
+driver_impl_ice_bug_report_outdated =
+    it seems that this compiler `{$version}` is outdated, a newer nightly should have been released in the mean time
+    .update = please consider running `rustup update nightly` to update the nightly channel and check if this problem still persists
+    .url = if the problem still persists, we would appreciate a bug report: {$bug_report_url}
 driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
 
 driver_impl_ice_flags = compiler flags: {$flags}
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index ab1e37e4ac2..85be97ea24f 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -58,7 +58,7 @@ use std::str;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, OnceLock};
 use std::time::{Instant, SystemTime};
-use time::OffsetDateTime;
+use time::{Date, OffsetDateTime, Time};
 
 #[allow(unused_macros)]
 macro do_not_use_print($($t:tt)*) {
@@ -1369,6 +1369,9 @@ pub fn install_ice_hook(
     using_internal_features
 }
 
+const DATE_FORMAT: &[time::format_description::FormatItem<'static>] =
+    &time::macros::format_description!("[year]-[month]-[day]");
+
 /// Prints the ICE message, including query stack, but without backtrace.
 ///
 /// The message will point the user at `bug_report_url` to report the ICE.
@@ -1397,10 +1400,34 @@ fn report_ice(
         dcx.emit_err(session_diagnostics::Ice);
     }
 
-    if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
-        dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
+    use time::ext::NumericalDuration;
+
+    // Try to hint user to update nightly if applicable when reporting an ICE.
+    // Attempt to calculate when current version was released, and add 12 hours
+    // as buffer. If the current version's release timestamp is older than
+    // the system's current time + 24 hours + 12 hours buffer if we're on
+    // nightly.
+    if let Some("nightly") = option_env!("CFG_RELEASE_CHANNEL")
+        && let Some(version) = option_env!("CFG_VERSION")
+        && let Some(ver_date_str) = option_env!("CFG_VER_DATE")
+        && let Ok(ver_date) = Date::parse(&ver_date_str, DATE_FORMAT)
+        && let ver_datetime = OffsetDateTime::new_utc(ver_date, Time::MIDNIGHT)
+        && let system_datetime = OffsetDateTime::from(SystemTime::now())
+        && system_datetime.checked_sub(36.hours()).is_some_and(|d| d > ver_datetime)
+        && !using_internal_features.load(std::sync::atomic::Ordering::Relaxed)
+    {
+        dcx.emit_note(session_diagnostics::IceBugReportOutdated {
+            version,
+            bug_report_url,
+            note_update: (),
+            note_url: (),
+        });
     } else {
-        dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+        if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) {
+            dcx.emit_note(session_diagnostics::IceBugReportInternalFeature);
+        } else {
+            dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+        }
     }
 
     let version = util::version_str!().unwrap_or("unknown_version");
diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs
index 2b31fdd77cc..62d0da62d2a 100644
--- a/compiler/rustc_driver_impl/src/session_diagnostics.rs
+++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs
@@ -47,6 +47,17 @@ pub(crate) struct IceBugReport<'a> {
 pub(crate) struct IceBugReportInternalFeature;
 
 #[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report_outdated)]
+pub(crate) struct IceBugReportOutdated<'a> {
+    pub version: &'a str,
+    pub bug_report_url: &'a str,
+    #[note(driver_impl_update)]
+    pub note_update: (),
+    #[note(driver_impl_url)]
+    pub note_url: (),
+}
+
+#[derive(Diagnostic)]
 #[diag(driver_impl_ice_version)]
 pub(crate) struct IceVersion<'a> {
     pub version: &'a str,
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 293d8f01e67..57b8df52f4b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -10,7 +10,6 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::{FileLines, FileName, SourceFile, Span};
 
-use crate::error::TranslateError;
 use crate::snippet::{
     Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
 };
@@ -539,18 +538,9 @@ impl Emitter for HumanEmitter {
 /// Fatal diagnostics are forwarded to `fatal_dcx` to avoid silent
 /// failures of rustc, as witnessed e.g. in issue #89358.
 pub struct SilentEmitter {
+    pub fallback_bundle: LazyFallbackBundle,
     pub fatal_dcx: DiagCtxt,
-    pub fatal_note: String,
-}
-
-pub fn silent_translate<'a>(message: &'a DiagMessage) -> Result<Cow<'_, str>, TranslateError<'_>> {
-    match message {
-        DiagMessage::Str(msg) | DiagMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
-        DiagMessage::FluentIdentifier(identifier, _) => {
-            // Any value works here.
-            Ok(identifier.clone())
-        }
-    }
+    pub fatal_note: Option<String>,
 }
 
 impl Translate for SilentEmitter {
@@ -559,17 +549,9 @@ impl Translate for SilentEmitter {
     }
 
     fn fallback_fluent_bundle(&self) -> &FluentBundle {
-        panic!("silent emitter attempted to translate message")
-    }
-
-    // Override `translate_message` for the silent emitter because eager translation of
-    // subdiagnostics result in a call to this.
-    fn translate_message<'a>(
-        &'a self,
-        message: &'a DiagMessage,
-        _: &'a FluentArgs<'_>,
-    ) -> Result<Cow<'_, str>, TranslateError<'_>> {
-        silent_translate(message)
+        // Ideally this field wouldn't be necessary and the fallback bundle in `fatal_dcx` would be
+        // used but the lock prevents this.
+        &self.fallback_bundle
     }
 }
 
@@ -580,7 +562,9 @@ impl Emitter for SilentEmitter {
 
     fn emit_diagnostic(&mut self, mut diag: DiagInner) {
         if diag.level == Level::Fatal {
-            diag.sub(Level::Note, self.fatal_note.clone(), MultiSpan::new());
+            if let Some(fatal_note) = &self.fatal_note {
+                diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
+            }
             self.fatal_dcx.emit_diagnostic(diag);
         }
     }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 0a6d66f52da..0caa8fa9e8a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -63,7 +63,7 @@ use emitter::{is_case_difference, DynEmitter, Emitter};
 use registry::Registry;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_data_structures::AtomicRef;
 use rustc_lint_defs::LintExpectationId;
 use rustc_span::source_map::SourceMap;
@@ -606,29 +606,54 @@ impl DiagCtxt {
     }
 
     pub fn new(emitter: Box<DynEmitter>) -> Self {
-        Self {
-            inner: Lock::new(DiagCtxtInner {
-                flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
-                err_guars: Vec::new(),
-                lint_err_guars: Vec::new(),
-                delayed_bugs: Vec::new(),
-                deduplicated_err_count: 0,
-                deduplicated_warn_count: 0,
-                emitter,
-                must_produce_diag: false,
-                has_printed: false,
-                suppressed_expected_diag: false,
-                taught_diagnostics: Default::default(),
-                emitted_diagnostic_codes: Default::default(),
-                emitted_diagnostics: Default::default(),
-                stashed_diagnostics: Default::default(),
-                future_breakage_diagnostics: Vec::new(),
-                check_unstable_expect_diagnostics: false,
-                unstable_expect_diagnostics: Vec::new(),
-                fulfilled_expectations: Default::default(),
-                ice_file: None,
-            }),
+        Self { inner: Lock::new(DiagCtxtInner::new(emitter)) }
+    }
+
+    pub fn make_silent(&mut self, fallback_bundle: LazyFallbackBundle, fatal_note: Option<String>) {
+        self.wrap_emitter(|old_dcx| {
+            Box::new(emitter::SilentEmitter {
+                fallback_bundle,
+                fatal_dcx: DiagCtxt { inner: Lock::new(old_dcx) },
+                fatal_note,
+            })
+        });
+    }
+
+    fn wrap_emitter<F>(&mut self, f: F)
+    where
+        F: FnOnce(DiagCtxtInner) -> Box<DynEmitter>,
+    {
+        // A empty type that implements `Emitter` so that a `DiagCtxtInner` can be constructed
+        // to temporarily swap in place of the real one, which will be used in constructing
+        // its replacement.
+        struct FalseEmitter;
+
+        impl Emitter for FalseEmitter {
+            fn emit_diagnostic(&mut self, _: DiagInner) {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+
+            fn source_map(&self) -> Option<&Lrc<SourceMap>> {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
         }
+
+        impl translation::Translate for FalseEmitter {
+            fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+
+            fn fallback_fluent_bundle(&self) -> &FluentBundle {
+                unimplemented!("false emitter must only used during `wrap_emitter`")
+            }
+        }
+
+        let mut inner = self.inner.borrow_mut();
+        let mut prev_dcx = DiagCtxtInner::new(Box::new(FalseEmitter));
+        std::mem::swap(&mut *inner, &mut prev_dcx);
+        let new_emitter = f(prev_dcx);
+        let mut new_dcx = DiagCtxtInner::new(new_emitter);
+        std::mem::swap(&mut *inner, &mut new_dcx);
     }
 
     /// Translate `message` eagerly with `args` to `SubdiagMessage::Eager`.
@@ -1345,6 +1370,30 @@ impl DiagCtxt {
 // `DiagCtxt::foo()` just borrows `inner` and forwards a call to
 // `DiagCtxtInner::foo`.
 impl DiagCtxtInner {
+    fn new(emitter: Box<DynEmitter>) -> Self {
+        Self {
+            flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() },
+            err_guars: Vec::new(),
+            lint_err_guars: Vec::new(),
+            delayed_bugs: Vec::new(),
+            deduplicated_err_count: 0,
+            deduplicated_warn_count: 0,
+            emitter,
+            must_produce_diag: false,
+            has_printed: false,
+            suppressed_expected_diag: false,
+            taught_diagnostics: Default::default(),
+            emitted_diagnostic_codes: Default::default(),
+            emitted_diagnostics: Default::default(),
+            stashed_diagnostics: Default::default(),
+            future_breakage_diagnostics: Vec::new(),
+            check_unstable_expect_diagnostics: false,
+            unstable_expect_diagnostics: Vec::new(),
+            fulfilled_expectations: Default::default(),
+            ice_file: None,
+        }
+    }
+
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
         let mut guar = None;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index b6e2695590c..2cc37651ef5 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -791,7 +791,12 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
 }
 
 fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option<FieldIdx> {
-    tcx.adt_def(def_id).non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| {
+    let adt = tcx.adt_def(def_id);
+    if adt.is_enum() {
+        return None;
+    }
+
+    adt.non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| {
         if field.is_unnamed() {
             let field_ty = tcx.type_of(field.did).instantiate_identity();
             let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field");
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f0e998b7a00..dcb01a117b0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -46,9 +46,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
     for &assoc_id in tcx.associated_item_def_ids(impl_def_id) {
         let assoc = tcx.associated_item(assoc_id);
         match assoc.kind {
-            ty::AssocKind::Const | ty::AssocKind::Fn => {
-                locator.check(assoc_id.expect_local(), ImplTraitSource::AssocTy)
-            }
+            ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()),
             // Associated types don't have bodies, so they can't constrain hidden types
             ty::AssocKind::Type => {}
         }
@@ -182,15 +180,9 @@ struct TaitConstraintLocator<'tcx> {
     typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
 }
 
-#[derive(Debug)]
-enum ImplTraitSource {
-    AssocTy,
-    TyAlias,
-}
-
 impl TaitConstraintLocator<'_> {
     #[instrument(skip(self), level = "debug")]
-    fn check(&mut self, item_def_id: LocalDefId, source: ImplTraitSource) {
+    fn check(&mut self, item_def_id: LocalDefId) {
         // Don't try to check items that cannot possibly constrain the type.
         if !self.tcx.has_typeck_results(item_def_id) {
             debug!("no constraint: no typeck results");
@@ -242,12 +234,8 @@ impl TaitConstraintLocator<'_> {
                 continue;
             }
             constrained = true;
-            let opaque_types_defined_by = match source {
-                ImplTraitSource::AssocTy => {
-                    self.tcx.impl_trait_in_assoc_types_defined_by(item_def_id)
-                }
-                ImplTraitSource::TyAlias => self.tcx.opaque_types_defined_by(item_def_id),
-            };
+            let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
+
             if !opaque_types_defined_by.contains(&self.def_id) {
                 self.tcx.dcx().emit_err(TaitForwardCompat {
                     span: hidden_type.span,
@@ -308,7 +296,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     }
     fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         if let hir::ExprKind::Closure(closure) = ex.kind {
-            self.check(closure.def_id, ImplTraitSource::TyAlias);
+            self.check(closure.def_id);
         }
         intravisit::walk_expr(self, ex);
     }
@@ -316,7 +304,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+            self.check(it.owner_id.def_id);
             intravisit::walk_item(self, it);
         }
     }
@@ -324,13 +312,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
         trace!(?it.owner_id);
         // The opaque type itself or its children are not within its reveal scope.
         if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+            self.check(it.owner_id.def_id);
             intravisit::walk_impl_item(self, it);
         }
     }
     fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         trace!(?it.owner_id);
-        self.check(it.owner_id.def_id, ImplTraitSource::TyAlias);
+        self.check(it.owner_id.def_id);
         intravisit::walk_trait_item(self, it);
     }
     fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 3a2bbed19be..b2ec8e53429 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -45,9 +45,10 @@ pub struct Compiler {
 pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
     cfgs.into_iter()
         .map(|s| {
-            let psess = ParseSess::with_silent_emitter(format!(
-                "this error occurred on the command line: `--cfg={s}`"
-            ));
+            let psess = ParseSess::with_silent_emitter(
+                vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+                format!("this error occurred on the command line: `--cfg={s}`"),
+            );
             let filename = FileName::cfg_spec_source_code(&s);
 
             macro_rules! error {
@@ -107,9 +108,10 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
     let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
 
     for s in specs {
-        let psess = ParseSess::with_silent_emitter(format!(
-            "this error occurred on the command line: `--check-cfg={s}`"
-        ));
+        let psess = ParseSess::with_silent_emitter(
+            vec![crate::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE],
+            format!("this error occurred on the command line: `--check-cfg={s}`"),
+        );
         let filename = FileName::cfg_spec_source_code(&s);
 
         macro_rules! error {
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index a0aa252bcdf..a58a37bf3ac 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -12,6 +12,43 @@ use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::BytePos;
 
+const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35;
+
+fn check_cfg_expected_note(
+    sess: &Session,
+    possibilities: &[Symbol],
+    type_: &str,
+    name: Option<Symbol>,
+    suffix: &str,
+) -> String {
+    use std::fmt::Write;
+
+    let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected {
+        possibilities.len()
+    } else {
+        std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES)
+    };
+
+    let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
+    possibilities.sort();
+
+    let and_more = possibilities.len().saturating_sub(n_possibilities);
+    let possibilities = possibilities[..n_possibilities].join("`, `");
+
+    let mut note = String::with_capacity(50 + possibilities.len());
+
+    write!(&mut note, "expected {type_}").unwrap();
+    if let Some(name) = name {
+        write!(&mut note, " for `{name}`").unwrap();
+    }
+    write!(&mut note, " are: {suffix}`{possibilities}`").unwrap();
+    if and_more > 0 {
+        write!(&mut note, " and {and_more} more").unwrap();
+    }
+
+    note
+}
+
 pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
     match diagnostic {
         BuiltinLintDiag::UnicodeTextFlow(span, content) => {
@@ -286,16 +323,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
                     }
                 }
                 if !possibilities.is_empty() {
-                    let mut possibilities =
-                        possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-                    possibilities.sort();
-                    let possibilities = possibilities.join("`, `");
-
-                    // The list of expected names can be long (even by default) and
-                    // so the diagnostic produced can take a lot of space. To avoid
-                    // cloging the user output we only want to print that diagnostic
-                    // once.
-                    diag.help_once(format!("expected names are: `{possibilities}`"));
+                    diag.help_once(check_cfg_expected_note(
+                        sess,
+                        &possibilities,
+                        "names",
+                        None,
+                        "",
+                    ));
                 }
             }
 
@@ -338,16 +372,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
             // Show the full list if all possible values for a given name, but don't do it
             // for names as the possibilities could be very long
             if !possibilities.is_empty() {
-                {
-                    let mut possibilities =
-                        possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-                    possibilities.sort();
-
-                    let possibilities = possibilities.join("`, `");
-                    let none = if have_none_possibility { "(none), " } else { "" };
-
-                    diag.note(format!("expected values for `{name}` are: {none}`{possibilities}`"));
-                }
+                diag.note(check_cfg_expected_note(
+                    sess,
+                    &possibilities,
+                    "values",
+                    Some(name),
+                    if have_none_possibility { "(none), " } else { "" },
+                ));
 
                 if let Some((value, value_span)) = value {
                     // Suggest the most probable if we found one
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 8b48570fbba..0d37c0feb0c 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1132,7 +1132,13 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
             Err(err) => {
                 // Only try to recover from this specific error.
                 if !matches!(err, libloading::Error::LoadLibraryExW { .. }) {
-                    return Err(err.to_string());
+                    let err = format_dlopen_err(&err);
+                    // We include the path of the dylib in the error ourselves, so
+                    // if it's in the error, we strip it.
+                    if let Some(err) = err.strip_prefix(&format!(": {}", path.display())) {
+                        return Err(err.to_string());
+                    }
+                    return Err(err);
                 }
 
                 last_error = Some(err);
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 8357c21a3c2..b0431ae05d3 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -344,15 +344,6 @@ rustc_queries! {
         }
     }
 
-    query impl_trait_in_assoc_types_defined_by(
-        key: LocalDefId
-    ) -> &'tcx ty::List<LocalDefId> {
-        desc {
-            |tcx| "computing the opaque types defined by `{}`",
-            tcx.def_path_str(key.to_def_id())
-        }
-    }
-
     /// Returns the list of bounds that can be used for
     /// `SelectionCandidate::ProjectionCandidate(_)` and
     /// `ProjectionTyCandidate::TraitDef`.
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 0cd925c5ba6..6647a9a2792 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -8,8 +8,8 @@ use crate::errors::{
     ItemsInTraitsAreNotImportable,
 };
 use crate::Determinacy::{self, *};
-use crate::Namespace::*;
 use crate::{module_to_string, names_to_string, ImportSuggestion};
+use crate::{AmbiguityError, Namespace::*};
 use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment};
 use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
 use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used};
@@ -538,7 +538,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             .chain(indeterminate_imports.iter().map(|i| (true, i)))
         {
             let unresolved_import_error = self.finalize_import(*import);
-
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
             self.import_dummy_binding(*import, is_indeterminate);
@@ -856,7 +855,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
             _ => None,
         };
-        let prev_ambiguity_errors_len = self.ambiguity_errors.len();
+        let ambiguity_errors_len =
+            |errors: &Vec<AmbiguityError<'_>>| errors.iter().filter(|error| !error.warning).count();
+        let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);
         let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
 
         // We'll provide more context to the privacy errors later, up to `len`.
@@ -870,7 +871,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ignore_binding,
         );
 
-        let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
+        let no_ambiguity =
+            ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
         import.vis.set(orig_vis);
         let module = match path_res {
             PathResult::Module(module) => {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 42c9d5e10eb..55e1556cdf8 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1565,6 +1565,8 @@ options! {
         "set options for branch target identification and pointer authentication on AArch64"),
     cf_protection: CFProtection = (CFProtection::None, parse_cfprotection, [TRACKED],
         "instrument control-flow architecture protection"),
+    check_cfg_all_expected: bool = (false, parse_bool, [UNTRACKED],
+        "show all expected values in check-cfg diagnostics (default: no)"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
     collapse_macro_debuginfo: CollapseMacroDebuginfo = (CollapseMacroDebuginfo::Unspecified,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 25b5422f322..506bd5d5dbd 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -265,14 +265,20 @@ impl ParseSess {
         }
     }
 
-    pub fn with_silent_emitter(fatal_note: String) -> Self {
-        let fallback_bundle = fallback_fluent_bundle(Vec::new(), false);
+    pub fn with_silent_emitter(locale_resources: Vec<&'static str>, fatal_note: String) -> Self {
+        let fallback_bundle = fallback_fluent_bundle(locale_resources, false);
         let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-        let emitter =
-            Box::new(HumanEmitter::new(stderr_destination(ColorConfig::Auto), fallback_bundle));
+        let emitter = Box::new(HumanEmitter::new(
+            stderr_destination(ColorConfig::Auto),
+            fallback_bundle.clone(),
+        ));
         let fatal_dcx = DiagCtxt::new(emitter);
-        let dcx =
-            DiagCtxt::new(Box::new(SilentEmitter { fatal_dcx, fatal_note })).disable_warnings();
+        let dcx = DiagCtxt::new(Box::new(SilentEmitter {
+            fallback_bundle,
+            fatal_dcx,
+            fatal_note: Some(fatal_note),
+        }))
+        .disable_warnings();
         ParseSess::with_dcx(dcx, sm)
     }
 
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index aaf968cbb75..c6448b4f661 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -33,7 +33,11 @@ enum CollectionMode {
 }
 
 impl<'tcx> OpaqueTypeCollector<'tcx> {
-    fn new(tcx: TyCtxt<'tcx>, item: LocalDefId, mode: CollectionMode) -> Self {
+    fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
+        let mode = match tcx.def_kind(tcx.local_parent(item)) {
+            DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes,
+            _ => CollectionMode::TypeAliasImplTraitTransition,
+        };
         Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode }
     }
 
@@ -284,23 +288,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
     }
 }
 
-fn impl_trait_in_assoc_types_defined_by<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    item: LocalDefId,
-) -> &'tcx ty::List<LocalDefId> {
-    let mut collector = OpaqueTypeCollector::new(tcx, item, CollectionMode::ImplTraitInAssocTypes);
-    super::sig_types::walk_types(tcx, item, &mut collector);
-    tcx.mk_local_def_ids(&collector.opaques)
-}
-
 fn opaque_types_defined_by<'tcx>(
     tcx: TyCtxt<'tcx>,
     item: LocalDefId,
 ) -> &'tcx ty::List<LocalDefId> {
     let kind = tcx.def_kind(item);
     trace!(?kind);
-    let mut collector =
-        OpaqueTypeCollector::new(tcx, item, CollectionMode::TypeAliasImplTraitTransition);
+    let mut collector = OpaqueTypeCollector::new(tcx, item);
     super::sig_types::walk_types(tcx, item, &mut collector);
     match kind {
         DefKind::AssocFn
@@ -343,6 +337,5 @@ fn opaque_types_defined_by<'tcx>(
 }
 
 pub(super) fn provide(providers: &mut Providers) {
-    *providers =
-        Providers { opaque_types_defined_by, impl_trait_in_assoc_types_defined_by, ..*providers };
+    *providers = Providers { opaque_types_defined_by, ..*providers };
 }