1
Fork 0

Auto merge of #76850 - ecstatic-morse:const-checking-refactor, r=oli-obk

Remove `qualify_min_const_fn`

~~Blocked on #76807 (the first six commits).~~

With this PR, all checks in `qualify_min_const_fn` are replicated in `check_consts`, and the former is no longer invoked. My goal was to have as few changes to test output as possible, since making sweeping changes to the code *while* doing big batches of diagnostics updates turned out to be a headache. To this end, there's a few `HACK`s in `check_consts` to achieve parity with `qualify_min_const_fn`.

The new system that replaces `is_min_const_fn` is referred to as "const-stability"  My end goal for the const-stability rules is this:
* Const-stability is only applicable to functions defined in `staged_api` crates.
* All functions not marked `rustc_const_unstable` are considered "const-stable".
    - NB. This is currently not implemented. `#[unstable]` functions are also const-unstable. This causes problems when searching for feature gates.
    - All "const-unstable" functions have an associated feature gate
* const-stable functions can only call other const-stable functions
     - `allow_internal_unstable` can be used to circumvent this.
* All const-stable functions are subject to some additional checks (the ones that were unique to `qualify_min_const_fn`)

The plan is to remove each `HACK` individually in subsequent PRs. That way, changes to error message output can be reviewed in isolation.
This commit is contained in:
bors 2020-09-23 05:40:35 +00:00
commit f6d59207ad
54 changed files with 789 additions and 257 deletions

View file

@ -7,6 +7,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
#![feature(box_syntax)]
#![feature(const_fn)] // For the `transmute` in `P::new`
#![feature(const_fn_transmute)]
#![feature(const_panic)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]

View file

@ -51,6 +51,12 @@ impl ConstCx<'mir, 'tcx> {
pub fn const_kind(&self) -> hir::ConstContext {
self.const_kind.expect("`const_kind` must not be called on a non-const fn")
}
pub fn is_const_stable_const_fn(&self) -> bool {
self.const_kind == Some(hir::ConstContext::ConstFn)
&& self.tcx.features().staged_api
&& is_const_stable_const_fn(self.tcx, self.def_id.to_def_id())
}
}
/// Returns `true` if this `DefId` points to one of the official `panic` lang items.
@ -63,3 +69,37 @@ pub fn allow_internal_unstable(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: S
attr::allow_internal_unstable(&tcx.sess, attrs)
.map_or(false, |mut features| features.any(|name| name == feature_gate))
}
// Returns `true` if the given `const fn` is "const-stable".
//
// Panics if the given `DefId` does not refer to a `const fn`.
//
// Const-stability is only relevant for `const fn` within a `staged_api` crate. Only "const-stable"
// functions can be called in a const-context by users of the stable compiler. "const-stable"
// functions are subject to more stringent restrictions than "const-unstable" functions: They
// cannot use unstable features and can only call other "const-stable" functions.
pub fn is_const_stable_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
use attr::{ConstStability, Stability, StabilityLevel};
// Const-stability is only relevant for `const fn`.
assert!(tcx.is_const_fn_raw(def_id));
// Functions with `#[rustc_const_unstable]` are const-unstable.
match tcx.lookup_const_stability(def_id) {
Some(ConstStability { level: StabilityLevel::Unstable { .. }, .. }) => return false,
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => return true,
None => {}
}
// Functions with `#[unstable]` are const-unstable.
//
// FIXME(ecstaticmorse): We should keep const-stability attributes wholly separate from normal stability
// attributes. `#[unstable]` should be irrelevant.
if let Some(Stability { level: StabilityLevel::Unstable { .. }, .. }) =
tcx.lookup_stability(def_id)
{
return false;
}
true
}

View file

@ -10,33 +10,34 @@ use rustc_span::{Span, Symbol};
use super::ConstCx;
/// Emits an error if `op` is not allowed in the given const context.
pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {
/// Emits an error and returns `true` if `op` is not allowed in the given const context.
pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) -> bool {
debug!("illegal_op: op={:?}", op);
let gate = match op.status_in_item(ccx) {
Status::Allowed => return,
Status::Allowed => return false,
Status::Unstable(gate) if ccx.tcx.features().enabled(gate) => {
let unstable_in_stable = ccx.const_kind() == hir::ConstContext::ConstFn
&& ccx.tcx.features().enabled(sym::staged_api)
&& !ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_const_unstable)
let unstable_in_stable = ccx.is_const_stable_const_fn()
&& !super::allow_internal_unstable(ccx.tcx, ccx.def_id.to_def_id(), gate);
if unstable_in_stable {
ccx.tcx.sess
.struct_span_err(span, &format!("`#[feature({})]` cannot be depended on in a const-stable function", gate.as_str()))
.struct_span_err(
span,
&format!("const-stable function cannot use `#[feature({})]`", gate.as_str()),
)
.span_suggestion(
ccx.body.span,
"if it is not part of the public API, make this function unstably const",
concat!(r#"#[rustc_const_unstable(feature = "...", issue = "...")]"#, '\n').to_owned(),
Applicability::HasPlaceholders,
)
.help("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
.note("otherwise `#[allow_internal_unstable]` can be used to bypass stability checks")
.emit();
}
return;
return unstable_in_stable;
}
Status::Unstable(gate) => Some(gate),
@ -45,12 +46,14 @@ pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {
if ccx.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
ccx.tcx.sess.miri_unleashed_feature(span, gate);
return;
return false;
}
op.emit_error(ccx, span);
true
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
Allowed,
Unstable(Symbol),
@ -59,6 +62,8 @@ pub enum Status {
/// An operation that is not *always* allowed in a const context.
pub trait NonConstOp: std::fmt::Debug {
const STOPS_CONST_CHECKING: bool = false;
/// Returns an enum indicating whether this operation is allowed within the given item.
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
Status::Forbidden
@ -93,6 +98,34 @@ pub trait NonConstOp: std::fmt::Debug {
}
}
#[derive(Debug)]
pub struct Abort;
impl NonConstOp for Abort {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "abort is not stable in const fn")
}
}
#[derive(Debug)]
pub struct NonPrimitiveOp;
impl NonConstOp for NonPrimitiveOp {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "only int, `bool` and `char` operations are stable in const fn")
}
}
/// A function call where the callee is a pointer.
#[derive(Debug)]
pub struct FnCallIndirect;
@ -125,7 +158,8 @@ impl NonConstOp for FnCallNonConst {
///
/// Contains the name of the feature that would allow the use of this function.
#[derive(Debug)]
pub struct FnCallUnstable(pub DefId, pub Symbol);
pub struct FnCallUnstable(pub DefId, pub Option<Symbol>);
impl NonConstOp for FnCallUnstable {
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
let FnCallUnstable(def_id, feature) = *self;
@ -134,13 +168,51 @@ impl NonConstOp for FnCallUnstable {
span,
&format!("`{}` is not yet stable as a const fn", ccx.tcx.def_path_str(def_id)),
);
if nightly_options::is_nightly_build() {
err.help(&format!("add `#![feature({})]` to the crate attributes to enable", feature));
if ccx.is_const_stable_const_fn() {
err.help("Const-stable functions can only call other const-stable functions");
} else if nightly_options::is_nightly_build() {
if let Some(feature) = feature {
err.help(&format!(
"add `#![feature({})]` to the crate attributes to enable",
feature
));
}
}
err.emit();
}
}
#[derive(Debug)]
pub struct FnPtrCast;
impl NonConstOp for FnPtrCast {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn");
}
}
#[derive(Debug)]
pub struct Generator;
impl NonConstOp for Generator {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
// FIXME: This means generator-only MIR is only forbidden in const fn. This is for
// compatibility with the old code. Such MIR should be forbidden everywhere.
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "const fn generators are unstable");
}
}
#[derive(Debug)]
pub struct HeapAllocation;
impl NonConstOp for HeapAllocation {
@ -403,6 +475,24 @@ impl NonConstOp for ThreadLocalAccess {
}
}
#[derive(Debug)]
pub struct Transmute;
impl NonConstOp for Transmute {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn_transmute)
}
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "can only call `transmute` from const items, not `const fn`");
}
}
#[derive(Debug)]
pub struct UnionAccess;
impl NonConstOp for UnionAccess {
@ -425,3 +515,131 @@ impl NonConstOp for UnionAccess {
.emit();
}
}
/// See [#64992].
///
/// [#64992]: https://github.com/rust-lang/rust/issues/64992
#[derive(Debug)]
pub struct UnsizingCast;
impl NonConstOp for UnsizingCast {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(
ccx,
span,
"unsizing casts to types besides slices are not allowed in const fn",
);
}
}
pub mod ty {
use super::*;
#[derive(Debug)]
pub struct MutRef;
impl NonConstOp for MutRef {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_mut_refs)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "mutable references in const fn are unstable");
}
}
#[derive(Debug)]
pub struct FnPtr;
impl NonConstOp for FnPtr {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
// FIXME: This attribute a hack to allow the specialization of the `futures` API. See
// #59739. We should have a proper feature gate for this.
if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) {
Status::Allowed
} else {
mcf_status_in_item(ccx)
}
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "function pointers in const fn are unstable");
}
}
#[derive(Debug)]
pub struct ImplTrait;
impl NonConstOp for ImplTrait {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(ccx, span, "`impl Trait` in const fn is unstable");
}
}
#[derive(Debug)]
pub struct TraitBound;
impl NonConstOp for TraitBound {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
mcf_status_in_item(ccx)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
mcf_emit_error(
ccx,
span,
"trait bounds other than `Sized` on const fn parameters are unstable",
);
}
}
/// A trait bound with the `?const Trait` opt-out
#[derive(Debug)]
pub struct TraitBoundNotConst;
impl NonConstOp for TraitBoundNotConst {
const STOPS_CONST_CHECKING: bool = true;
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_trait_bound_opt_out)
}
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_trait_bound_opt_out,
span,
"`?const Trait` syntax is unstable",
)
.emit()
}
}
}
fn mcf_status_in_item(ccx: &ConstCx<'_, '_>) -> Status {
if ccx.const_kind() != hir::ConstContext::ConstFn {
Status::Allowed
} else {
Status::Unstable(sym::const_fn)
}
}
fn mcf_emit_error(ccx: &ConstCx<'_, '_>, span: Span, msg: &str) {
struct_span_err!(ccx.tcx.sess, span, E0723, "{}", msg)
.note(
"see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
for more information",
)
.help("add `#![feature(const_fn)]` to the crate attributes to enable")
.emit();
}

View file

@ -2,7 +2,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::{sym, Span};
use rustc_span::Span;
use super::ops;
use super::qualifs::{NeedsDrop, Qualif};
@ -11,13 +11,13 @@ use super::ConstCx;
/// Returns `true` if we should use the more precise live drop checker that runs after drop
/// elaboration.
pub fn checking_enabled(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
// Const-stable functions must always use the stable live drop checker.
if tcx.features().staged_api && !tcx.has_attr(def_id.to_def_id(), sym::rustc_const_unstable) {
if ccx.is_const_stable_const_fn() {
return false;
}
tcx.features().const_precise_live_drops
ccx.tcx.features().const_precise_live_drops
}
/// Look for live drops in a const context.
@ -30,12 +30,11 @@ pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<
return;
}
if !checking_enabled(tcx, def_id) {
let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
if !checking_enabled(&ccx) {
return;
}
let ccx = ConstCx { body, tcx, def_id, const_kind, param_env: tcx.param_env(def_id) };
let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
visitor.visit_body(body);

View file

@ -7,19 +7,21 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::{self, Instance, InstanceDef, TyCtxt};
use rustc_span::Span;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{
self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt, TypeAndMut,
};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::{self, TraitEngine};
use std::borrow::Cow;
use std::ops::Deref;
use super::ops::{self, NonConstOp};
use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
use super::resolver::FlowSensitiveAnalysis;
use super::{is_lang_panic_fn, ConstCx, Qualif};
use crate::const_eval::{is_const_fn, is_unstable_const_fn};
use crate::const_eval::is_unstable_const_fn;
use crate::dataflow::impls::MaybeMutBorrowedLocals;
use crate::dataflow::{self, Analysis};
@ -176,6 +178,8 @@ pub struct Validator<'mir, 'tcx> {
/// The span of the current statement.
span: Span,
const_checking_stopped: bool,
}
impl Deref for Validator<'mir, 'tcx> {
@ -188,30 +192,60 @@ impl Deref for Validator<'mir, 'tcx> {
impl Validator<'mir, 'tcx> {
pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self {
Validator { span: ccx.body.span, ccx, qualifs: Default::default() }
Validator {
span: ccx.body.span,
ccx,
qualifs: Default::default(),
const_checking_stopped: false,
}
}
pub fn check_body(&mut self) {
let ConstCx { tcx, body, def_id, const_kind, .. } = *self.ccx;
let ConstCx { tcx, body, def_id, .. } = *self.ccx;
let use_min_const_fn_checks = (const_kind == Some(hir::ConstContext::ConstFn)
&& crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id()))
&& !tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you;
// HACK: This function has side-effects???? Make sure we call it.
let _ = crate::const_eval::is_min_const_fn(tcx, def_id.to_def_id());
if use_min_const_fn_checks {
// Enforce `min_const_fn` for stable `const fn`s.
use crate::transform::qualify_min_const_fn::is_min_const_fn;
if let Err((span, err)) = is_min_const_fn(tcx, def_id.to_def_id(), &body) {
error_min_const_fn_violation(tcx, span, err);
return;
// The local type and predicate checks are not free and only relevant for `const fn`s.
if self.const_kind() == hir::ConstContext::ConstFn {
// Prevent const trait methods from being annotated as `stable`.
// FIXME: Do this as part of stability checking.
if self.is_const_stable_const_fn() {
let hir_id = tcx.hir().local_def_id_to_hir_id(self.def_id);
if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
struct_span_err!(
self.ccx.tcx.sess,
self.span,
E0723,
"trait methods cannot be stable const fn"
)
.emit();
}
}
self.check_item_predicates();
for local in &body.local_decls {
if local.internal {
continue;
}
self.span = local.source_info.span;
self.check_local_or_return_ty(local.ty);
}
// impl trait is gone in MIR, so check the return type of a const fn by its signature
// instead of the type of the return place.
self.span = body.local_decls[RETURN_PLACE].source_info.span;
let return_ty = tcx.fn_sig(def_id).output();
self.check_local_or_return_ty(return_ty.skip_binder());
}
self.visit_body(&body);
// Ensure that the end result is `Sync` in a non-thread local `static`.
let should_check_for_sync = const_kind
== Some(hir::ConstContext::Static(hir::Mutability::Not))
let should_check_for_sync = self.const_kind()
== hir::ConstContext::Static(hir::Mutability::Not)
&& !tcx.is_thread_local_static(def_id.to_def_id());
if should_check_for_sync {
@ -226,13 +260,22 @@ impl Validator<'mir, 'tcx> {
/// Emits an error if an expression cannot be evaluated in the current context.
pub fn check_op(&mut self, op: impl NonConstOp) {
ops::non_const(self.ccx, op, self.span);
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(&mut self, op: impl NonConstOp, span: Span) {
ops::non_const(self.ccx, op, span);
pub fn check_op_spanned<O: NonConstOp>(&mut self, op: O, span: Span) {
// HACK: This is for strict equivalence with the old `qualify_min_const_fn` pass, which
// only emitted one error per function. It should be removed and the test output updated.
if self.const_checking_stopped {
return;
}
let err_emitted = ops::non_const(self.ccx, op, span);
if err_emitted && O::STOPS_CONST_CHECKING {
self.const_checking_stopped = true;
}
}
fn check_static(&mut self, def_id: DefId, span: Span) {
@ -242,6 +285,100 @@ impl Validator<'mir, 'tcx> {
);
self.check_op_spanned(ops::StaticAccess, span)
}
fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>) {
for ty in ty.walk() {
let ty = match ty.unpack() {
GenericArgKind::Type(ty) => ty,
// No constraints on lifetimes or constants, except potentially
// constants' types, but `walk` will get to them as well.
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
};
match *ty.kind() {
ty::Ref(_, _, hir::Mutability::Mut) => self.check_op(ops::ty::MutRef),
ty::Opaque(..) => self.check_op(ops::ty::ImplTrait),
ty::FnPtr(..) => self.check_op(ops::ty::FnPtr),
ty::Dynamic(preds, _) => {
for pred in preds.iter() {
match pred.skip_binder() {
ty::ExistentialPredicate::AutoTrait(_)
| ty::ExistentialPredicate::Projection(_) => {
self.check_op(ops::ty::TraitBound)
}
ty::ExistentialPredicate::Trait(trait_ref) => {
if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
self.check_op(ops::ty::TraitBound)
}
}
}
}
}
_ => {}
}
}
}
fn check_item_predicates(&mut self) {
let ConstCx { tcx, def_id, .. } = *self.ccx;
let mut current = def_id.to_def_id();
loop {
let predicates = tcx.predicates_of(current);
for (predicate, _) in predicates.predicates {
match predicate.skip_binders() {
ty::PredicateAtom::RegionOutlives(_)
| ty::PredicateAtom::TypeOutlives(_)
| ty::PredicateAtom::WellFormed(_)
| ty::PredicateAtom::Projection(_)
| ty::PredicateAtom::ConstEvaluatable(..)
| ty::PredicateAtom::ConstEquate(..)
| ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
ty::PredicateAtom::ObjectSafe(_) => {
bug!("object safe predicate on function: {:#?}", predicate)
}
ty::PredicateAtom::ClosureKind(..) => {
bug!("closure kind predicate on function: {:#?}", predicate)
}
ty::PredicateAtom::Subtype(_) => {
bug!("subtype predicate on function: {:#?}", predicate)
}
ty::PredicateAtom::Trait(pred, constness) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
}
match pred.self_ty().kind() {
ty::Param(p) => {
let generics = tcx.generics_of(current);
let def = generics.type_param(p, tcx);
let span = tcx.def_span(def.def_id);
if constness == hir::Constness::Const {
self.check_op_spanned(ops::ty::TraitBound, span);
} else if !tcx.features().const_fn
|| self.ccx.is_const_stable_const_fn()
{
// HACK: We shouldn't need the conditional above, but trait
// bounds on containing impl blocks are wrongly being marked as
// "not-const".
self.check_op_spanned(ops::ty::TraitBound, span);
}
}
// other kinds of bounds are either tautologies
// or cause errors in other passes
_ => continue,
}
}
}
}
match predicates.parent {
Some(parent) => current = parent,
None => break,
}
}
}
}
impl Visitor<'tcx> for Validator<'mir, 'tcx> {
@ -309,11 +446,6 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
Rvalue::Use(_)
| Rvalue::Repeat(..)
| Rvalue::UnaryOp(UnOp::Neg, _)
| Rvalue::UnaryOp(UnOp::Not, _)
| Rvalue::NullaryOp(NullOp::SizeOf, _)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::Cast(CastKind::Pointer(_), ..)
| Rvalue::Discriminant(..)
| Rvalue::Len(_)
| Rvalue::Aggregate(..) => {}
@ -363,6 +495,35 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
}
}
Rvalue::Cast(
CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
_,
_,
) => {}
Rvalue::Cast(
CastKind::Pointer(
PointerCast::UnsafeFnPointer
| PointerCast::ClosureFnPointer(_)
| PointerCast::ReifyFnPointer,
),
_,
_,
) => self.check_op(ops::FnPtrCast),
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), _, cast_ty) => {
if let Some(TypeAndMut { ty, .. }) = cast_ty.builtin_deref(true) {
let unsized_ty = self.tcx.struct_tail_erasing_lifetimes(ty, self.param_env);
// Casting/coercing things to slices is fine.
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
return;
}
}
self.check_op(ops::UnsizingCast);
}
Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
let operand_ty = operand.ty(self.body, self.tcx);
let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
@ -373,8 +534,23 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
}
}
Rvalue::BinaryOp(op, ref lhs, _) => {
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind() {
Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
Rvalue::UnaryOp(_, ref operand) => {
let ty = operand.ty(self.body, self.tcx);
if !(ty.is_integral() || ty.is_bool()) {
self.check_op(ops::NonPrimitiveOp)
}
}
Rvalue::BinaryOp(op, ref lhs, ref rhs)
| Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
let lhs_ty = lhs.ty(self.body, self.tcx);
let rhs_ty = rhs.ty(self.body, self.tcx);
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs_ty.kind() {
assert_eq!(lhs_ty, rhs_ty);
assert!(
op == BinOp::Eq
|| op == BinOp::Ne
@ -387,10 +563,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
self.check_op(ops::RawPtrComparison);
}
}
Rvalue::NullaryOp(NullOp::Box, _) => {
self.check_op(ops::HeapAllocation);
if !(lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char())
|| !(rhs_ty.is_integral() || rhs_ty.is_bool() || rhs_ty.is_char())
{
self.check_op(ops::NonPrimitiveOp)
}
}
}
}
@ -491,14 +669,19 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
use rustc_target::spec::abi::Abi::RustIntrinsic;
trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);
self.super_terminator(terminator, location);
match &terminator.kind {
TerminatorKind::Call { func, .. } => {
let fn_ty = func.ty(self.body, self.tcx);
let ConstCx { tcx, body, def_id: caller, param_env, .. } = *self.ccx;
let caller = caller.to_def_id();
let (def_id, substs) = match *fn_ty.kind() {
let fn_ty = func.ty(body, tcx);
let (mut callee, substs) = match *fn_ty.kind() {
ty::FnDef(def_id, substs) => (def_id, substs),
ty::FnPtr(_) => {
@ -510,38 +693,80 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
}
};
// At this point, we are calling a function whose `DefId` is known...
if is_const_fn(self.tcx, def_id) {
return;
}
// See if this is a trait method for a concrete type whose impl of that trait is
// `const`.
// Resolve a trait method call to its concrete implementation, which may be in a
// `const` trait impl.
if self.tcx.features().const_trait_impl {
let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs);
debug!("Resolving ({:?}) -> {:?}", def_id, instance);
let instance = Instance::resolve(tcx, param_env, callee, substs);
debug!("Resolving ({:?}) -> {:?}", callee, instance);
if let Ok(Some(func)) = instance {
if let InstanceDef::Item(def) = func.def {
if is_const_fn(self.tcx, def.did) {
return;
}
callee = def.did;
}
}
}
if is_lang_panic_fn(self.tcx, def_id) {
// At this point, we are calling a function, `callee`, whose `DefId` is known...
if is_lang_panic_fn(tcx, callee) {
self.check_op(ops::Panic);
} else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) {
// Exempt unstable const fns inside of macros or functions with
// `#[allow_internal_unstable]`.
use crate::transform::qualify_min_const_fn::lib_feature_allowed;
if !self.span.allows_unstable(feature)
&& !lib_feature_allowed(self.tcx, self.def_id.to_def_id(), feature)
{
self.check_op(ops::FnCallUnstable(def_id, feature));
return;
}
// HACK: This is to "unstabilize" the `transmute` intrinsic
// within const fns. `transmute` is allowed in all other const contexts.
// This won't really scale to more intrinsics or functions. Let's allow const
// transmutes in const fn before we add more hacks to this.
if tcx.fn_sig(callee).abi() == RustIntrinsic
&& tcx.item_name(callee) == sym::transmute
{
self.check_op(ops::Transmute);
return;
}
if !tcx.is_const_fn_raw(callee) {
self.check_op(ops::FnCallNonConst(callee));
return;
}
// If the `const fn` we are trying to call is not const-stable, ensure that we have
// the proper feature gate enabled.
if let Some(gate) = is_unstable_const_fn(tcx, callee) {
if self.span.allows_unstable(gate) {
return;
}
// Calling an unstable function *always* requires that the corresponding gate
// be enabled, even if the function has `#[allow_internal_unstable(the_gate)]`.
if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) {
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}
// If this crate is not using stability attributes, or the caller is not claiming to be a
// stable `const fn`, that is all that is required.
if !self.ccx.is_const_stable_const_fn() {
return;
}
// Otherwise, we are something const-stable calling a const-unstable fn.
if super::allow_internal_unstable(tcx, caller, gate) {
return;
}
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
return;
}
// FIXME(ecstaticmorse); For compatibility, we consider `unstable` callees that
// have no `rustc_const_stable` attributes to be const-unstable as well. This
// should be fixed later.
let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none()
&& tcx.lookup_stability(callee).map_or(false, |s| s.level.is_unstable());
if callee_is_unstable_unmarked {
if self.ccx.is_const_stable_const_fn() {
self.check_op(ops::FnCallUnstable(callee, None));
}
} else {
self.check_op(ops::FnCallNonConst(def_id));
}
}
@ -551,7 +776,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
| TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
// If we are checking live drops after drop-elaboration, don't emit duplicate
// errors here.
if super::post_drop_elaboration::checking_enabled(self.tcx, self.def_id) {
if super::post_drop_elaboration::checking_enabled(self.ccx) {
return;
}
@ -582,37 +807,25 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
}
}
TerminatorKind::InlineAsm { .. } => {
self.check_op(ops::InlineAsm);
TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
TerminatorKind::Abort => self.check_op(ops::Abort),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
self.check_op(ops::Generator)
}
// FIXME: Some of these are only caught by `min_const_fn`, but should error here
// instead.
TerminatorKind::Abort
| TerminatorKind::Assert { .. }
TerminatorKind::Assert { .. }
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::Goto { .. }
| TerminatorKind::Resume
| TerminatorKind::Return
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::Unreachable
| TerminatorKind::Yield { .. } => {}
| TerminatorKind::Unreachable => {}
}
}
}
fn error_min_const_fn_violation(tcx: TyCtxt<'_>, span: Span, msg: Cow<'_, str>) {
struct_span_err!(tcx.sess, span, E0723, "{}", msg)
.note(
"see issue #57563 <https://github.com/rust-lang/rust/issues/57563> \
for more information",
)
.help("add `#![feature(const_fn)]` to the crate attributes to enable")
.emit();
}
fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) {
let ty = body.return_ty();
tcx.infer_ctxt().enter(|infcx| {

View file

@ -217,6 +217,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
/// assert!(!bull.is_borrowed());
/// ```
#[unstable(feature = "cow_is_borrowed", issue = "65143")]
#[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")]
pub const fn is_borrowed(&self) -> bool {
match *self {
Borrowed(_) => true,
@ -239,6 +240,7 @@ impl<B: ?Sized + ToOwned> Cow<'_, B> {
/// assert!(!bull.is_owned());
/// ```
#[unstable(feature = "cow_is_borrowed", issue = "65143")]
#[rustc_const_unstable(feature = "const_cow_is_borrowed", issue = "65143")]
pub const fn is_owned(&self) -> bool {
!self.is_borrowed()
}

View file

@ -86,9 +86,11 @@
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(const_btree_new)]
#![feature(const_fn)]
#![feature(const_generics)]
#![feature(const_in_array_repeat_expressions)]
#![feature(cow_is_borrowed)]
#![feature(const_cow_is_borrowed)]
#![feature(dispatch_from_dyn)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]

View file

@ -150,6 +150,7 @@ impl<T> RawVec<T, Global> {
impl<T, A: AllocRef> RawVec<T, A> {
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
#[allow_internal_unstable(const_fn)]
pub const fn new_in(alloc: A) -> Self {
// `cap: 0` means "unallocated". zero-sized types are ignored.
Self { ptr: Unique::dangling(), cap: 0, alloc }

View file

@ -1,6 +1,7 @@
#![feature(allocator_api)]
#![feature(box_syntax)]
#![feature(cow_is_borrowed)]
#![feature(const_cow_is_borrowed)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(new_uninit)]

View file

@ -177,6 +177,7 @@ impl Layout {
/// sentinel value. Types that lazily allocate must track initialization by
/// some other means.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[rustc_const_unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub const fn dangling(&self) -> NonNull<u8> {
// SAFETY: align is guaranteed to be non-zero

View file

@ -56,6 +56,7 @@ unsafe impl Sync for ResumeTy {}
#[lang = "from_generator"]
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[rustc_const_unstable(feature = "gen_future", issue = "50547")]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where

View file

@ -75,11 +75,13 @@
#![feature(const_float_bits_conv)]
#![feature(const_overflowing_int_methods)]
#![feature(const_int_unchecked_arith)]
#![feature(const_mut_refs)]
#![feature(const_int_pow)]
#![feature(constctlz)]
#![feature(const_panic)]
#![feature(const_pin)]
#![feature(const_fn_union)]
#![feature(const_fn)]
#![feature(const_generics)]
#![feature(const_option)]
#![feature(const_precise_live_drops)]

View file

@ -401,6 +401,7 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
}
impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
#[allow_internal_unstable(const_fn)]
pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
extern "C" fn run(
bridge: Bridge<'_>,
@ -413,6 +414,7 @@ impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
}
impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
#[allow_internal_unstable(const_fn)]
pub const fn expand2(
f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
) -> Self {
@ -457,6 +459,7 @@ impl ProcMacro {
}
}
#[allow_internal_unstable(const_fn)]
pub const fn custom_derive(
trait_name: &'static str,
attributes: &'static [&'static str],
@ -465,6 +468,7 @@ impl ProcMacro {
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
}
#[allow_internal_unstable(const_fn)]
pub const fn attr(
name: &'static str,
expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
@ -472,6 +476,7 @@ impl ProcMacro {
ProcMacro::Attr { name, client: Client::expand2(expand) }
}
#[allow_internal_unstable(const_fn)]
pub const fn bang(
name: &'static str,
expand: fn(crate::TokenStream) -> crate::TokenStream,

View file

@ -35,6 +35,7 @@ impl<'a, 'b, T: LambdaL> DerefMut for RefMutL<'a, 'b, T> {
pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);
impl<T: LambdaL> ScopedCell<T> {
#[allow_internal_unstable(const_fn)]
pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self {
ScopedCell(Cell::new(value))
}

View file

@ -20,6 +20,7 @@
)]
#![feature(nll)]
#![feature(staged_api)]
#![feature(const_fn)]
#![feature(allow_internal_unstable)]
#![feature(decl_macro)]
#![feature(extern_types)]

View file

@ -237,6 +237,7 @@
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_transmute)]
#![feature(const_fn)]
#![feature(const_ipv6)]
#![feature(const_raw_ptr_deref)]
#![feature(const_ipv4)]
@ -306,6 +307,7 @@
#![feature(str_internals)]
#![feature(test)]
#![feature(thread_local)]
#![feature(thread_local_internals)]
#![feature(toowned_clone_into)]
#![feature(total_cmp)]
#![feature(trace_macros)]

View file

@ -117,6 +117,7 @@ pub struct Key {
pub const INIT: StaticKey = StaticKey::new(None);
impl StaticKey {
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> StaticKey {
StaticKey { key: atomic::AtomicUsize::new(0), dtor }
}

View file

@ -225,6 +225,7 @@ impl<T: 'static> LocalKey<T> {
reason = "recently added to create a key",
issue = "none"
)]
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey<T> {
LocalKey { inner }
}
@ -497,6 +498,7 @@ pub mod os {
}
impl<T: 'static> Key<T> {
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
pub const fn new() -> Key<T> {
Key { os: OsStaticKey::new(Some(destroy_value::<T>)), marker: marker::PhantomData }
}

View file

@ -5,9 +5,7 @@ const X : usize = 2;
const fn f(x: usize) -> usize {
let mut sum = 0;
for i in 0..x {
//~^ ERROR E0015
//~| ERROR E0015
//~| ERROR E0658
//~^ ERROR mutable references
//~| ERROR E0080
//~| ERROR E0744
sum += i;

View file

@ -7,7 +7,7 @@ extern "C" {
const extern fn bar() {
unsafe {
regular_in_block();
//~^ ERROR: can only call other `const fn` within a `const fn`
//~^ ERROR: calls in constant functions
}
}
@ -16,7 +16,7 @@ extern fn regular() {}
const extern fn foo() {
unsafe {
regular();
//~^ ERROR: can only call other `const fn` within a `const fn`
//~^ ERROR: calls in constant functions
}
}

View file

@ -1,21 +1,15 @@
error[E0723]: can only call other `const fn` within a `const fn`, but `regular_in_block` is not stable as `const fn`
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-extern-fn-call-extern-fn.rs:9:9
|
LL | regular_in_block();
| ^^^^^^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: can only call other `const fn` within a `const fn`, but `regular` is not stable as `const fn`
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-extern-fn-call-extern-fn.rs:18:9
|
LL | regular();
| ^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0723`.
For more information about this error, try `rustc --explain E0015`.

View file

@ -6,7 +6,7 @@ const unsafe extern "C" fn closure() -> fn() { || {} }
const unsafe extern fn use_float() { 1.0 + 1.0; }
//~^ ERROR only int, `bool` and `char` operations are stable in const fn
const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
//~^ ERROR casting pointers to ints is unstable in const fn
//~^ ERROR casting pointers to integers
fn main() {}

View file

@ -16,15 +16,16 @@ LL | const unsafe extern fn use_float() { 1.0 + 1.0; }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: casting pointers to ints is unstable in const fn
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/const-extern-fn-min-const-fn.rs:8:48
|
LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
| ^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0723`.
Some errors have detailed explanations: E0658, E0723.
For more information about an error, try `rustc --explain E0658`.

View file

@ -1,6 +1,6 @@
// Test that we can't call random fns in a const fn or do other bad things.
#![feature(const_fn, const_transmute)]
#![feature(const_fn, const_fn_transmute)]
use std::mem::transmute;

View file

@ -2,6 +2,7 @@ fn main() {
foo(&mut 5);
}
const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn are unstable
const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references in const fn
*x + 1
}

View file

@ -6,8 +6,8 @@ struct S {
impl S {
const fn foo(&mut self, x: u32) {
//~^ ERROR mutable references
self.state = x;
//~^ contains unimplemented expression
}
}

View file

@ -1,10 +1,11 @@
error[E0019]: constant function contains unimplemented expression type
--> $DIR/const_let_assign3.rs:9:9
error[E0723]: mutable references in const fn are unstable
--> $DIR/const_let_assign3.rs:8:18
|
LL | self.state = x;
| ^^^^^^^^^^^^^^
LL | const fn foo(&mut self, x: u32) {
| ^^^^^^^^^
|
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0764]: mutable references are not allowed in constants
--> $DIR/const_let_assign3.rs:16:5
@ -28,5 +29,5 @@ LL | *y = 42;
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0019, E0764.
Some errors have detailed explanations: E0019, E0723, E0764.
For more information about an error, try `rustc --explain E0019`.

View file

@ -1,5 +1,8 @@
const fn foo(a: i32) -> Vec<i32> {
vec![1, 2, 3] //~ ERROR heap allocations are not allowed in const fn
vec![1, 2, 3]
//~^ ERROR allocations are not allowed
//~| ERROR unimplemented expression type
//~| ERROR calls in constant functions
}
fn main() {}

View file

@ -1,13 +1,29 @@
error[E0723]: heap allocations are not allowed in const fn
error[E0010]: allocations are not allowed in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^ allocation not allowed in constant functions
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0019]: constant function contains unimplemented expression type
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0723`.
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0010, E0015, E0019.
For more information about an error, try `rustc --explain E0010`.

View file

@ -78,25 +78,25 @@ const fn foo11<T: std::fmt::Display>(t: T) -> T { t }
const fn foo11_2<T: Send>(t: T) -> T { t }
//~^ ERROR trait bounds other than `Sized` on const fn parameters are unstable
const fn foo19(f: f32) -> f32 { f * 2.0 }
//~^ ERROR only int, `bool` and `char` operations are stable in const fn
//~^ ERROR int, `bool` and `char` operations
const fn foo19_2(f: f32) -> f32 { 2.0 - f }
//~^ ERROR only int, `bool` and `char` operations are stable in const fn
//~^ ERROR int, `bool` and `char` operations
const fn foo19_3(f: f32) -> f32 { -f }
//~^ ERROR only int and `bool` operations are stable in const fn
//~^ ERROR int, `bool` and `char` operations
const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
//~^ ERROR only int, `bool` and `char` operations are stable in const fn
//~^ ERROR int, `bool` and `char` operations
static BAR: u32 = 42;
const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
const fn foo25() -> u32 { BAR } //~ ERROR cannot refer to statics
const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot refer to statics
const fn foo30(x: *const u32) -> usize { x as usize }
//~^ ERROR casting pointers to ints is unstable
//~^ ERROR casting pointers to integers
const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
//~^ ERROR casting pointers to ints is unstable
//~^ ERROR casting pointers to integers
const fn foo30_2(x: *mut u32) -> usize { x as usize }
//~^ ERROR casting pointers to ints is unstable
//~^ ERROR casting pointers to integers
const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
//~^ ERROR casting pointers to ints is unstable
//~^ ERROR casting pointers to integers
const fn foo30_6() -> bool { let x = true; x }
const fn inc(x: &mut i32) { *x += 1 }
//~^ ERROR mutable references in const fn are unstable

View file

@ -94,7 +94,7 @@ LL | const fn foo19_2(f: f32) -> f32 { 2.0 - f }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: only int and `bool` operations are stable in const fn
error[E0723]: only int, `bool` and `char` operations are stable in const fn
--> $DIR/min_const_fn.rs:84:35
|
LL | const fn foo19_3(f: f32) -> f32 { -f }
@ -112,59 +112,57 @@ LL | const fn foo19_4(f: f32, g: f32) -> f32 { f / g }
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: cannot access `static` items in const fn
error[E0013]: constant functions cannot refer to statics
--> $DIR/min_const_fn.rs:90:27
|
LL | const fn foo25() -> u32 { BAR }
| ^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0723]: cannot access `static` items in const fn
error[E0013]: constant functions cannot refer to statics
--> $DIR/min_const_fn.rs:91:37
|
LL | const fn foo26() -> &'static u32 { &BAR }
| ^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0723]: casting pointers to ints is unstable in const fn
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:92:42
|
LL | const fn foo30(x: *const u32) -> usize { x as usize }
| ^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0723]: casting pointers to ints is unstable in const fn
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:94:63
|
LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0723]: casting pointers to ints is unstable in const fn
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:96:42
|
LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
| ^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0723]: casting pointers to ints is unstable in const fn
error[E0658]: casting pointers to integers in constant functions is unstable
--> $DIR/min_const_fn.rs:98:63
|
LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
| ^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51910 <https://github.com/rust-lang/rust/issues/51910> for more information
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
error[E0723]: mutable references in const fn are unstable
--> $DIR/min_const_fn.rs:101:14
@ -267,5 +265,5 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
error: aborting due to 30 previous errors
Some errors have detailed explanations: E0493, E0723.
For more information about an error, try `rustc --explain E0493`.
Some errors have detailed explanations: E0013, E0493, E0658, E0723.
For more information about an error, try `rustc --explain E0013`.

View file

@ -13,7 +13,7 @@ const fn foo() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn`
const fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
#[unstable(feature = "rust1", issue = "none")]
const fn foo2() -> u32 { 42 }
@ -21,12 +21,13 @@ const fn foo2() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn`
const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// conformity is required, even with `const_fn` feature gate
const fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` operations
const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
//~^ ERROR const-stable function cannot use `#[feature(const_fn)]`
// check whether this function cannot be called even with the feature gate active
#[unstable(feature = "foo2", issue = "none")]
@ -35,6 +36,6 @@ const fn foo2_gated() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `const fn`
const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
fn main() {}

View file

@ -1,39 +1,38 @@
error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
error: `foo` is not yet stable as a const fn
--> $DIR/min_const_fn_libstd_stability.rs:16:25
|
LL | const fn bar() -> u32 { foo() }
| ^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
error: `foo2` is not yet stable as a const fn
--> $DIR/min_const_fn_libstd_stability.rs:24:26
|
LL | const fn bar2() -> u32 { foo2() }
| ^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: only int, `bool` and `char` operations are stable in const fn
error: const-stable function cannot use `#[feature(const_fn)]`
--> $DIR/min_const_fn_libstd_stability.rs:29:26
|
LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 }
| ^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks
help: if it is not part of the public API, make this function unstably const
|
LL | #[rustc_const_unstable(feature = "...", issue = "...")]
|
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
--> $DIR/min_const_fn_libstd_stability.rs:38:32
error: `foo2_gated` is not yet stable as a const fn
--> $DIR/min_const_fn_libstd_stability.rs:39:32
|
LL | const fn bar2_gated() -> u32 { foo2_gated() }
| ^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0723`.

View file

@ -12,5 +12,5 @@ fn main() {}
const unsafe fn no_union() {
union Foo { x: (), y: () }
Foo { x: () }.y
//~^ accessing union fields is unstable
//~^ unions in const fn
}

View file

@ -25,16 +25,15 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u
= note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
= help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
error[E0723]: accessing union fields is unstable
error[E0658]: unions in const fn are unstable
--> $DIR/min_const_fn_unsafe_bad.rs:14:5
|
LL | Foo { x: () }.y
| ^^^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: see issue #51909 <https://github.com/rust-lang/rust/issues/51909> for more information
= help: add `#![feature(const_fn_union)]` to the crate attributes to enable
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0658, E0723.
For more information about an error, try `rustc --explain E0658`.
For more information about this error, try `rustc --explain E0658`.

View file

@ -13,7 +13,7 @@ const unsafe fn foo() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `const fn`
const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR not yet stable as a const fn
#[unstable(feature = "rust1", issue = "none")]
const unsafe fn foo2() -> u32 { 42 }
@ -21,12 +21,13 @@ const unsafe fn foo2() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `const fn`
const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as a const fn
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// conformity is required, even with `const_fn` feature gate
const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } //~ ERROR only int, `bool` and `char` op
const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
//~^ ERROR const-stable function cannot use `#[feature(const_fn)]`
// check whether this function cannot be called even with the feature gate active
#[unstable(feature = "foo2", issue = "none")]
@ -36,6 +37,6 @@ const unsafe fn foo2_gated() -> u32 { 42 }
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
//~^ ERROR can only call other `const fn`
//~^ ERROR not yet stable as a const fn
fn main() {}

View file

@ -1,39 +1,38 @@
error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
error: `foo` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41
|
LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
| ^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
error: `foo2` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42
|
LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
| ^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: only int, `bool` and `char` operations are stable in const fn
error: const-stable function cannot use `#[feature(const_fn)]`
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:29:33
|
LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 }
| ^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= note: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks
help: if it is not part of the public API, make this function unstably const
|
LL | #[rustc_const_unstable(feature = "...", issue = "...")]
|
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:38:48
error: `foo2_gated` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:39:48
|
LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
| ^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0723`.

View file

@ -13,7 +13,7 @@ const fn foo() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn`
const unsafe fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
#[unstable(feature = "rust1", issue = "none")]
const fn foo2() -> u32 { 42 }
@ -21,7 +21,7 @@ const fn foo2() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn`
const unsafe fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
// check whether this function cannot be called even with the feature gate active
#[unstable(feature = "foo2", issue = "none")]
@ -30,6 +30,6 @@ const fn foo2_gated() -> u32 { 42 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
// can't call non-min_const_fn
const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `const fn`
const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
fn main() {}

View file

@ -1,30 +1,26 @@
error[E0723]: can only call other `const fn` within a `const fn`, but `foo` is not stable as `const fn`
error: `foo` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32
|
LL | const unsafe fn bar() -> u32 { foo() }
| ^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2` is not stable as `const fn`
error: `foo2` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33
|
LL | const unsafe fn bar2() -> u32 { foo2() }
| ^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error[E0723]: can only call other `const fn` within a `const fn`, but `foo2_gated` is not stable as `const fn`
error: `foo2_gated` is not yet stable as a const fn
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39
|
LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
| ^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0723`.

View file

@ -12,6 +12,16 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "
warning: skipping const checks
|
help: skipping check for `const_fn` feature
--> $DIR/abi-mismatch.rs:9:23
|
LL | const fn call_rust_fn(my_fn: extern "Rust" fn()) {
| ^^^^^
help: skipping check for `const_fn` feature
--> $DIR/abi-mismatch.rs:10:5
|
LL | my_fn();
| ^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/abi-mismatch.rs:10:5
|

View file

@ -4,7 +4,7 @@ use std::ptr::NonNull;
pub const fn dangling_slice<T>() -> NonNull<[T]> {
NonNull::<[T; 0]>::dangling()
//~^ ERROR: unsizing casts are only allowed for references right now
//~^ ERROR: unsizing casts to types besides slices
}
fn main() {}

View file

@ -1,4 +1,4 @@
error[E0723]: unsizing casts are only allowed for references right now
error[E0723]: unsizing casts to types besides slices are not allowed in const fn
--> $DIR/unsizing-cast-non-null.rs:6:5
|
LL | NonNull::<[T; 0]>::dangling()

View file

@ -6,6 +6,7 @@
#![stable(feature = "core", since = "1.6.0")]
#![feature(rustc_const_unstable)]
#![feature(staged_api)]
#![feature(const_fn)]
enum Opt<T> {
Some(T),

View file

@ -1,11 +1,11 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/unstable-const-fn-in-libcore.rs:23:26
--> $DIR/unstable-const-fn-in-libcore.rs:24:26
|
LL | Opt::None => f(),
| ^^^
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:18:53
--> $DIR/unstable-const-fn-in-libcore.rs:19:53
|
LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
| ^ constant functions cannot evaluate destructors
@ -14,7 +14,7 @@ LL | }
| - value is dropped here
error[E0493]: destructors cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:18:47
--> $DIR/unstable-const-fn-in-libcore.rs:19:47
|
LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
| ^^^^ constant functions cannot evaluate destructors

View file

@ -12,6 +12,7 @@ fn main() {
extern "C" fn ff4() {} // OK.
const async unsafe extern "C" fn ff5() {} // OK.
//~^ ERROR functions cannot be both `const` and `async`
//~| ERROR `from_generator` is not yet stable as a const fn
trait X {
async fn ft1(); //~ ERROR functions in traits cannot be declared `async`
@ -34,6 +35,7 @@ fn main() {
const async unsafe extern "C" fn ft5() {}
//~^ ERROR functions in traits cannot be declared `async`
//~| ERROR functions in traits cannot be declared const
//~| ERROR `from_generator` is not yet stable as a const fn
//~| ERROR method `ft5` has an incompatible type for trait
//~| ERROR functions cannot be both `const` and `async`
}
@ -45,6 +47,7 @@ fn main() {
extern "C" fn fi4() {} // OK.
const async unsafe extern "C" fn fi5() {}
//~^ ERROR functions cannot be both `const` and `async`
//~| ERROR `from_generator` is not yet stable as a const fn
}
extern {

View file

@ -8,7 +8,7 @@ LL | const async unsafe extern "C" fn ff5() {} // OK.
| `const` because of this
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:17:9
--> $DIR/fn-header-semantic-fail.rs:18:9
|
LL | async fn ft1();
| -----^^^^^^^^^^
@ -19,19 +19,19 @@ LL | async fn ft1();
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
error[E0379]: functions in traits cannot be declared const
--> $DIR/fn-header-semantic-fail.rs:19:9
--> $DIR/fn-header-semantic-fail.rs:20:9
|
LL | const fn ft3();
| ^^^^^ functions in traits cannot be const
error[E0379]: functions in traits cannot be declared const
--> $DIR/fn-header-semantic-fail.rs:21:9
--> $DIR/fn-header-semantic-fail.rs:22:9
|
LL | const async unsafe extern "C" fn ft5();
| ^^^^^ functions in traits cannot be const
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:21:9
--> $DIR/fn-header-semantic-fail.rs:22:9
|
LL | const async unsafe extern "C" fn ft5();
| ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -42,7 +42,7 @@ LL | const async unsafe extern "C" fn ft5();
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
error: functions cannot be both `const` and `async`
--> $DIR/fn-header-semantic-fail.rs:21:9
--> $DIR/fn-header-semantic-fail.rs:22:9
|
LL | const async unsafe extern "C" fn ft5();
| ^^^^^-^^^^^----------------------------
@ -51,7 +51,7 @@ LL | const async unsafe extern "C" fn ft5();
| `const` because of this
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:29:9
--> $DIR/fn-header-semantic-fail.rs:30:9
|
LL | async fn ft1() {}
| -----^^^^^^^^^^^^
@ -62,19 +62,19 @@ LL | async fn ft1() {}
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
error[E0379]: functions in traits cannot be declared const
--> $DIR/fn-header-semantic-fail.rs:32:9
--> $DIR/fn-header-semantic-fail.rs:33:9
|
LL | const fn ft3() {}
| ^^^^^ functions in traits cannot be const
error[E0379]: functions in traits cannot be declared const
--> $DIR/fn-header-semantic-fail.rs:34:9
--> $DIR/fn-header-semantic-fail.rs:35:9
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^ functions in traits cannot be const
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:34:9
--> $DIR/fn-header-semantic-fail.rs:35:9
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -85,7 +85,7 @@ LL | const async unsafe extern "C" fn ft5() {}
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
error: functions cannot be both `const` and `async`
--> $DIR/fn-header-semantic-fail.rs:34:9
--> $DIR/fn-header-semantic-fail.rs:35:9
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^-^^^^^------------------------------
@ -94,7 +94,7 @@ LL | const async unsafe extern "C" fn ft5() {}
| `const` because of this
error: functions cannot be both `const` and `async`
--> $DIR/fn-header-semantic-fail.rs:46:9
--> $DIR/fn-header-semantic-fail.rs:48:9
|
LL | const async unsafe extern "C" fn fi5() {}
| ^^^^^-^^^^^------------------------------
@ -103,7 +103,7 @@ LL | const async unsafe extern "C" fn fi5() {}
| `const` because of this
error: functions in `extern` blocks cannot have qualifiers
--> $DIR/fn-header-semantic-fail.rs:51:18
--> $DIR/fn-header-semantic-fail.rs:54:18
|
LL | extern {
| ------ in this `extern` block
@ -113,7 +113,7 @@ LL | async fn fe1();
| help: remove the qualifiers: `fn`
error: functions in `extern` blocks cannot have qualifiers
--> $DIR/fn-header-semantic-fail.rs:52:19
--> $DIR/fn-header-semantic-fail.rs:55:19
|
LL | extern {
| ------ in this `extern` block
@ -124,7 +124,7 @@ LL | unsafe fn fe2();
| help: remove the qualifiers: `fn`
error: functions in `extern` blocks cannot have qualifiers
--> $DIR/fn-header-semantic-fail.rs:53:18
--> $DIR/fn-header-semantic-fail.rs:56:18
|
LL | extern {
| ------ in this `extern` block
@ -135,7 +135,7 @@ LL | const fn fe3();
| help: remove the qualifiers: `fn`
error: functions in `extern` blocks cannot have qualifiers
--> $DIR/fn-header-semantic-fail.rs:54:23
--> $DIR/fn-header-semantic-fail.rs:57:23
|
LL | extern {
| ------ in this `extern` block
@ -146,7 +146,7 @@ LL | extern "C" fn fe4();
| help: remove the qualifiers: `fn`
error: functions in `extern` blocks cannot have qualifiers
--> $DIR/fn-header-semantic-fail.rs:55:42
--> $DIR/fn-header-semantic-fail.rs:58:42
|
LL | extern {
| ------ in this `extern` block
@ -157,7 +157,7 @@ LL | const async unsafe extern "C" fn fe5();
| help: remove the qualifiers: `fn`
error: functions cannot be both `const` and `async`
--> $DIR/fn-header-semantic-fail.rs:55:9
--> $DIR/fn-header-semantic-fail.rs:58:9
|
LL | const async unsafe extern "C" fn fe5();
| ^^^^^-^^^^^----------------------------
@ -165,8 +165,16 @@ LL | const async unsafe extern "C" fn fe5();
| | `async` because of this
| `const` because of this
error: `from_generator` is not yet stable as a const fn
--> $DIR/fn-header-semantic-fail.rs:13:44
|
LL | const async unsafe extern "C" fn ff5() {} // OK.
| ^^
|
= help: add `#![feature(gen_future)]` to the crate attributes to enable
error[E0053]: method `ft1` has an incompatible type for trait
--> $DIR/fn-header-semantic-fail.rs:29:24
--> $DIR/fn-header-semantic-fail.rs:30:24
|
LL | async fn ft1();
| - type in trait
@ -181,7 +189,7 @@ LL | async fn ft1() {}
found fn pointer `fn() -> impl Future`
error[E0053]: method `ft5` has an incompatible type for trait
--> $DIR/fn-header-semantic-fail.rs:34:48
--> $DIR/fn-header-semantic-fail.rs:35:48
|
LL | const async unsafe extern "C" fn ft5();
| - type in trait
@ -195,7 +203,23 @@ LL | const async unsafe extern "C" fn ft5() {}
= note: expected fn pointer `unsafe extern "C" fn()`
found fn pointer `unsafe extern "C" fn() -> impl Future`
error: aborting due to 20 previous errors
error: `from_generator` is not yet stable as a const fn
--> $DIR/fn-header-semantic-fail.rs:35:48
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^
|
= help: add `#![feature(gen_future)]` to the crate attributes to enable
error: `from_generator` is not yet stable as a const fn
--> $DIR/fn-header-semantic-fail.rs:48:48
|
LL | const async unsafe extern "C" fn fi5() {}
| ^^
|
= help: add `#![feature(gen_future)]` to the crate attributes to enable
error: aborting due to 23 previous errors
Some errors have detailed explanations: E0053, E0379, E0706.
For more information about an error, try `rustc --explain E0053`.

View file

@ -10,7 +10,7 @@ fn non_const() {}
impl const T for S {
fn foo() { non_const() }
//~^ ERROR can only call other `const fn`
//~^ ERROR calls in constant functions
}
fn main() {}

View file

@ -1,12 +1,9 @@
error[E0723]: can only call other `const fn` within a `const fn`, but `non_const` is not stable as `const fn`
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/const-check-fns-in-const-impl.rs:12:16
|
LL | fn foo() { non_const() }
| ^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0723`.
For more information about this error, try `rustc --explain E0015`.

View file

@ -1,5 +1,5 @@
error: fatal error triggered by #[rustc_error]
--> $DIR/feature-gate.rs:16:1
--> $DIR/feature-gate.rs:17:1
|
LL | fn main() {}
| ^^^^^^^^^

View file

@ -4,6 +4,7 @@
#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
#![allow(incomplete_features)]
#![feature(rustc_attrs)]
#![feature(const_fn)]
trait T {
const CONST: i32;

View file

@ -1,5 +1,5 @@
error[E0658]: `?const` on trait bounds is experimental
--> $DIR/feature-gate.rs:12:29
--> $DIR/feature-gate.rs:13:29
|
LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
| ^^^^^^

View file

@ -30,7 +30,7 @@ impl const std::ops::Add for Int {
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
pub const fn foo() -> Int {
Int(1i32) + Int(2i32)
//~^ ERROR can only call other `const fn` within a `const fn`
//~^ ERROR not yet stable as a const fn
}
// ok

View file

@ -6,18 +6,14 @@ LL | |
LL | | Int(self.0 - rhs.0)
LL | | }
| |_____^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
error[E0723]: can only call other `const fn` within a `const fn`, but `<Int as Add>::add` is not stable as `const fn`
error: `<Int as Add>::add` is not yet stable as a const fn
--> $DIR/stability.rs:32:5
|
LL | Int(1i32) + Int(2i32)
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
= help: add `#![feature(const_fn)]` to the crate attributes to enable
= help: Const-stable functions can only call other const-stable functions
error: aborting due to 2 previous errors

View file

@ -8,13 +8,13 @@ fn main() {
const fn foo() -> NonZero<u32> {
let mut x = unsafe { NonZero(1) };
let y = &mut x.0; //~ ERROR references in const fn are unstable
let y = &mut x.0; //~ ERROR mutable references
//~^ ERROR mutation of layout constrained field is unsafe
unsafe { NonZero(1) }
}
const fn bar() -> NonZero<u32> {
let mut x = unsafe { NonZero(1) };
let y = unsafe { &mut x.0 }; //~ ERROR mutable references in const fn are unstable
let y = unsafe { &mut x.0 }; //~ ERROR mutable references
unsafe { NonZero(1) }
}