mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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:
commit
953c4dcc30
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
¶m_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,
|
||||
|
143
compiler/rustc_const_eval/src/util/call_kind.rs
Normal file
143
compiler/rustc_const_eval/src/util/call_kind.rs
Normal 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 }
|
||||
})
|
||||
}
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -184,6 +184,7 @@ symbols! {
|
||||
Formatter,
|
||||
From,
|
||||
FromIterator,
|
||||
FromResidual,
|
||||
Future,
|
||||
FxHashMap,
|
||||
FxHashSet,
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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`
|
||||
|
@ -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>] = &[
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
struct X<const N: usize = {
|
||||
(||1usize)()
|
||||
//~^ ERROR calls in constants are limited to
|
||||
//~^ ERROR cannot call
|
||||
}>;
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user