Improve error messages even more

This commit is contained in:
Deadbeef
2021-12-09 22:42:17 +08:00
parent 1b0dcdc341
commit f7f0f843b7
10 changed files with 433 additions and 238 deletions

View File

@@ -293,13 +293,13 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
}
/// Emits an error if an expression cannot be evaluated in the current context.
pub fn check_op(&mut self, op: impl NonConstOp) {
pub fn check_op(&mut self, op: impl NonConstOp<'tcx>) {
self.check_op_spanned(op, self.span);
}
/// Emits an error at the given `span` if an expression cannot be evaluated in the current
/// context.
pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
pub fn check_op_spanned<O: NonConstOp<'tcx>>(&mut self, op: O, span: Span) {
let gate = match op.status_in_item(self.ccx) {
Status::Allowed => return,
@@ -773,7 +773,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.super_terminator(terminator, location);
match &terminator.kind {
TerminatorKind::Call { func, args, .. } => {
TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => {
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
let caller = self.def_id().to_def_id();
@@ -797,7 +797,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if let Some(trait_id) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method");
if !self.tcx.features().const_trait_impl {
self.check_op(ops::FnCallNonConst(callee, substs));
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
@@ -856,7 +862,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(callee, substs));
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
}
@@ -925,7 +937,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(callee, substs));
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
}

View File

@@ -3,14 +3,20 @@
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::{mir, ty::AssocKind};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Param, TraitPredicate, Ty};
use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{symbol::Ident, Span, Symbol};
use rustc_span::{BytePos, Pos};
use rustc_span::{BytePos, Pos, Span, Symbol};
use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
use crate::util::{call_kind, CallDesugaringKind, CallKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
@@ -29,9 +35,9 @@ pub enum DiagnosticImportance {
}
/// An operation that is not *always* allowed in a const context.
pub trait NonConstOp: std::fmt::Debug {
pub trait NonConstOp<'tcx>: std::fmt::Debug {
/// Returns an enum indicating whether this operation is allowed within the given item.
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Forbidden
}
@@ -39,13 +45,13 @@ pub trait NonConstOp: std::fmt::Debug {
DiagnosticImportance::Primary
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>;
}
#[derive(Debug)]
pub struct FloatingPointOp;
impl NonConstOp for FloatingPointOp {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for FloatingPointOp {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() == hir::ConstContext::ConstFn {
Status::Unstable(sym::const_fn_floating_point_arithmetic)
} else {
@@ -53,7 +59,7 @@ impl NonConstOp for FloatingPointOp {
}
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_floating_point_arithmetic,
@@ -66,40 +72,120 @@ impl NonConstOp for FloatingPointOp {
/// A function call where the callee is a pointer.
#[derive(Debug)]
pub struct FnCallIndirect;
impl NonConstOp for FnCallIndirect {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn")
}
}
/// A function call where the callee is not marked as `const`.
#[derive(Debug)]
pub struct FnCallNonConst<'tcx>(pub DefId, pub SubstsRef<'tcx>);
impl<'a> NonConstOp for FnCallNonConst<'a> {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let FnCallNonConst(def_id, substs) = *self;
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"cannot call non-const fn `{}` in {}s",
ccx.tcx.def_path_str_with_substs(def_id, substs),
ccx.const_kind()
);
err.note(&format!(
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
ccx.const_kind(),
));
#[derive(Debug, Clone, Copy)]
pub struct FnCallNonConst<'tcx> {
pub caller: DefId,
pub callee: DefId,
pub substs: SubstsRef<'tcx>,
pub span: Span,
pub from_hir_call: bool,
}
if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() {
if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind(
ccx.tcx,
Ident::with_dummy_span(sym::eq),
AssocKind::Fn,
trait_def_id,
) {
if callee == eq_item.def_id && substs.len() == 2 {
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> DiagnosticBuilder<'tcx> {
let FnCallNonConst { caller, callee, substs, span, from_hir_call } = *self;
let ConstCx { tcx, param_env, .. } = *ccx;
let diag_trait = |mut err, self_ty: Ty<'_>, trait_id| {
let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
match self_ty.kind() {
Param(param_ty) => {
debug!(?param_ty);
if let Some(generics) = caller
.as_local()
.map(|id| tcx.hir().local_def_id_to_hir_id(id))
.map(|id| tcx.hir().get(id))
.as_ref()
.and_then(|node| node.generics())
{
let constraint = with_no_trimmed_paths(|| {
format!("~const {}", trait_ref.print_only_trait_path())
});
suggest_constraining_type_param(
tcx,
generics,
&mut err,
&param_ty.name.as_str(),
&constraint,
None,
);
}
}
Adt(..) => {
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
Binder::dummy(TraitPredicate {
trait_ref,
constness: BoundConstness::ConstIfConst,
polarity: ImplPolarity::Positive,
}),
);
let implsrc = tcx.infer_ctxt().enter(|infcx| {
let mut selcx = SelectionContext::new(&infcx);
selcx.select(&obligation)
});
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
let span =
tcx.sess.source_map().guess_head_span(tcx.def_span(data.impl_def_id));
err.span_note(span, "impl defined here, but it is not `const`");
}
}
_ => {}
}
err
};
let call_kind = call_kind(tcx, ccx.param_env, callee, substs, span, from_hir_call, None);
debug!(?call_kind);
let mut err = match call_kind {
CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
macro_rules! error {
($fmt:literal) => {
struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind(),)
};
}
let err = match kind {
CallDesugaringKind::ForLoopIntoIter => {
error!("cannot convert `{}` into an iterator in {}s")
}
CallDesugaringKind::QuestionBranch => {
error!("`?` cannot determine the branch of `{}` in {}s")
}
CallDesugaringKind::QuestionFromResidual => {
error!("`?` cannot convert from residual of `{}` in {}s")
}
CallDesugaringKind::TryBlockFromOutput => {
error!("`try` block cannot convert `{}` to the result in {}s")
}
};
diag_trait(err, self_ty, kind.trait_def_id(tcx))
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut err = struct_span_err!(
tcx.sess,
span,
E0015,
"cannot call non-const operator in {}s",
ccx.const_kind()
);
if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
match (substs[0].unpack(), substs[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
@@ -137,8 +223,43 @@ impl<'a> NonConstOp for FnCallNonConst<'a> {
_ => {}
}
}
diag_trait(err, self_ty, trait_id)
}
}
CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
let mut err = struct_span_err!(
tcx.sess,
span,
E0015,
"cannot perform deref coercion on `{}` in {}s",
self_ty,
ccx.const_kind()
);
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() {
err.span_note(deref_target, "deref defined here");
}
diag_trait(err, self_ty, tcx.lang_items().deref_trait().unwrap())
}
_ => struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"cannot call non-const fn `{}` in {}s",
ccx.tcx.def_path_str_with_substs(callee, substs),
ccx.const_kind(),
),
};
err.note(&format!(
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
ccx.const_kind(),
));
err
}
@@ -150,8 +271,8 @@ impl<'a> NonConstOp for FnCallNonConst<'a> {
#[derive(Debug)]
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
impl NonConstOp for FnCallUnstable {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let FnCallUnstable(def_id, feature) = *self;
let mut err = ccx.tcx.sess.struct_span_err(
@@ -176,8 +297,8 @@ impl NonConstOp for FnCallUnstable {
#[derive(Debug)]
pub struct FnPtrCast;
impl NonConstOp for FnPtrCast {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for FnPtrCast {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
@@ -185,7 +306,7 @@ impl NonConstOp for FnPtrCast {
}
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
@@ -197,8 +318,8 @@ impl NonConstOp for FnPtrCast {
#[derive(Debug)]
pub struct Generator(pub hir::GeneratorKind);
impl NonConstOp for Generator {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for Generator {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
Status::Unstable(sym::const_async_blocks)
} else {
@@ -206,7 +327,7 @@ impl NonConstOp for Generator {
}
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg)
@@ -218,8 +339,8 @@ impl NonConstOp for Generator {
#[derive(Debug)]
pub struct HeapAllocation;
impl NonConstOp for HeapAllocation {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
@@ -242,8 +363,8 @@ impl NonConstOp for HeapAllocation {
#[derive(Debug)]
pub struct InlineAsm;
impl NonConstOp for InlineAsm {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for InlineAsm {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
struct_span_err!(
ccx.tcx.sess,
span,
@@ -258,8 +379,8 @@ impl NonConstOp for InlineAsm {
pub struct LiveDrop {
pub dropped_at: Option<Span>,
}
impl NonConstOp for LiveDrop {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for LiveDrop {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
@@ -278,8 +399,8 @@ impl NonConstOp for LiveDrop {
/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to
/// the final value of the constant.
pub struct TransientCellBorrow;
impl NonConstOp for TransientCellBorrow {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_refs_to_cell)
}
fn importance(&self) -> DiagnosticImportance {
@@ -287,7 +408,7 @@ impl NonConstOp for TransientCellBorrow {
// not additionally emit a feature gate error if activating the feature gate won't work.
DiagnosticImportance::Secondary
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_refs_to_cell,
@@ -302,8 +423,8 @@ impl NonConstOp for TransientCellBorrow {
/// the final value of the constant, and thus we cannot allow this (for now). We may allow
/// it in the future for static items.
pub struct CellBorrow;
impl NonConstOp for CellBorrow {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for CellBorrow {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
@@ -339,8 +460,8 @@ impl NonConstOp for CellBorrow {
/// static or const items.
pub struct MutBorrow(pub hir::BorrowKind);
impl NonConstOp for MutBorrow {
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for MutBorrow {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Forbidden
}
@@ -350,7 +471,7 @@ impl NonConstOp for MutBorrow {
DiagnosticImportance::Secondary
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let raw = match self.0 {
hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "",
@@ -384,12 +505,12 @@ impl NonConstOp for MutBorrow {
#[derive(Debug)]
pub struct TransientMutBorrow(pub hir::BorrowKind);
impl NonConstOp for TransientMutBorrow {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for TransientMutBorrow {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let raw = match self.0 {
hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "",
@@ -406,8 +527,8 @@ impl NonConstOp for TransientMutBorrow {
#[derive(Debug)]
pub struct MutDeref;
impl NonConstOp for MutDeref {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for MutDeref {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}
@@ -416,7 +537,7 @@ impl NonConstOp for MutDeref {
DiagnosticImportance::Secondary
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_mut_refs,
@@ -429,8 +550,8 @@ impl NonConstOp for MutDeref {
/// A call to a `panic()` lang item where the first argument is _not_ a `&str`.
#[derive(Debug)]
pub struct PanicNonStr;
impl NonConstOp for PanicNonStr {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for PanicNonStr {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
ccx.tcx.sess.struct_span_err(
span,
"argument to `panic!()` in a const context must have type `&str`",
@@ -443,8 +564,8 @@ impl NonConstOp for PanicNonStr {
/// allocation base addresses that are not known at compile-time.
#[derive(Debug)]
pub struct RawPtrComparison;
impl NonConstOp for RawPtrComparison {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = ccx
.tcx
.sess
@@ -459,12 +580,12 @@ impl NonConstOp for RawPtrComparison {
#[derive(Debug)]
pub struct RawMutPtrDeref;
impl NonConstOp for RawMutPtrDeref {
impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_mut_refs)
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_mut_refs,
@@ -479,8 +600,8 @@ impl NonConstOp for RawMutPtrDeref {
/// allocation base addresses that are not known at compile-time.
#[derive(Debug)]
pub struct RawPtrToIntCast;
impl NonConstOp for RawPtrToIntCast {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for RawPtrToIntCast {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = ccx
.tcx
.sess
@@ -496,8 +617,8 @@ impl NonConstOp for RawPtrToIntCast {
/// An access to a (non-thread-local) `static`.
#[derive(Debug)]
pub struct StaticAccess;
impl NonConstOp for StaticAccess {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for StaticAccess {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if let hir::ConstContext::Static(_) = ccx.const_kind() {
Status::Allowed
} else {
@@ -505,7 +626,7 @@ impl NonConstOp for StaticAccess {
}
}
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
@@ -530,8 +651,8 @@ impl NonConstOp for StaticAccess {
/// An access to a thread-local `static`.
#[derive(Debug)]
pub struct ThreadLocalAccess;
impl NonConstOp for ThreadLocalAccess {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
struct_span_err!(
ccx.tcx.sess,
span,
@@ -548,8 +669,8 @@ pub mod ty {
#[derive(Debug)]
pub struct MutRef(pub mir::LocalKind);
impl NonConstOp for MutRef {
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for MutRef {
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_mut_refs)
}
@@ -562,11 +683,7 @@ pub mod ty {
}
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_mut_refs,
@@ -578,7 +695,7 @@ pub mod ty {
#[derive(Debug)]
pub struct FnPtr(pub mir::LocalKind);
impl NonConstOp for FnPtr {
impl<'tcx> NonConstOp<'tcx> for FnPtr {
fn importance(&self) -> DiagnosticImportance {
match self.0 {
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
@@ -588,7 +705,7 @@ pub mod ty {
}
}
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
@@ -596,11 +713,7 @@ pub mod ty {
}
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_fn_ptr_basics,
@@ -612,16 +725,12 @@ pub mod ty {
#[derive(Debug)]
pub struct ImplTrait;
impl NonConstOp for ImplTrait {
impl<'tcx> NonConstOp<'tcx> for ImplTrait {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_impl_trait)
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_impl_trait,
@@ -633,7 +742,7 @@ pub mod ty {
#[derive(Debug)]
pub struct TraitBound(pub mir::LocalKind);
impl NonConstOp for TraitBound {
impl<'tcx> NonConstOp<'tcx> for TraitBound {
fn importance(&self) -> DiagnosticImportance {
match self.0 {
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
@@ -643,7 +752,7 @@ pub mod ty {
}
}
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
@@ -651,11 +760,7 @@ pub mod ty {
}
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound,
@@ -676,7 +781,7 @@ pub mod ty {
#[derive(Debug)]
pub struct DynTrait(pub mir::LocalKind);
impl NonConstOp for DynTrait {
impl<'tcx> NonConstOp<'tcx> for DynTrait {
fn importance(&self) -> DiagnosticImportance {
match self.0 {
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
@@ -686,7 +791,7 @@ pub mod ty {
}
}
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
fn status_in_item(&self, ccx: &ConstCx<'_, 'tcx>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
@@ -694,11 +799,7 @@ pub mod ty {
}
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_fn_trait_bound,
@@ -720,16 +821,12 @@ pub mod ty {
/// A trait bound with the `?const Trait` opt-out
#[derive(Debug)]
pub struct TraitBoundNotConst;
impl NonConstOp for TraitBoundNotConst {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
impl<'tcx> NonConstOp<'tcx> for TraitBoundNotConst {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
Status::Unstable(sym::const_trait_bound_opt_out)
}
fn build_error<'tcx>(
&self,
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_trait_bound_opt_out,