about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-11 12:16:20 +0000
committerbors <bors@rust-lang.org>2022-07-11 12:16:20 +0000
commit9fb32dc924653e35950f17c8d91793c9ca983d03 (patch)
tree0ffdaaeb8d72a455d04db05cf326c8c77386fbb3 /compiler
parent7d1f57a757af4fe5d47a6f6d3167761ec61b7894 (diff)
parent21d6b1fc0e7f0bfd7296445b0ab2d29497b9929d (diff)
downloadrust-9fb32dc924653e35950f17c8d91793c9ca983d03.tar.gz
rust-9fb32dc924653e35950f17c8d91793c9ca983d03.zip
Auto merge of #99151 - Dylan-DPC:rollup-40aqkxy, r=Dylan-DPC
Rollup of 5 pull requests

Successful merges:

 - #98882 (explain doc comments in macros a bit)
 - #98907 (Deny float const params even when `adt_const_params` is enabled)
 - #99091 (Do not mention private types from other crates as impl candidates)
 - #99140 (Implement `SourceMap::is_span_accessible`)
 - #99147 (Mention similarly named associated type even if it's not clearly in supertrait)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs9
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/expand.ftl5
-rw-r--r--compiler/rustc_error_messages/src/lib.rs3
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs38
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs57
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_span/src/source_map.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs22
-rw-r--r--compiler/rustc_typeck/src/astconv/errors.rs56
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs4
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs86
-rw-r--r--compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs2
18 files changed, 235 insertions, 90 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index b9cfc3732dc..687ff0fb505 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -309,7 +309,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ));
 
                 // Check first whether the source is accessible (issue #87060)
-                if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
+                if self.infcx.tcx.sess.source_map().is_span_accessible(deref_target) {
                     err.span_note(deref_target, "deref defined here");
                 }
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index d296a1a0ac6..9c7671eee38 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -975,14 +975,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     if self.fn_self_span_reported.insert(fn_span) {
                         err.span_note(
                             // Check whether the source is accessible
-                            if self
-                                .infcx
-                                .tcx
-                                .sess
-                                .source_map()
-                                .span_to_snippet(self_arg.span)
-                                .is_ok()
-                            {
+                            if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) {
                                 self_arg.span
                             } else {
                                 fn_call_span
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 17376e59e09..1d083b0bf82 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -299,7 +299,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 err.note(&format!("attempting to deref into `{}`", deref_target_ty));
 
                 // Check first whether the source is accessible (issue #87060)
-                if tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
+                if tcx.sess.source_map().is_span_accessible(deref_target) {
                     err.span_note(deref_target, "deref defined here");
                 }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 6e5a0c813ac..0aa7b117b89 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -226,7 +226,7 @@ impl Qualif for CustomEq {
         // because that component may be part of an enum variant (e.g.,
         // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
         // structural-match (`Option::None`).
-        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
+        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty, true).is_some()
     }
 
     fn in_adt_inherently<'tcx>(
diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_error_messages/locales/en-US/expand.ftl
new file mode 100644
index 00000000000..8d506a3ea8b
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl
@@ -0,0 +1,5 @@
+expand-explain-doc-comment-outer =
+    outer doc comments expand to `#[doc = "..."]`, which is what this macro attempted to match
+
+expand-explain-doc-comment-inner =
+    inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 5a482bc5b2c..d16171cb162 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -33,11 +33,12 @@ pub use unic_langid::{langid, LanguageIdentifier};
 fluent_messages! {
     borrowck => "../locales/en-US/borrowck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
+    const_eval => "../locales/en-US/const_eval.ftl",
+    expand => "../locales/en-US/expand.ftl",
     lint => "../locales/en-US/lint.ftl",
     parser => "../locales/en-US/parser.ftl",
     privacy => "../locales/en-US/privacy.ftl",
     typeck => "../locales/en-US/typeck.ftl",
-    const_eval => "../locales/en-US/const_eval.ftl",
 }
 
 pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES};
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index ffe4ecebb2e..e59a74e380a 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1558,7 +1558,7 @@ pub fn add_elided_lifetime_in_path_suggestion(
     insertion_span: Span,
 ) {
     diag.span_label(path_span, format!("expected lifetime parameter{}", pluralize!(n)));
-    if source_map.span_to_snippet(insertion_span).is_err() {
+    if !source_map.is_span_accessible(insertion_span) {
         // Do not try to suggest anything if generated by a proc-macro.
         return;
     }
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index f40c365cbcc..3e9ddd6aec0 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, TransparencyError};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_feature::Features;
 use rustc_lint_defs::builtin::{
     RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
@@ -25,6 +25,7 @@ use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
+use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent};
 use rustc_span::Span;
 
@@ -345,7 +346,7 @@ fn expand_macro<'cx>(
     if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
     }
-
+    annotate_doc_comment(&mut err, sess.source_map(), span);
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
     if let Some((arg, comma_span)) = arg.add_comma() {
         for lhs in lhses {
@@ -453,7 +454,10 @@ pub fn compile_declarative_macro(
         Failure(token, msg) => {
             let s = parse_failure_msg(&token);
             let sp = token.span.substitute_dummy(def.span);
-            sess.parse_sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit();
+            let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s);
+            err.span_label(sp, msg);
+            annotate_doc_comment(&mut err, sess.source_map(), sp);
+            err.emit();
             return dummy_syn_ext();
         }
         Error(sp, msg) => {
@@ -590,6 +594,34 @@ pub fn compile_declarative_macro(
     (mk_syn_ext(expander), rule_spans)
 }
 
+#[derive(SessionSubdiagnostic)]
+enum ExplainDocComment {
+    #[label(expand::explain_doc_comment_inner)]
+    Inner {
+        #[primary_span]
+        span: Span,
+    },
+    #[label(expand::explain_doc_comment_outer)]
+    Outer {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+fn annotate_doc_comment(
+    err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+    sm: &SourceMap,
+    span: Span,
+) {
+    if let Ok(src) = sm.span_to_snippet(span) {
+        if src.starts_with("///") || src.starts_with("/**") {
+            err.subdiagnostic(ExplainDocComment::Outer { span });
+        } else if src.starts_with("//!") || src.starts_with("/*!") {
+            err.subdiagnostic(ExplainDocComment::Inner { span });
+        }
+    }
+}
+
 fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 61ac3d14e50..75fd156ebfd 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -432,7 +432,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                 "`let` bindings require an \"irrefutable pattern\", like a `struct` or \
                  an `enum` with only one variant",
             );
-            if self.tcx.sess.source_map().span_to_snippet(span).is_ok() {
+            if self.tcx.sess.source_map().is_span_accessible(span) {
                 let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
                 let start_span = span.shrink_to_lo();
                 let end_span = semi_span.shrink_to_lo();
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index f22f3f61a01..e32e0b11ba4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -120,32 +120,37 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
     }
 
     fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
-        traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
-            with_no_trimmed_paths!(match non_sm_ty.kind {
-                traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
-                traits::NonStructuralMatchTyKind::Dynamic => {
-                    "trait objects cannot be used in patterns".to_string()
-                }
-                traits::NonStructuralMatchTyKind::Opaque => {
-                    "opaque types cannot be used in patterns".to_string()
-                }
-                traits::NonStructuralMatchTyKind::Closure => {
-                    "closures cannot be used in patterns".to_string()
-                }
-                traits::NonStructuralMatchTyKind::Generator => {
-                    "generators cannot be used in patterns".to_string()
-                }
-                traits::NonStructuralMatchTyKind::Param => {
-                    bug!("use of a constant whose type is a parameter inside a pattern")
-                }
-                traits::NonStructuralMatchTyKind::Projection => {
-                    bug!("use of a constant whose type is a projection inside a pattern")
-                }
-                traits::NonStructuralMatchTyKind::Foreign => {
-                    bug!("use of a value of a foreign type inside a pattern")
-                }
-            })
-        })
+        traits::search_for_structural_match_violation(self.span, self.tcx(), ty, true).map(
+            |non_sm_ty| {
+                with_no_trimmed_paths!(match non_sm_ty.kind {
+                    traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
+                    traits::NonStructuralMatchTyKind::Dynamic => {
+                        "trait objects cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTyKind::Opaque => {
+                        "opaque types cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTyKind::Closure => {
+                        "closures cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTyKind::Generator => {
+                        "generators cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTyKind::Float => {
+                        "floating-point numbers cannot be used in patterns".to_string()
+                    }
+                    traits::NonStructuralMatchTyKind::Param => {
+                        bug!("use of a constant whose type is a parameter inside a pattern")
+                    }
+                    traits::NonStructuralMatchTyKind::Projection => {
+                        bug!("use of a constant whose type is a projection inside a pattern")
+                    }
+                    traits::NonStructuralMatchTyKind::Foreign => {
+                        bug!("use of a value of a foreign type inside a pattern")
+                    }
+                })
+            },
+        )
     }
 
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index b4a39982b74..2851b08cd93 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1647,7 +1647,7 @@ impl<'a> Resolver<'a> {
 
     fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
         let res = b.res();
-        if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() {
+        if b.span.is_dummy() || !self.session.source_map().is_span_accessible(b.span) {
             // These already contain the "built-in" prefix or look bad with it.
             let add_built_in =
                 !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 227127aed50..afbb88e9233 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -597,6 +597,13 @@ impl SourceMap {
         local_begin.sf.src.is_some() && local_end.sf.src.is_some()
     }
 
+    pub fn is_span_accessible(&self, sp: Span) -> bool {
+        self.span_to_source(sp, |src, start_index, end_index| {
+            Ok(src.get(start_index..end_index).is_some())
+        })
+        .map_or(false, |is_accessible| is_accessible)
+    }
+
     /// Returns the source snippet as `String` corresponding to the given `Span`.
     pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
         self.span_to_source(sp, |src, start_index, end_index| {
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..34f4a9f7902 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -673,6 +673,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             if !self.report_similar_impl_candidates(
                                 impl_candidates,
                                 trait_ref,
+                                obligation.cause.body_id,
                                 &mut err,
                             ) {
                                 // This is *almost* equivalent to
@@ -707,6 +708,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                                     self.report_similar_impl_candidates(
                                         impl_candidates,
                                         trait_ref,
+                                        obligation.cause.body_id,
                                         &mut err,
                                     );
                                 }
@@ -1353,6 +1355,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
         &self,
         impl_candidates: Vec<ImplCandidate<'tcx>>,
         trait_ref: ty::PolyTraitRef<'tcx>,
+        body_id: hir::HirId,
         err: &mut Diagnostic,
     ) -> bool;
 
@@ -1735,6 +1738,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
         &self,
         impl_candidates: Vec<ImplCandidate<'tcx>>,
         trait_ref: ty::PolyTraitRef<'tcx>,
+        body_id: hir::HirId,
         err: &mut Diagnostic,
     ) -> bool {
         let report = |mut candidates: Vec<TraitRef<'tcx>>, err: &mut Diagnostic| {
@@ -1805,8 +1809,24 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                         || self.tcx.is_builtin_derive(def_id)
                 })
                 .filter_map(|def_id| self.tcx.impl_trait_ref(def_id))
-                // Avoid mentioning type parameters.
-                .filter(|trait_ref| !matches!(trait_ref.self_ty().kind(), ty::Param(_)))
+                .filter(|trait_ref| {
+                    let self_ty = trait_ref.self_ty();
+                    // Avoid mentioning type parameters.
+                    if let ty::Param(_) = self_ty.kind() {
+                        false
+                    }
+                    // Avoid mentioning types that are private to another crate
+                    else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
+                        // FIXME(compiler-errors): This could be generalized, both to
+                        // be more granular, and probably look past other `#[fundamental]`
+                        // types, too.
+                        self.tcx
+                            .visibility(def.did())
+                            .is_accessible_from(body_id.owner.to_def_id(), self.tcx)
+                    } else {
+                        true
+                    }
+                })
                 .collect();
             return report(normalized_impl_candidates, err);
         }
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 94ca138b9d2..6c0b83fbd03 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -26,6 +26,7 @@ pub enum NonStructuralMatchTyKind<'tcx> {
     Closure,
     Generator,
     Projection,
+    Float,
 }
 
 /// This method traverses the structure of `ty`, trying to find an
@@ -53,12 +54,16 @@ pub enum NonStructuralMatchTyKind<'tcx> {
 /// For more background on why Rust has this requirement, and issues
 /// that arose when the requirement was not enforced completely, see
 /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
+///
+/// The floats_allowed flag is used to deny constants in floating point
 pub fn search_for_structural_match_violation<'tcx>(
     span: Span,
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
+    floats_allowed: bool,
 ) -> Option<NonStructuralMatchTy<'tcx>> {
-    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value()
+    ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), floats_allowed })
+        .break_value()
 }
 
 /// This method returns true if and only if `adt_ty` itself has been marked as
@@ -119,6 +124,8 @@ struct Search<'tcx> {
     /// Tracks ADTs previously encountered during search, so that
     /// we will not recur on them again.
     seen: FxHashSet<hir::def_id::DefId>,
+
+    floats_allowed: bool,
 }
 
 impl<'tcx> Search<'tcx> {
@@ -192,13 +199,24 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
                 // for empty array.
                 return ControlFlow::CONTINUE;
             }
-            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
+            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => {
                 // These primitive types are always structural match.
                 //
                 // `Never` is kind of special here, but as it is not inhabitable, this should be fine.
                 return ControlFlow::CONTINUE;
             }
 
+            ty::Float(_) => {
+                if self.floats_allowed {
+                    return ControlFlow::CONTINUE;
+                } else {
+                    return ControlFlow::Break(NonStructuralMatchTy {
+                        ty,
+                        kind: NonStructuralMatchTyKind::Float,
+                    });
+                }
+            }
+
             ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
                 // First check all contained types and then tell the caller to continue searching.
                 return ty.super_visit_with(self);
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs
index d111008e82c..c873cf27e42 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_typeck/src/astconv/errors.rs
@@ -164,10 +164,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 suggested_name,
                 Applicability::MaybeIncorrect,
             );
-        } else {
-            err.span_label(span, format!("associated type `{}` not found", assoc_name));
+            return err.emit();
         }
 
+        // If we didn't find a good item in the supertraits (or couldn't get
+        // the supertraits), like in ItemCtxt, then look more generally from
+        // all visible traits. If there's one clear winner, just suggest that.
+
+        let visible_traits: Vec<_> = self
+            .tcx()
+            .all_traits()
+            .filter(|trait_def_id| {
+                let viz = self.tcx().visibility(*trait_def_id);
+                if let Some(def_id) = self.item_def_id() {
+                    viz.is_accessible_from(def_id, self.tcx())
+                } else {
+                    viz.is_visible_locally()
+                }
+            })
+            .collect();
+
+        let wider_candidate_names: Vec<_> = visible_traits
+            .iter()
+            .flat_map(|trait_def_id| {
+                self.tcx().associated_items(*trait_def_id).in_definition_order()
+            })
+            .filter_map(
+                |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
+            )
+            .collect();
+
+        if let (Some(suggested_name), true) = (
+            find_best_match_for_name(&wider_candidate_names, assoc_name.name, None),
+            assoc_name.span != DUMMY_SP,
+        ) {
+            if let [best_trait] = visible_traits
+                .iter()
+                .filter(|trait_def_id| {
+                    self.tcx()
+                        .associated_items(*trait_def_id)
+                        .filter_by_name_unhygienic(suggested_name)
+                        .any(|item| item.kind == ty::AssocKind::Type)
+                })
+                .collect::<Vec<_>>()[..]
+            {
+                err.span_label(
+                    assoc_name.span,
+                    format!(
+                        "there is a similarly named associated type `{suggested_name}` in the trait `{}`",
+                        self.tcx().def_path_str(*best_trait)
+                    ),
+                );
+                return err.emit();
+            }
+        }
+
+        err.span_label(span, format!("associated type `{}` not found", assoc_name));
         err.emit()
     }
 
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index eb7e52c5ed3..dc553d1441e 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -760,7 +760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     if let Some(call_span) =
                         iter::successors(Some(expr.span), |s| s.parent_callsite())
                             .find(|&s| sp.contains(s))
-                        && sm.span_to_snippet(call_span).is_ok()
+                        && sm.is_span_accessible(call_span)
                     {
                         return Some((
                             sp.with_hi(call_span.lo()),
@@ -773,7 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     return None;
                 }
                 if sp.contains(expr.span)
-                    && sm.span_to_snippet(expr.span).is_ok()
+                    && sm.is_span_accessible(expr.span)
                 {
                     return Some((
                         sp.with_hi(expr.span.lo()),
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index f93f567fb20..5621cf2e1a4 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -824,50 +824,62 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                 }
 
                 if let Some(non_structural_match_ty) =
-                    traits::search_for_structural_match_violation(param.span, tcx, ty)
+                    traits::search_for_structural_match_violation(param.span, tcx, ty, false)
                 {
                     // We use the same error code in both branches, because this is really the same
                     // issue: we just special-case the message for type parameters to make it
                     // clearer.
-                    if let ty::Param(_) = ty.peel_refs().kind() {
-                        // Const parameters may not have type parameters as their types,
-                        // because we cannot be sure that the type parameter derives `PartialEq`
-                        // and `Eq` (just implementing them is not enough for `structural_match`).
-                        struct_span_err!(
-                            tcx.sess,
-                            hir_ty.span,
-                            E0741,
-                            "`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
-                            used as the type of a const parameter",
-                            ty,
-                        )
-                        .span_label(
-                            hir_ty.span,
-                            format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
-                        )
-                        .note(
-                            "it is not currently possible to use a type parameter as the type of a \
-                            const parameter",
-                        )
-                        .emit();
-                    } else {
-                        let mut diag = struct_span_err!(
-                            tcx.sess,
-                            hir_ty.span,
-                            E0741,
-                            "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
-                            the type of a const parameter",
-                            non_structural_match_ty.ty,
-                        );
-
-                        if ty == non_structural_match_ty.ty {
-                            diag.span_label(
+                    match ty.peel_refs().kind() {
+                        ty::Param(_) => {
+                            // Const parameters may not have type parameters as their types,
+                            // because we cannot be sure that the type parameter derives `PartialEq`
+                            // and `Eq` (just implementing them is not enough for `structural_match`).
+                            struct_span_err!(
+                                tcx.sess,
                                 hir_ty.span,
-                                format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
-                            );
+                                E0741,
+                                "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
+                                used as the type of a const parameter",
+                            )
+                            .span_label(
+                                hir_ty.span,
+                                format!("`{ty}` may not derive both `PartialEq` and `Eq`"),
+                            )
+                            .note(
+                                "it is not currently possible to use a type parameter as the type of a \
+                                const parameter",
+                            )
+                            .emit();
+                        }
+                        ty::Float(_) => {
+                            struct_span_err!(
+                                tcx.sess,
+                                hir_ty.span,
+                                E0741,
+                                "`{ty}` is forbidden as the type of a const generic parameter",
+                            )
+                            .note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
+                            .emit();
                         }
+                        _ => {
+                            let mut diag = struct_span_err!(
+                                tcx.sess,
+                                hir_ty.span,
+                                E0741,
+                                "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
+                                the type of a const parameter",
+                                non_structural_match_ty.ty,
+                            );
 
-                        diag.emit();
+                            if ty == non_structural_match_ty.ty {
+                                diag.span_label(
+                                    hir_ty.span,
+                                    format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
+                                );
+                            }
+
+                            diag.emit();
+                        }
                     }
                 }
             } else {
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
index 265a57c3929..469f7d1172a 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
@@ -812,7 +812,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
     /// Builds the `type defined here` message.
     fn show_definition(&self, err: &mut Diagnostic) {
         let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
-            if self.tcx.sess.source_map().span_to_snippet(def_span).is_ok() {
+            if self.tcx.sess.source_map().is_span_accessible(def_span) {
                 def_span.into()
             } else {
                 return;