Improve error messages even more
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
¶m_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,
|
||||
|
||||
Reference in New Issue
Block a user