migrate check_const.rs to translateable diagnostics
This commit is contained in:
parent
c457abee2e
commit
572f3414b7
3 changed files with 54 additions and 4 deletions
|
@ -426,3 +426,10 @@ passes_feature_stable_twice =
|
||||||
|
|
||||||
passes_feature_previously_declared =
|
passes_feature_previously_declared =
|
||||||
feature `{$feature}` is declared {$declared}, but was previously declared {$prev_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]`
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
//! through, but errors for structured control flow in a `const` should be emitted here.
|
//! through, but errors for structured control flow in a `const` should be emitted here.
|
||||||
|
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_errors::struct_span_err;
|
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
|
@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::{sym, Span, Symbol};
|
use rustc_span::{sym, Span, Symbol};
|
||||||
|
|
||||||
|
use crate::errors::{ConstImplConstTrait, ExprNotAllowedInContext};
|
||||||
|
|
||||||
/// An expression that is not *always* legal in a const context.
|
/// An expression that is not *always* legal in a const context.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum NonConstExpr {
|
enum NonConstExpr {
|
||||||
|
@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> {
|
||||||
let const_kind =
|
let const_kind =
|
||||||
const_kind.expect("`const_check_violated` may only be called inside a const context");
|
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 required_gates = required_gates.unwrap_or(&[]);
|
||||||
let missing_gates: Vec<_> =
|
let missing_gates: Vec<_> =
|
||||||
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
|
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
|
||||||
|
|
||||||
match missing_gates.as_slice() {
|
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 @ ..] => {
|
[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);
|
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
|
// 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()
|
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) {
|
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
|
||||||
let kind = Some(hir::ConstContext::Const);
|
let kind = Some(hir::ConstContext::Const);
|
||||||
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
|
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
|
||||||
|
|
|
@ -852,3 +852,21 @@ pub struct FeaturePreviouslyDeclared<'a, 'b> {
|
||||||
pub declared: &'a str,
|
pub declared: &'a str,
|
||||||
pub prev_declared: &'b 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,
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue