Rollup merge of #90532 - fee1-dead:improve-const-fn-err-msg, r=oli-obk

More informative error message for E0015

Helps with #92380
This commit is contained in:
Matthias Krüger 2022-02-13 06:44:13 +01:00 committed by GitHub
commit 953c4dcc30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 895 additions and 406 deletions

View File

@ -1,4 +1,5 @@
use either::Either;
use rustc_const_eval::util::{CallDesugaringKind, CallKind};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir;
@ -26,7 +27,7 @@ use crate::{
use super::{
explain_borrow::{BorrowExplanation, LaterUseKind},
FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
IncludingDowncast, RegionName, RegionNameSource, UseSpans,
};
#[derive(Debug)]
@ -195,7 +196,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "value".to_owned());
match kind {
FnSelfUseKind::FnOnceCall => {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.span_label(
fn_call_span,
&format!(
@ -208,7 +211,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"this value implements `FnOnce`, which causes it to be moved when called",
);
}
FnSelfUseKind::Operator { self_arg } => {
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
err.span_label(
fn_call_span,
&format!(
@ -235,12 +239,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
}
FnSelfUseKind::Normal {
self_arg,
implicit_into_iter,
is_option_or_result,
} => {
if implicit_into_iter {
CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
let self_arg = self_arg.unwrap();
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
err.span_label(
fn_call_span,
&format!(
@ -305,8 +306,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
}
// Deref::deref takes &self, which cannot cause a move
FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
// Other desugarings takes &self, which cannot cause a move
_ => unreachable!(),
}
} else {
err.span_label(
@ -433,7 +434,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
if let UseSpans::FnSelfUse {
kind: FnSelfUseKind::DerefCoercion { deref_target, deref_target_ty },
kind: CallKind::DerefCoercion { deref_target, deref_target_ty, .. },
..
} = use_spans
{

View File

@ -1,10 +1,10 @@
//! Borrow checker diagnostics.
use rustc_const_eval::util::call_kind;
use rustc_errors::DiagnosticBuilder;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItemGroup;
use rustc_hir::GeneratorKind;
use rustc_middle::mir::{
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
@ -13,7 +13,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::{hygiene::DesugaringKind, symbol::sym, Span};
use rustc_span::{symbol::sym, Span};
use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData;
@ -37,7 +37,7 @@ crate use mutability_errors::AccessKind;
crate use outlives_suggestion::OutlivesSuggestionBuilder;
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
crate use region_name::{RegionName, RegionNameSource};
use rustc_span::symbol::Ident;
crate use rustc_const_eval::util::CallKind;
pub(super) struct IncludingDowncast(pub(super) bool);
@ -563,7 +563,7 @@ pub(super) enum UseSpans<'tcx> {
fn_call_span: Span,
/// The definition span of the method being called
fn_span: Span,
kind: FnSelfUseKind<'tcx>,
kind: CallKind<'tcx>,
},
/// This access is caused by a `match` or `if let` pattern.
PatUse(Span),
@ -571,38 +571,15 @@ pub(super) enum UseSpans<'tcx> {
OtherUse(Span),
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(super) enum FnSelfUseKind<'tcx> {
/// A normal method call of the form `receiver.foo(a, b, c)`
Normal {
self_arg: Ident,
implicit_into_iter: bool,
/// Whether the self type of the method call has an `.as_ref()` method.
/// Used for better diagnostics.
is_option_or_result: bool,
},
/// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
FnOnceCall,
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
Operator { self_arg: Ident },
DerefCoercion {
/// The `Span` of the `Target` associated type
/// in the `Deref` impl we are using.
deref_target: Span,
/// The type `T::Deref` we are dereferencing to
deref_target_ty: Ty<'tcx>,
},
}
impl UseSpans<'_> {
pub(super) fn args_or_use(self) -> Span {
match self {
UseSpans::ClosureUse { args_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
UseSpans::FnSelfUse {
fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
} => fn_call_span,
UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
fn_call_span
}
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
@ -613,9 +590,9 @@ impl UseSpans<'_> {
UseSpans::ClosureUse { path_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
UseSpans::FnSelfUse {
fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
} => fn_call_span,
UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
fn_call_span
}
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
@ -626,9 +603,9 @@ impl UseSpans<'_> {
UseSpans::ClosureUse { capture_kind_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::OtherUse(span) => span,
UseSpans::FnSelfUse {
fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, ..
} => fn_call_span,
UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
fn_call_span
}
UseSpans::FnSelfUse { var_span, .. } => var_span,
}
}
@ -904,67 +881,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return normal_ret;
};
let tcx = self.infcx.tcx;
let parent = tcx.parent(method_did);
let is_fn_once = parent == tcx.lang_items().fn_once_trait();
let is_operator = !from_hir_call
&& parent.map_or(false, |p| tcx.lang_items().group(LangItemGroup::Op).contains(&p));
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
let fn_call_span = *fn_span;
let self_arg = tcx.fn_arg_names(method_did)[0];
debug!(
"terminator = {:?} from_hir_call={:?}",
self.body[location.block].terminator, from_hir_call
let kind = call_kind(
self.infcx.tcx,
self.param_env,
method_did,
method_substs,
*fn_span,
*from_hir_call,
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
);
// Check for a 'special' use of 'self' -
// an FnOnce call, an operator (e.g. `<<`), or a
// deref coercion.
let kind = if is_fn_once {
Some(FnSelfUseKind::FnOnceCall)
} else if is_operator {
Some(FnSelfUseKind::Operator { self_arg })
} else if is_deref {
let deref_target =
tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
Instance::resolve(tcx, self.param_env, deref_target, method_substs)
.transpose()
});
if let Some(Ok(instance)) = deref_target {
let deref_target_ty = instance.ty(tcx, self.param_env);
Some(FnSelfUseKind::DerefCoercion {
deref_target: tcx.def_span(instance.def_id()),
deref_target_ty,
})
} else {
None
}
} else {
None
};
let kind = kind.unwrap_or_else(|| {
// This isn't a 'special' use of `self`
debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
let implicit_into_iter = Some(method_did) == tcx.lang_items().into_iter_fn()
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop);
let parent_self_ty = parent
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
.and_then(|did| match tcx.type_of(did).kind() {
ty::Adt(def, ..) => Some(def.did),
_ => None,
});
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
});
return FnSelfUse {
var_span: stmt.source_info.span,
fn_call_span,
fn_call_span: *fn_span,
fn_span: self
.infcx
.tcx

View File

@ -1,3 +1,4 @@
use rustc_const_eval::util::CallDesugaringKind;
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
@ -8,7 +9,7 @@ use rustc_mir_dataflow::move_paths::{
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use crate::diagnostics::{FnSelfUseKind, UseSpans};
use crate::diagnostics::{CallKind, UseSpans};
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
@ -410,7 +411,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
} else if let Some(UseSpans::FnSelfUse {
kind: FnSelfUseKind::Normal { implicit_into_iter: true, .. },
kind:
CallKind::Normal { desugaring: Some((CallDesugaringKind::ForLoopIntoIter, _)), .. },
..
}) = use_spans
{

View File

@ -14,6 +14,7 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty,
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::SelectionContext;
use std::mem;
@ -293,13 +294,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 +774,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,20 +798,24 @@ 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(Some((callee, substs))));
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}),
);
let poly_trait_pred = Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
});
let obligation =
Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
let implsrc = tcx.infer_ctxt().enter(|infcx| {
let mut selcx = SelectionContext::new(&infcx);
@ -826,10 +831,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}
Ok(Some(ImplSource::UserDefined(data))) => {
if let hir::Constness::NotConst = tcx.impl_constness(data.impl_def_id) {
self.check_op(ops::FnCallNonConst(None));
return;
}
let callee_name = tcx.item_name(callee);
if let Some(&did) = tcx
.associated_item_def_ids(data.impl_def_id)
@ -841,22 +842,61 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
substs = InternalSubsts::identity_for_item(tcx, did);
callee = did;
}
if let hir::Constness::NotConst = tcx.impl_constness(data.impl_def_id) {
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
}
_ if !tcx.is_const_fn_raw(callee) => {
// At this point, it is only legal when the caller is marked with
// #[default_method_body_is_const], and the callee is in the same
// trait.
let callee_trait = tcx.trait_of_item(callee);
if callee_trait.is_some() {
if tcx.has_attr(caller, sym::default_method_body_is_const) {
if tcx.trait_of_item(caller) == callee_trait {
nonconst_call_permission = true;
}
}
if callee_trait.is_some()
&& tcx.has_attr(caller, sym::default_method_body_is_const)
&& callee_trait == tcx.trait_of_item(caller)
// Can only call methods when it's `<Self as TheTrait>::f`.
&& tcx.types.self_param == substs.type_at(0)
{
nonconst_call_permission = true;
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(None));
let obligation = Obligation::new(
ObligationCause::dummy_with_span(*fn_span),
param_env,
tcx.mk_predicate(
poly_trait_pred.map_bound(ty::PredicateKind::Trait),
),
);
// improve diagnostics by showing what failed. Our requirements are stricter this time
// as we are going to error again anyways.
tcx.infer_ctxt().enter(|infcx| {
if let Err(e) = implsrc {
infcx.report_selection_error(
obligation.clone(),
&obligation,
&e,
false,
);
}
});
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
}
@ -925,7 +965,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(None));
self.check_op(ops::FnCallNonConst {
caller,
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
});
return;
}
}

View File

@ -3,14 +3,22 @@
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, Closure, FnDef, FnPtr, 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 +37,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 +47,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 +61,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,77 +74,229 @@ 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 Option<(DefId, SubstsRef<'tcx>)>);
impl<'a> NonConstOp for FnCallNonConst<'a> {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"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 FnCallNonConst(Some((callee, substs))) = *self {
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 {
match (substs[0].unpack(), substs[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = inner_ty;
}
let deref = "*".repeat(num_refs);
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;
if let Ok(call_str) =
ccx.tcx.sess.source_map().span_to_snippet(span)
{
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
.find(|c: char| !c.is_whitespace())
{
let rhs_pos = span.lo()
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
err.multipart_suggestion(
"consider dereferencing here",
vec![
(span.shrink_to_lo(), deref.clone()),
(rhs_span, deref),
],
Applicability::MachineApplicable,
);
}
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::NotConst,
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::FnCall { fn_trait_id, self_ty } => {
let mut err = struct_span_err!(
tcx.sess,
span,
E0015,
"cannot call non-const closure in {}s",
ccx.const_kind(),
);
match self_ty.kind() {
FnDef(def_id, ..) => {
let span = tcx.sess.source_map().guess_head_span(tcx.def_span(*def_id));
if ccx.tcx.is_const_fn_raw(*def_id) {
span_bug!(span, "calling const FnDef errored when it shouldn't");
}
err.span_note(span, "function defined here, but it is not `const`");
}
FnPtr(..) => {
err.note(&format!(
"function pointers need an RFC before allowed to be called in {}s",
ccx.const_kind()
));
}
Closure(..) => {
err.note(&format!(
"closures need an RFC before allowed to be called in {}s",
ccx.const_kind()
));
}
_ => {}
}
diag_trait(err, self_ty, fn_trait_id)
}
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
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = inner_ty;
}
let deref = "*".repeat(num_refs);
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) =
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
{
let rhs_pos =
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
err.multipart_suggestion(
"consider dereferencing here",
vec![
(span.shrink_to_lo(), deref.clone()),
(rhs_span, deref),
],
Applicability::MachineApplicable,
);
}
}
}
_ => {}
}
_ => {}
}
}
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
}
@ -148,8 +308,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(
@ -174,8 +334,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 {
@ -183,7 +343,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,
@ -195,8 +355,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 {
@ -204,7 +364,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)
@ -216,8 +376,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,
@ -240,8 +400,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,
@ -256,8 +416,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,
@ -276,8 +436,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 {
@ -285,7 +445,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,
@ -300,8 +460,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,
@ -337,8 +497,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
}
@ -348,7 +508,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 => "",
@ -382,12 +542,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 => "",
@ -404,8 +564,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)
}
@ -414,7 +574,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,
@ -427,8 +587,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`",
@ -441,8 +601,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
@ -457,12 +617,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,
@ -477,8 +637,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
@ -494,8 +654,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 {
@ -503,7 +663,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,
@ -528,8 +688,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,
@ -546,8 +706,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)
}
@ -560,11 +720,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,
@ -576,7 +732,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,
@ -586,7 +742,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 {
@ -594,11 +750,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,
@ -610,16 +762,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,
@ -631,7 +779,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,
@ -641,7 +789,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 {
@ -649,11 +797,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,
@ -674,7 +818,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,
@ -684,7 +828,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 {
@ -692,11 +836,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,
@ -718,16 +858,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,

View File

@ -0,0 +1,143 @@
//! Common logic for borrowck use-after-move errors when moved into a `fn(self)`,
//! as well as errors when attempting to call a non-const function in a const
//! context.
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItemGroup;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind, Span};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallDesugaringKind {
/// for _ in x {} calls x.into_iter()
ForLoopIntoIter,
/// x? calls x.branch()
QuestionBranch,
/// x? calls type_of(x)::from_residual()
QuestionFromResidual,
/// try { ..; x } calls type_of(x)::from_output(x)
TryBlockFromOutput,
}
impl CallDesugaringKind {
pub fn trait_def_id(self, tcx: TyCtxt<'_>) -> DefId {
match self {
Self::ForLoopIntoIter => tcx.get_diagnostic_item(sym::IntoIterator).unwrap(),
Self::QuestionBranch | Self::TryBlockFromOutput => {
tcx.lang_items().try_trait().unwrap()
}
Self::QuestionFromResidual => tcx.get_diagnostic_item(sym::FromResidual).unwrap(),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallKind<'tcx> {
/// A normal method call of the form `receiver.foo(a, b, c)`
Normal {
self_arg: Option<Ident>,
desugaring: Option<(CallDesugaringKind, Ty<'tcx>)>,
/// Whether the self type of the method call has an `.as_ref()` method.
/// Used for better diagnostics.
is_option_or_result: bool,
},
/// A call to `Fn(..)::call(..)`, desugared from `my_closure(a, b, c)`
FnCall { fn_trait_id: DefId, self_ty: Ty<'tcx> },
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
Operator { self_arg: Option<Ident>, trait_id: DefId, self_ty: Ty<'tcx> },
DerefCoercion {
/// The `Span` of the `Target` associated type
/// in the `Deref` impl we are using.
deref_target: Span,
/// The type `T::Deref` we are dereferencing to
deref_target_ty: Ty<'tcx>,
self_ty: Ty<'tcx>,
},
}
pub fn call_kind<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
method_did: DefId,
method_substs: SubstsRef<'tcx>,
fn_call_span: Span,
from_hir_call: bool,
self_arg: Option<Ident>,
) -> CallKind<'tcx> {
let parent = tcx.opt_associated_item(method_did).and_then(|assoc| match assoc.container {
AssocItemContainer::ImplContainer(impl_did) => tcx.trait_id_of_impl(impl_did),
AssocItemContainer::TraitContainer(trait_did) => Some(trait_did),
});
let fn_call = parent
.and_then(|p| tcx.lang_items().group(LangItemGroup::Fn).iter().find(|did| **did == p));
let operator = (!from_hir_call)
.then(|| parent)
.flatten()
.and_then(|p| tcx.lang_items().group(LangItemGroup::Op).iter().find(|did| **did == p));
let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
// Check for a 'special' use of 'self' -
// an FnOnce call, an operator (e.g. `<<`), or a
// deref coercion.
let kind = if let Some(&trait_id) = fn_call {
Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
} else if let Some(&trait_id) = operator {
Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
} else if is_deref {
let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
Instance::resolve(tcx, param_env, deref_target, method_substs).transpose()
});
if let Some(Ok(instance)) = deref_target {
let deref_target_ty = instance.ty(tcx, param_env);
Some(CallKind::DerefCoercion {
deref_target: tcx.def_span(instance.def_id()),
deref_target_ty,
self_ty: method_substs.type_at(0),
})
} else {
None
}
} else {
None
};
kind.unwrap_or_else(|| {
// This isn't a 'special' use of `self`
debug!(?method_did, ?fn_call_span);
let desugaring = if Some(method_did) == tcx.lang_items().into_iter_fn()
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop)
{
Some((CallDesugaringKind::ForLoopIntoIter, method_substs.type_at(0)))
} else if fn_call_span.desugaring_kind() == Some(DesugaringKind::QuestionMark) {
if Some(method_did) == tcx.lang_items().branch_fn() {
Some((CallDesugaringKind::QuestionBranch, method_substs.type_at(0)))
} else if Some(method_did) == tcx.lang_items().from_residual_fn() {
Some((CallDesugaringKind::QuestionFromResidual, method_substs.type_at(0)))
} else {
None
}
} else if Some(method_did) == tcx.lang_items().from_output_fn()
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::TryBlock)
{
Some((CallDesugaringKind::TryBlockFromOutput, method_substs.type_at(0)))
} else {
None
};
let parent_self_ty = tcx
.parent(method_did)
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
.and_then(|did| match tcx.type_of(did).kind() {
ty::Adt(def, ..) => Some(def.did),
_ => None,
});
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
CallKind::Normal { self_arg, desugaring, is_option_or_result }
})
}

View File

@ -1,8 +1,10 @@
pub mod aggregate;
mod alignment;
mod call_kind;
pub mod collect_writes;
mod find_self_call;
pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::find_self_call::find_self_call;

View File

@ -21,9 +21,10 @@ use std::lazy::SyncLazy;
pub enum LangItemGroup {
Op,
Fn,
}
const NUM_GROUPS: usize = 1;
const NUM_GROUPS: usize = 2;
macro_rules! expand_group {
() => {
@ -98,11 +99,12 @@ macro_rules! language_item_table {
/// Construct an empty collection of lang items and no missing ones.
pub fn new() -> Self {
fn init_none(_: LangItem) -> Option<DefId> { None }
const EMPTY: Vec<DefId> = Vec::new();
Self {
items: vec![$(init_none(LangItem::$variant)),*],
missing: Vec::new(),
groups: [vec![]; NUM_GROUPS],
groups: [EMPTY; NUM_GROUPS],
}
}
@ -251,9 +253,9 @@ language_item_table! {
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
Fn(Fn), kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
FnMut(Fn), sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
FnOnce(Fn), sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
@ -264,8 +266,8 @@ language_item_table! {
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
PartialEq(Op), sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
PartialOrd(Op), sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
// A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
// various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.

View File

@ -184,6 +184,7 @@ symbols! {
Formatter,
From,
FromIterator,
FromResidual,
Future,
FxHashMap,
FxHashSet,

View File

@ -302,6 +302,7 @@ pub trait Try: FromResidual {
enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
),
)]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// Constructs the type from a compatible `Residual` type.

View File

@ -2,7 +2,7 @@ struct Project;
struct Value;
static settings_dir: String = format!("");
//~^ ERROR calls in statics are limited to constant functions
//~^ ERROR cannot call non-const fn
//~| ERROR is not yet stable as a const
fn from_string(_: String) -> Value {

View File

@ -7,12 +7,13 @@ LL | static settings_dir: String = format!("");
= help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable
= note: this error originates in the macro `$crate::__export::format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `format` in statics
--> $DIR/issue-64453.rs:4:31
|
LL | static settings_dir: String = format!("");
| ^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0507]: cannot move out of static item `settings_dir`

View File

@ -87,7 +87,7 @@ static mut STATIC13: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
static mut STATIC14: SafeStruct = SafeStruct {
field1: SafeEnum::Variant1,
field2: SafeEnum::Variant4("str".to_string())
//~^ ERROR calls in statics are limited to constant functions
//~^ ERROR cannot call non-const fn
};
static STATIC15: &'static [Box<MyOwned>] = &[

View File

@ -15,11 +15,13 @@ error[E0010]: allocations are not allowed in statics
LL | static STATIC11: Box<MyOwned> = box MyOwned;
| ^^^^^^^^^^^ allocation not allowed in statics
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> $DIR/check-static-values-constraints.rs:89:32
error[E0015]: cannot call non-const fn `<str as ToString>::to_string` in statics
--> $DIR/check-static-values-constraints.rs:89:38
|
LL | field2: SafeEnum::Variant4("str".to_string())
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:94:5

View File

@ -1,6 +1,6 @@
struct X<const N: usize = {
(||1usize)()
//~^ ERROR calls in constants are limited to
//~^ ERROR cannot call
}>;
fn main() {}

View File

@ -1,8 +1,11 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-93647.rs:2:5
|
LL | (||1usize)()
| ^^^^^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -13,7 +13,7 @@ fn consume<T: 'static>(_val: T)
where
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
//~^ ERROR: overly complex generic constant
//~| ERROR: calls in constants are limited to constant functions
//~| ERROR: cannot call non-const operator in constants
{
}
@ -21,7 +21,7 @@ fn test<T: 'static>()
where
If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
//~^ ERROR: overly complex generic constant
//~| ERROR: calls in constants are limited to constant functions
//~| ERROR: cannot call non-const operator in constants
{
}

View File

@ -9,11 +9,19 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:14:10
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
|
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
| ^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: overly complex generic constant
--> $DIR/issue-90318.rs:22:8
@ -26,11 +34,19 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
= help: consider moving this anonymous constant into a `const` function
= note: this operation may be supported in the future
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constants
--> $DIR/issue-90318.rs:22:10
|
LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/any.rs:LL:COL
|
LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
| ^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants
--> $DIR/nested-type.rs:15:5
|
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -14,11 +14,13 @@ LL | | }]>;
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `Foo::{constant#0}::Foo::<17_usize>::value` in constants
--> $DIR/nested-type.rs:15:5
|
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View File

@ -13,7 +13,7 @@ struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
}
Foo::<17>::value()
//~^ ERROR calls in constants are limited to constant functions
//~^ ERROR cannot call non-const fn
}]>;
fn main() {}

View File

@ -4,5 +4,5 @@ fn f(x: usize) -> usize {
fn main() {
let _ = [0; f(2)];
//~^ ERROR calls in constants are limited to constant functions
//~^ ERROR cannot call non-const fn
}

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `f` in constants
--> $DIR/const-call.rs:6:17
|
LL | let _ = [0; f(2)];
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -7,7 +7,7 @@ extern "C" {
const extern "C" fn bar() {
unsafe {
regular_in_block();
//~^ ERROR: calls in constant functions
//~^ ERROR: cannot call non-const fn
}
}
@ -16,7 +16,7 @@ extern "C" fn regular() {}
const extern "C" fn foo() {
unsafe {
regular();
//~^ ERROR: calls in constant functions
//~^ ERROR: cannot call non-const fn
}
}

View File

@ -1,14 +1,18 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `regular_in_block` in constant functions
--> $DIR/const-extern-fn-call-extern-fn.rs:9:9
|
LL | regular_in_block();
| ^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `regular` in constant functions
--> $DIR/const-extern-fn-call-extern-fn.rs:18:9
|
LL | regular();
| ^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View File

@ -4,8 +4,8 @@ const fn f(x: usize) -> usize {
let mut sum = 0;
for i in 0..x {
//~^ ERROR mutable references
//~| ERROR calls in constant functions
//~| ERROR calls in constant functions
//~| ERROR cannot convert
//~| ERROR cannot call non-const fn
//~| ERROR `for` is not allowed in a `const fn`
sum += i;
}

View File

@ -13,11 +13,18 @@ LL | | }
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
= help: add `#![feature(const_for)]` to the crate attributes to enable
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot convert `std::ops::Range<usize>` into an iterator in constant functions
--> $DIR/const-fn-error.rs:5:14
|
LL | for i in 0..x {
| ^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: Iterator> IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/const-fn-error.rs:5:14
@ -28,11 +35,13 @@ LL | for i in 0..x {
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<std::ops::Range<usize> as Iterator>::next` in constant functions
--> $DIR/const-fn-error.rs:5:14
|
LL | for i in 0..x {
| ^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 4 previous errors

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `random` in constant functions
--> $DIR/const-fn-not-safe-for-const.rs:14:5
|
LL | random()
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0013]: constant functions cannot refer to statics
--> $DIR/const-fn-not-safe-for-const.rs:20:5

View File

@ -3,8 +3,8 @@
const _: () = {
for _ in 0..5 {}
//~^ error: calls in constants are limited to
//~| error: calls in constants are limited to
//~^ error: cannot convert
//~| error: cannot call non-const fn
};
fn main() {}

View File

@ -1,14 +1,23 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants
--> $DIR/const-for.rs:5:14
|
LL | for _ in 0..5 {}
| ^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: Iterator> IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
--> $DIR/const-for.rs:5:14
|
LL | for _ in 0..5 {}
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View File

@ -8,7 +8,7 @@ fn non_const() -> Thing {
}
pub const Q: i32 = match non_const() {
//~^ ERROR calls in constants are limited to constant functions
//~^ ERROR cannot call non-const fn
Thing::This => 1,
Thing::That => 0
};

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `non_const` in constants
--> $DIR/issue-46843.rs:10:26
|
LL | pub const Q: i32 = match non_const() {
| ^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -11,7 +11,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
}
unsafe { copy(src, dst, count) }
//~^ ERROR calls in constant functions are limited to constant functions
//~^ ERROR cannot call non-const fn
}
fn main() {}

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `copy::copy::<T>` in constant functions
--> $DIR/intrinsic_without_const_stab.rs:13:14
|
LL | unsafe { copy(src, dst, count) }
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -9,7 +9,7 @@ extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
#[inline]
pub const unsafe fn stuff<T>(src: *const T, dst: *mut T, count: usize) {
unsafe { copy(src, dst, count) } //~ ERROR calls in constant functions are limited
unsafe { copy(src, dst, count) } //~ ERROR cannot call non-const fn
}
fn main() {}

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `copy::<T>` in constant functions
--> $DIR/intrinsic_without_const_stab_fail.rs:12:14
|
LL | unsafe { copy(src, dst, count) }
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -2,7 +2,7 @@
const X: u8 =
|| -> u8 { 5 }()
//~^ ERROR calls in constants are limited to constant functions
//~^ ERROR cannot call non-const closure
;
fn main() {}

View File

@ -1,8 +1,11 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-28113.rs:4:5
|
LL | || -> u8 { 5 }()
| ^^^^^^^^^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -8,7 +8,7 @@ const bad : u32 = {
const bad_two : u32 = {
{
invalid();
//~^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
//~^ ERROR: cannot call non-const fn `invalid`
0
}
};
@ -30,7 +30,7 @@ static bad_four : u32 = {
static bad_five : u32 = {
{
invalid();
//~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
//~^ ERROR: cannot call non-const fn `invalid`
0
}
};
@ -52,7 +52,7 @@ static mut bad_seven : u32 = {
static mut bad_eight : u32 = {
{
invalid();
//~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
//~^ ERROR: cannot call non-const fn `invalid`
0
}
};

View File

@ -1,20 +1,26 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `invalid` in constants
--> $DIR/issue-32829-2.rs:10:9
|
LL | invalid();
| ^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `invalid` in statics
--> $DIR/issue-32829-2.rs:32:9
|
LL | invalid();
| ^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `invalid` in statics
--> $DIR/issue-32829-2.rs:54:9
|
LL | invalid();
| ^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to 3 previous errors

View File

@ -1,7 +1,7 @@
fn xyz() -> u8 { 42 }
const NUM: u8 = xyz();
//~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants
//~^ ERROR cannot call non-const fn
fn main() {
match 1 {

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `xyz` in constants
--> $DIR/issue-43105.rs:3:17
|
LL | const NUM: u8 = xyz();
| ^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: could not evaluate constant pattern
--> $DIR/issue-43105.rs:8:9

View File

@ -1,7 +1,7 @@
#![feature(const_fn_fn_ptr_basics)]
const fn foo() { (||{})() }
//~^ ERROR calls in constant functions
//~^ ERROR cannot call non-const closure
const fn bad(input: fn()) {
input()

View File

@ -1,8 +1,11 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/issue-56164.rs:3:18
|
LL | const fn foo() { (||{})() }
| ^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constant functions
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: function pointers are not allowed in const fn
--> $DIR/issue-56164.rs:7:5

View File

@ -3,7 +3,7 @@
// in the length part of an array.
struct Bug {
a: [(); (|| { 0 })()] //~ ERROR calls in constants are limited to
a: [(); (|| { 0 })()] //~ ERROR cannot call non-const closure
}
fn main() {}

View File

@ -1,8 +1,11 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constants
--> $DIR/issue-68542-closure-in-array-len.rs:6:13
|
LL | a: [(); (|| { 0 })()]
| ^^^^^^^^^^^^
|
= note: closures need an RFC before allowed to be called in constants
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -6,20 +6,20 @@
const fn f(a: &u8, b: &u8) -> bool {
*a == *b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
}
const fn g(a: &&&&i64, b: &&&&i64) -> bool {
****a == ****b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
}
const fn h(mut a: &[u8], mut b: &[u8]) -> bool {
while let ([l, at @ ..], [r, bt @ ..]) = (a, b) {
if *l == *r {
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
a = at;
b = bt;

View File

@ -6,20 +6,20 @@
const fn f(a: &u8, b: &u8) -> bool {
a == b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
}
const fn g(a: &&&&i64, b: &&&&i64) -> bool {
a == b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
}
const fn h(mut a: &[u8], mut b: &[u8]) -> bool {
while let ([l, at @ ..], [r, bt @ ..]) = (a, b) {
if l == r {
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~^ ERROR: cannot call non-const operator in constant functions [E0015]
//~| HELP: consider dereferencing here
a = at;
b = bt;

View File

@ -1,31 +1,34 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constant functions
--> $DIR/issue-90870.rs:8:5
|
LL | a == b
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider dereferencing here
|
LL | *a == *b
| + +
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constant functions
--> $DIR/issue-90870.rs:14:5
|
LL | a == b
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider dereferencing here
|
LL | ****a == ****b
| ++++ ++++
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constant functions
--> $DIR/issue-90870.rs:21:12
|
LL | if l == r {
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider dereferencing here
|
LL | if *l == *r {

View File

@ -1,7 +1,7 @@
const fn foo(a: i32) -> Vec<i32> {
vec![1, 2, 3]
//~^ ERROR allocations are not allowed
//~| ERROR calls in constant functions
//~| ERROR cannot call non-const fn
}
fn main() {}

View File

@ -6,12 +6,13 @@ LL | vec![1, 2, 3]
|
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors

View File

@ -6,6 +6,6 @@ fn bar() -> Foo {
}
static foo: Foo = bar();
//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
//~^ ERROR cannot call non-const fn
fn main() {}

View File

@ -1,8 +1,10 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `bar` in statics
--> $DIR/mir_check_nonconst.rs:8:19
|
LL | static foo: Foo = bar();
| ^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -1,8 +1,14 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const closure in constant functions
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
|
LL | Opt::None => f(),
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn unwrap_or_else<F: FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
| +++++++++++++++++++++++++++++
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:19:53

View File

@ -1,8 +1,10 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `Y::foo` in statics
--> $DIR/issue-16538.rs:15:23
|
LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0133]: use of extern static is unsafe and requires unsafe function or block
--> $DIR/issue-16538.rs:15:30

View File

@ -14,11 +14,13 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
|
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `Y::foo` in statics
--> $DIR/issue-16538.rs:15:23
|
LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to 3 previous errors

View File

@ -2,7 +2,7 @@ struct A;
struct B;
static S: &'static B = &A;
//~^ ERROR calls in statics are limited to constant functions
//~^ ERROR cannot perform deref coercion on `A` in statics
use std::ops::Deref;

View File

@ -1,8 +1,21 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot perform deref coercion on `A` in statics
--> $DIR/issue-25901.rs:4:24
|
LL | static S: &'static B = &A;
| ^^
|
= note: attempting to deref into `B`
note: deref defined here
--> $DIR/issue-25901.rs:10:5
|
LL | type Target = B;
| ^^^^^^^^^^^^^^^^
note: impl defined here, but it is not `const`
--> $DIR/issue-25901.rs:9:1
|
LL | impl Deref for A {
| ^^^^^^^^^^^^^^^^
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -1,14 +1,18 @@
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<Dim3 as Dim>::dim` in constants
--> $DIR/issue-39559-2.rs:14:24
|
LL | let array: [usize; Dim3::dim()]
| ^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<Dim3 as Dim>::dim` in constants
--> $DIR/issue-39559-2.rs:16:15
|
LL | = [0; Dim3::dim()];
| ^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View File

@ -8,7 +8,7 @@ fn main() {
[(); { for _ in 0usize.. {}; 0}];
//~^ ERROR `for` is not allowed in a `const`
//~| ERROR calls in constants are limited to constant functions
//~| ERROR cannot convert
//~| ERROR mutable references are not allowed in constants
//~| ERROR calls in constants are limited to constant functions
//~| ERROR cannot call non-const fn
}

View File

@ -38,11 +38,18 @@ LL | [(); loop { break }];
| expected `usize`, found `()`
| help: give it a value of the expected type: `break 42`
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot convert `RangeFrom<usize>` into an iterator in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
| ^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | impl<I: Iterator> IntoIterator for I {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constants
--> $DIR/issue-52443.rs:9:21
@ -53,11 +60,13 @@ LL | [(); { for _ in 0usize.. {}; 0}];
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<RangeFrom<usize> as Iterator>::next` in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
| ^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 6 previous errors; 1 warning emitted

View File

@ -22,7 +22,8 @@ pub const fn add_i32(a: i32, b: i32) -> i32 {
pub const fn add_u32(a: u32, b: u32) -> u32 {
a.plus(b)
//~^ ERROR calls in constant functions are limited to constant functions
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
}
fn main() {}

View File

@ -1,9 +1,24 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/call-const-trait-method-fail.rs:24:5
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
--> $DIR/call-const-trait-method-fail.rs:24:7
|
LL | a.plus(b)
| ^^^^^^^^^
| ^^^^^^^ the trait `~const Plus` is not implemented for `u32`
|
note: the trait `Plus` is implemented for `u32`, but that implementation is not `const`
--> $DIR/call-const-trait-method-fail.rs:24:7
|
LL | a.plus(b)
| ^^^^^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
--> $DIR/call-const-trait-method-fail.rs:24:7
|
LL | a.plus(b)
| ^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -3,7 +3,8 @@
pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
*t == *t
//~^ ERROR calls in constant functions are limited to constant functions
//~^ ERROR can't compare
//~| ERROR cannot call non-const
}
fn main() {}

View File

@ -1,9 +1,28 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0277]: can't compare `T` with `T` in const contexts
--> $DIR/call-generic-method-fail.rs:5:5
|
LL | *t == *t
| ^^^^^^^^ no implementation for `T == T`
|
note: the trait `PartialEq` is implemented for `T`, but that implementation is not `const`
--> $DIR/call-generic-method-fail.rs:5:5
|
LL | *t == *t
| ^^^^^^^^
error: aborting due to previous error
error[E0015]: cannot call non-const operator in constant functions
--> $DIR/call-generic-method-fail.rs:5:5
|
LL | *t == *t
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
| ++++++++++++++++++++++++++++
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -9,7 +9,7 @@ fn non_const() {}
impl const T for S {
fn foo() { non_const() }
//~^ ERROR calls in constant functions
//~^ ERROR cannot call non-const fn
}
fn main() {}

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `non_const` in constant functions
--> $DIR/const-check-fns-in-const-impl.rs:11:16
|
LL | fn foo() { non_const() }
| ^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -23,7 +23,8 @@ impl const ConstDefaultFn for ConstImpl {
const fn test() {
NonConstImpl.a();
//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple variants
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
ConstImpl.a();
}

View File

@ -1,9 +1,24 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-default-method-bodies.rs:25:5
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
--> $DIR/const-default-method-bodies.rs:25:18
|
LL | NonConstImpl.a();
| ^^^^^^^^^^^^^^^^
| ^^^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
|
note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
--> $DIR/const-default-method-bodies.rs:25:18
|
LL | NonConstImpl.a();
| ^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
--> $DIR/const-default-method-bodies.rs:25:18
|
LL | NonConstImpl.a();
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,9 +1,24 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/cross-crate.rs:15:5
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
--> $DIR/cross-crate.rs:15:14
|
LL | NonConst.func();
| ^^^^^^^^^^^^^^^
| ^^^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
|
note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
--> $DIR/cross-crate.rs:15:14
|
LL | NonConst.func();
| ^^^^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:15:14
|
LL | NonConst.func();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -12,10 +12,10 @@ fn non_const_context() {
}
const fn const_context() {
NonConst.func();
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
NonConst.func(); //~ ERROR: cannot call non-const fn
//[gated]~^ ERROR: the trait bound
Const.func();
//[stock]~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants
//[stock]~^ ERROR: cannot call non-const fn
}
fn main() {}

View File

@ -1,14 +1,18 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/cross-crate.rs:15:5
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:15:14
|
LL | NonConst.func();
| ^^^^^^^^^^^^^^^
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/cross-crate.rs:17:5
error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
--> $DIR/cross-crate.rs:17:11
|
LL | Const.func();
| ^^^^^^^^^^^^
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors

View File

@ -8,7 +8,8 @@ pub trait Tr {
#[default_method_body_is_const]
fn b(&self) {
().a()
//~^ ERROR calls in constant functions are limited
//~^ ERROR the trait bound
//~| ERROR cannot call
}
}

View File

@ -1,9 +1,24 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:9
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
LL | ().a()
| ^^^^^^
| ^^^ the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
LL | ().a()
| ^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<() as Tr>::a` in constant functions
--> $DIR/default-method-body-is-const-same-trait-ck.rs:10:12
|
LL | ().a()
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -7,7 +7,8 @@ pub trait A {
pub const fn foo<T: A>() -> bool {
T::assoc()
//~^ ERROR calls in constant functions are limited
//~^ ERROR the trait bound
//~| ERROR cannot call non-const fn
}
fn main() {}

View File

@ -1,9 +1,24 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0277]: the trait bound `T: ~const A` is not satisfied
--> $DIR/issue-88155.rs:9:5
|
LL | T::assoc()
| ^^^^^^^^^^ the trait `~const A` is not implemented for `T`
|
note: the trait `A` is implemented for `T`, but that implementation is not `const`
--> $DIR/issue-88155.rs:9:5
|
LL | T::assoc()
| ^^^^^^^^^^
error: aborting due to previous error
error[E0015]: cannot call non-const fn `<T as A>::assoc` in constant functions
--> $DIR/issue-88155.rs:9:5
|
LL | T::assoc()
| ^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
For more information about this error, try `rustc --explain E0015`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0015, E0277.
For more information about an error, try `rustc --explain E0015`.

View File

@ -11,7 +11,7 @@ fn non_const_context() -> Vec<usize> {
const fn const_context() -> Vec<usize> {
Default::default()
//[stock]~^ ERROR calls in constant functions are limited
//[stock]~^ ERROR cannot call non-const fn
}
fn main() {

View File

@ -1,8 +1,10 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions
--> $DIR/std-impl-gate.rs:13:5
|
LL | Default::default()
| ^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error

View File

@ -1,8 +1,10 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `foo` in statics
--> $DIR/static-vec-repeat-not-constant.rs:3:25
|
LL | static a: [isize; 2] = [foo(); 2];
| ^^^^^
|
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error