From 1c26a278f30a173a47606695211b586451396fbf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 25 Oct 2022 18:28:04 +0000 Subject: [PATCH] Split diagnostic details out into a separate function and fluent files --- .../locales/en-US/hir_analysis.ftl | 9 ++++ .../rustc_hir_analysis/src/astconv/mod.rs | 5 +- compiler/rustc_hir_analysis/src/collect.rs | 48 ++++++++++--------- compiler/rustc_hir_analysis/src/errors.rs | 21 ++++++++ 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl index 357c6900a70e5..7ac44312695d9 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl @@ -137,3 +137,12 @@ hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(l hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function + +hir_analysis_const_impl_for_non_const_trait = + const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]` + .suggestion = mark `{$trait_name}` as const + .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const` + .adding = adding a non-const method body in the future would be a breaking change + +hir_analysis_const_bound_for_non_const_trait = + ~const can only be applied to `#[const_trait]` traits diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index a4ebe38b02ec2..6baf98449775d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -539,10 +539,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(ty::BoundConstness::ConstIfConst) = constness && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) { - tcx.sess.span_err( - span, - "~const can only be applied to `#[const_trait]` traits", - ); + tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } ); } (substs, arg_count) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 0698ec7c4d021..e261bb07f9545 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1294,34 +1294,38 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { &icx, ast_trait_ref, selfty, - match impl_.constness { - hir::Constness::Const => { - if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { - let trait_name = tcx.item_name(trait_def_id); - let mut err = tcx.sess.struct_span_err( - ast_trait_ref.path.span, - &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"), - ); - if trait_def_id.is_local() { - let sp = tcx.def_span(trait_def_id).shrink_to_lo(); - err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable); - } - err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`"); - err.note("adding a non-const method body in the future would be a breaking change"); - err.emit(); - ty::BoundConstness::NotConst - } else { - ty::BoundConstness::ConstIfConst - } - }, - hir::Constness::NotConst => ty::BoundConstness::NotConst, - }, + check_impl_constness(tcx, impl_.constness, ast_trait_ref), ) }), _ => bug!(), } } +fn check_impl_constness( + tcx: TyCtxt<'_>, + constness: hir::Constness, + ast_trait_ref: &hir::TraitRef<'_>, +) -> ty::BoundConstness { + match constness { + hir::Constness::Const => { + if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) { + let trait_name = tcx.item_name(trait_def_id).to_string(); + tcx.sess.emit_err(errors::ConstImplForNonConstTrait { + trait_ref_span: ast_trait_ref.path.span, + trait_name, + local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()), + marking: (), + adding: (), + }); + ty::BoundConstness::NotConst + } else { + ty::BoundConstness::ConstIfConst + } + }, + hir::Constness::NotConst => ty::BoundConstness::NotConst, + } +} + fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(def_id.expect_local()); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 9457da32ce65a..bd0c1f5dd1098 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -249,3 +249,24 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_impl_for_non_const_trait)] +pub struct ConstImplForNonConstTrait { + #[primary_span] + pub trait_ref_span: Span, + pub trait_name: String, + #[suggestion(applicability = "machine-applicable", code = "#[const_trait]")] + pub local_trait_span: Option, + #[note] + pub marking: (), + #[note(adding)] + pub adding: (), +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_const_bound_for_non_const_trait)] +pub struct ConstBoundForNonConstTrait { + #[primary_span] + pub span: Span, +}