From 572f3414b782311a8ec4143c50bbe3b006594898 Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Sat, 24 Sep 2022 12:49:29 -0600 Subject: [PATCH] migrate check_const.rs to translateable diagnostics --- .../locales/en-US/passes.ftl | 7 ++++ compiler/rustc_passes/src/check_const.rs | 33 ++++++++++++++++--- compiler/rustc_passes/src/errors.rs | 18 ++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index b2c54aaccfe..550096469bb 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -426,3 +426,10 @@ passes_feature_stable_twice = passes_feature_previously_declared = feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared} + +passes_expr_not_allowed_in_context = + {$expr} is not allowed in a `{$context}` + +passes_const_impl_const_trait = + const `impl`s must be for traits marked with `#[const_trait]` + .note = this trait must be annotated with `#[const_trait]` diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index e502b9b54e3..0a509598ec5 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -8,7 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc_attr as attr; -use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; @@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt; use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; +use crate::errors::{ConstImplConstTrait, ExprNotAllowedInContext}; + /// An expression that is not *always* legal in a const context. #[derive(Clone, Copy)] enum NonConstExpr { @@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> { let const_kind = const_kind.expect("`const_check_violated` may only be called inside a const context"); - let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); - let required_gates = required_gates.unwrap_or(&[]); let missing_gates: Vec<_> = required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect(); match missing_gates.as_slice() { [] => { - struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(); + tcx.sess.emit_err(ExprNotAllowedInContext { + span, + expr: expr.name(), + context: const_kind.keyword_name(), + }); } [missing_primary, ref missing_secondary @ ..] => { + let msg = + format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name()); let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg); // If multiple feature gates would be required to enable this expression, include @@ -191,6 +196,26 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { self.tcx.hir() } + fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { + let tcx = self.tcx; + if let hir::ItemKind::Impl(hir::Impl { + constness: hir::Constness::Const, + of_trait: Some(trait_ref), + .. + }) = item.kind + && let Some(def_id) = trait_ref.trait_def_id() + { + let source_map = tcx.sess.source_map(); + if !tcx.has_attr(def_id, sym::const_trait) { + tcx.sess.emit_err(ConstImplConstTrait { + span: source_map.guess_head_span(item.span), + def_span: source_map.guess_head_span(tcx.def_span(def_id)), + }); + } + } + intravisit::walk_item(self, item); + } + fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { let kind = Some(hir::ConstContext::Const); self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 7c3a575242f..fe169c566f6 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -852,3 +852,21 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> { pub declared: &'a str, pub prev_declared: &'b str, } + +#[derive(Diagnostic)] +#[diag(passes::expr_not_allowed_in_context, code = "E0744")] +pub struct ExprNotAllowedInContext<'a> { + #[primary_span] + pub span: Span, + pub expr: String, + pub context: &'a str, +} + +#[derive(Diagnostic)] +#[diag(passes::const_impl_const_trait)] +pub struct ConstImplConstTrait { + #[primary_span] + pub span: Span, + #[note] + pub def_span: Span, +}