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:
commit
f6d59207ad
54 changed files with 789 additions and 257 deletions
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
)]
|
||||
#![feature(nll)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(extern_types)]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ struct S {
|
|||
|
||||
impl S {
|
||||
const fn foo(&mut self, x: u32) {
|
||||
//~^ ERROR mutable references
|
||||
self.state = x;
|
||||
//~^ contains unimplemented expression
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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() {}
|
||||
| ^^^^^^^^^
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }
|
||||
| ^^^^^^
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue