diff options
| author | bors <bors@rust-lang.org> | 2022-07-11 12:16:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-07-11 12:16:20 +0000 |
| commit | 9fb32dc924653e35950f17c8d91793c9ca983d03 (patch) | |
| tree | 0ffdaaeb8d72a455d04db05cf326c8c77386fbb3 /compiler | |
| parent | 7d1f57a757af4fe5d47a6f6d3167761ec61b7894 (diff) | |
| parent | 21d6b1fc0e7f0bfd7296445b0ab2d29497b9929d (diff) | |
| download | rust-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')
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; |
