mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Re-do recursive const stability checks
Fundamentally, we have *three* disjoint categories of functions: 1. const-stable functions 2. private/unstable functions that are meant to be callable from const-stable functions 3. functions that can make use of unstable const features This PR implements the following system: - `#[rustc_const_stable]` puts functions in the first category. It may only be applied to `#[stable]` functions. - `#[rustc_const_unstable]` by default puts functions in the third category. The new attribute `#[rustc_const_stable_indirect]` can be added to such a function to move it into the second category. - `const fn` without a const stability marker are in the second category if they are still unstable. They automatically inherit the feature gate for regular calls, it can now also be used for const-calls. Also, several holes in recursive const stability checking are being closed. There's still one potential hole that is hard to avoid, which is when MIR building automatically inserts calls to a particular function in stable functions -- which happens in the panic machinery. Those need to *not* be `rustc_const_unstable` (or manually get a `rustc_const_stable_indirect`) to be sure they follow recursive const stability. But that's a fairly rare and special case so IMO it's fine. The net effect of this is that a `#[unstable]` or unmarked function can be constified simply by marking it as `const fn`, and it will then be const-callable from stable `const fn` and subject to recursive const stability requirements. If it is publicly reachable (which implies it cannot be unmarked), it will be const-unstable under the same feature gate. Only if the function ever becomes `#[stable]` does it need a `#[rustc_const_unstable]` or `#[rustc_const_stable]` marker to decide if this should also imply const-stability. Adding `#[rustc_const_unstable]` is only needed for (a) functions that need to use unstable const lang features (including intrinsics), or (b) `#[stable]` functions that are not yet intended to be const-stable. Adding `#[rustc_const_stable]` is only needed for functions that are actually meant to be directly callable from stable const code. `#[rustc_const_stable_indirect]` is used to mark intrinsics as const-callable and for `#[rustc_const_unstable]` functions that are actually called from other, exposed-on-stable `const fn`. No other attributes are required.
This commit is contained in:
parent
45089ec19e
commit
a0215d8e46
@ -91,6 +91,9 @@ attr_non_ident_feature =
|
|||||||
attr_rustc_allowed_unstable_pairing =
|
attr_rustc_allowed_unstable_pairing =
|
||||||
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
|
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
|
||||||
|
|
||||||
|
attr_rustc_const_stable_indirect_pairing =
|
||||||
|
`const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied
|
||||||
|
|
||||||
attr_rustc_promotable_pairing =
|
attr_rustc_promotable_pairing =
|
||||||
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
|
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
|
|||||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::symbol::{Symbol, kw, sym};
|
use rustc_span::symbol::{Symbol, kw, sym};
|
||||||
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
|
|
||||||
use crate::fluent_generated;
|
use crate::fluent_generated;
|
||||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||||
@ -92,7 +92,11 @@ impl Stability {
|
|||||||
#[derive(HashStable_Generic)]
|
#[derive(HashStable_Generic)]
|
||||||
pub struct ConstStability {
|
pub struct ConstStability {
|
||||||
pub level: StabilityLevel,
|
pub level: StabilityLevel,
|
||||||
pub feature: Symbol,
|
/// This can be `None` for functions that do not have an explicit const feature.
|
||||||
|
/// We still track them for recursive const stability checks.
|
||||||
|
pub feature: Option<Symbol>,
|
||||||
|
/// This is true iff the `const_stable_indirect` attribute is present.
|
||||||
|
pub const_stable_indirect: bool,
|
||||||
/// whether the function has a `#[rustc_promotable]` attribute
|
/// whether the function has a `#[rustc_promotable]` attribute
|
||||||
pub promotable: bool,
|
pub promotable: bool,
|
||||||
}
|
}
|
||||||
@ -268,17 +272,23 @@ pub fn find_stability(
|
|||||||
|
|
||||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||||
|
///
|
||||||
|
/// `is_const_fn` indicates whether this is a function marked as `const`. It will always
|
||||||
|
/// be false for intrinsics in an `extern` block!
|
||||||
pub fn find_const_stability(
|
pub fn find_const_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
|
is_const_fn: bool,
|
||||||
) -> Option<(ConstStability, Span)> {
|
) -> Option<(ConstStability, Span)> {
|
||||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||||
let mut promotable = false;
|
let mut promotable = false;
|
||||||
|
let mut const_stable_indirect = None;
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
match attr.name_or_empty() {
|
match attr.name_or_empty() {
|
||||||
sym::rustc_promotable => promotable = true,
|
sym::rustc_promotable => promotable = true,
|
||||||
|
sym::rustc_const_stable_indirect => const_stable_indirect = Some(attr.span),
|
||||||
sym::rustc_const_unstable => {
|
sym::rustc_const_unstable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
@ -287,8 +297,15 @@ pub fn find_const_stability(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||||
const_stab =
|
const_stab = Some((
|
||||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
ConstStability {
|
||||||
|
level,
|
||||||
|
feature: Some(feature),
|
||||||
|
const_stable_indirect: false,
|
||||||
|
promotable: false,
|
||||||
|
},
|
||||||
|
attr.span,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::rustc_const_stable => {
|
sym::rustc_const_stable => {
|
||||||
@ -298,15 +315,22 @@ pub fn find_const_stability(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||||
const_stab =
|
const_stab = Some((
|
||||||
Some((ConstStability { level, feature, promotable: false }, attr.span));
|
ConstStability {
|
||||||
|
level,
|
||||||
|
feature: Some(feature),
|
||||||
|
const_stable_indirect: false,
|
||||||
|
promotable: false,
|
||||||
|
},
|
||||||
|
attr.span,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the const-unstable info into the stability info
|
// Merge promotable and not_exposed_on_stable into stability info
|
||||||
if promotable {
|
if promotable {
|
||||||
match &mut const_stab {
|
match &mut const_stab {
|
||||||
Some((stab, _)) => stab.promotable = promotable,
|
Some((stab, _)) => stab.promotable = promotable,
|
||||||
@ -317,6 +341,46 @@ pub fn find_const_stability(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if const_stable_indirect.is_some() {
|
||||||
|
match &mut const_stab {
|
||||||
|
Some((stab, _)) => {
|
||||||
|
if stab.is_const_unstable() {
|
||||||
|
stab.const_stable_indirect = true;
|
||||||
|
} else {
|
||||||
|
_ = sess.dcx().emit_err(session_diagnostics::RustcConstStableIndirectPairing {
|
||||||
|
span: item_sp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
|
||||||
|
// the `default_const_unstable` logic.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
|
||||||
|
// fn` get *some* marker, since we are a staged_api crate and therefore will do recursive const
|
||||||
|
// stability checks for them. We need to do this because the default for whether an unmarked
|
||||||
|
// function enforces recursive stability differs between staged-api crates and force-unmarked
|
||||||
|
// crates: in force-unmarked crates, only functions *explicitly* marked `const_stable_indirect`
|
||||||
|
// enforce recursive stability. Therefore when `lookup_const_stability` is `None`, we have to
|
||||||
|
// assume the function does not have recursive stability. All functions that *do* have recursive
|
||||||
|
// stability must explicitly record this, and so that's what we do for all `const fn` in a
|
||||||
|
// staged_api crate.
|
||||||
|
if (is_const_fn || const_stable_indirect.is_some()) && const_stab.is_none() {
|
||||||
|
let c = ConstStability {
|
||||||
|
feature: None,
|
||||||
|
const_stable_indirect: const_stable_indirect.is_some(),
|
||||||
|
promotable: false,
|
||||||
|
level: StabilityLevel::Unstable {
|
||||||
|
reason: UnstableReason::Default,
|
||||||
|
issue: None,
|
||||||
|
is_soft: false,
|
||||||
|
implied_by: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const_stab = Some((c, const_stable_indirect.unwrap_or(DUMMY_SP)));
|
||||||
|
}
|
||||||
|
|
||||||
const_stab
|
const_stab
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,13 @@ pub(crate) struct RustcPromotablePairing {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(attr_rustc_const_stable_indirect_pairing)]
|
||||||
|
pub(crate) struct RustcConstStableIndirectPairing {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
|
#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
|
||||||
pub(crate) struct RustcAllowedUnstablePairing {
|
pub(crate) struct RustcAllowedUnstablePairing {
|
||||||
|
@ -38,7 +38,7 @@ diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
|
|||||||
index d9de37e..8293fce 100644
|
index d9de37e..8293fce 100644
|
||||||
--- a/library/core/src/sync/atomic.rs
|
--- a/library/core/src/sync/atomic.rs
|
||||||
+++ b/library/core/src/sync/atomic.rs
|
+++ b/library/core/src/sync/atomic.rs
|
||||||
@@ -2996,42 +2996,6 @@ atomic_int! {
|
@@ -2996,44 +2996,6 @@ atomic_int! {
|
||||||
8,
|
8,
|
||||||
u64 AtomicU64
|
u64 AtomicU64
|
||||||
}
|
}
|
||||||
@ -52,7 +52,8 @@ index d9de37e..8293fce 100644
|
|||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
- rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
|
- rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"),
|
- cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"),
|
||||||
- "i128",
|
- "i128",
|
||||||
- "#![feature(integer_atomics)]\n\n",
|
- "#![feature(integer_atomics)]\n\n",
|
||||||
@ -70,7 +71,8 @@ index d9de37e..8293fce 100644
|
|||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- unstable(feature = "integer_atomics", issue = "99069"),
|
- unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
- rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
|
- rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
- cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"),
|
- cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"),
|
||||||
- "u128",
|
- "u128",
|
||||||
- "#![feature(integer_atomics)]\n\n",
|
- "#![feature(integer_atomics)]\n\n",
|
||||||
|
@ -41,8 +41,6 @@ const_eval_const_context = {$kind ->
|
|||||||
*[other] {""}
|
*[other] {""}
|
||||||
}
|
}
|
||||||
|
|
||||||
const_eval_const_stable = const-stable functions can only call other const-stable functions
|
|
||||||
|
|
||||||
const_eval_copy_nonoverlapping_overlapping =
|
const_eval_copy_nonoverlapping_overlapping =
|
||||||
`copy_nonoverlapping` called on overlapping ranges
|
`copy_nonoverlapping` called on overlapping ranges
|
||||||
|
|
||||||
@ -259,6 +257,9 @@ const_eval_non_const_fn_call =
|
|||||||
const_eval_non_const_impl =
|
const_eval_non_const_impl =
|
||||||
impl defined here, but it is not `const`
|
impl defined here, but it is not `const`
|
||||||
|
|
||||||
|
const_eval_non_const_intrinsic =
|
||||||
|
cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s
|
||||||
|
|
||||||
const_eval_not_enough_caller_args =
|
const_eval_not_enough_caller_args =
|
||||||
calling a function with fewer arguments than it requires
|
calling a function with fewer arguments than it requires
|
||||||
|
|
||||||
@ -397,17 +398,29 @@ const_eval_uninhabited_enum_variant_read =
|
|||||||
read discriminant of an uninhabited enum variant
|
read discriminant of an uninhabited enum variant
|
||||||
const_eval_uninhabited_enum_variant_written =
|
const_eval_uninhabited_enum_variant_written =
|
||||||
writing discriminant of an uninhabited enum variant
|
writing discriminant of an uninhabited enum variant
|
||||||
|
|
||||||
|
const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
|
||||||
|
.help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
|
||||||
|
const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
|
||||||
|
.help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||||
|
|
||||||
const_eval_unreachable = entering unreachable code
|
const_eval_unreachable = entering unreachable code
|
||||||
const_eval_unreachable_unwind =
|
const_eval_unreachable_unwind =
|
||||||
unwinding past a stack frame that does not allow unwinding
|
unwinding past a stack frame that does not allow unwinding
|
||||||
|
|
||||||
const_eval_unsized_local = unsized locals are not supported
|
const_eval_unsized_local = unsized locals are not supported
|
||||||
const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
|
const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
|
||||||
|
const_eval_unstable_in_stable_exposed =
|
||||||
|
const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]`
|
||||||
|
.is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
.unstable_sugg = if the {$is_function_call2 ->
|
||||||
|
[true] caller
|
||||||
|
*[false] function
|
||||||
|
} is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
.bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
||||||
const_eval_unstable_in_stable =
|
const_eval_unstable_intrinsic = `{$name}` is not yet stable as a const intrinsic
|
||||||
const-stable function cannot use `#[feature({$gate})]`
|
.help = add `#![feature({$feature})]` to the crate attributes to enable
|
||||||
.unstable_sugg = if the function is not (yet) meant to be stable, make this function unstably const
|
|
||||||
.bypass_sugg = otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
|
|
||||||
|
|
||||||
const_eval_unterminated_c_string =
|
const_eval_unterminated_c_string =
|
||||||
reading a null-terminated string starting at {$pointer} with no null found before end of allocation
|
reading a null-terminated string starting at {$pointer} with no null found before end of allocation
|
||||||
|
@ -5,6 +5,7 @@ use std::borrow::Cow;
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use rustc_attr::{ConstStability, StabilityLevel};
|
||||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{self as hir, LangItem};
|
use rustc_hir::{self as hir, LangItem};
|
||||||
@ -28,8 +29,8 @@ use super::ops::{self, NonConstOp, Status};
|
|||||||
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
|
||||||
use super::resolver::FlowSensitiveAnalysis;
|
use super::resolver::FlowSensitiveAnalysis;
|
||||||
use super::{ConstCx, Qualif};
|
use super::{ConstCx, Qualif};
|
||||||
use crate::const_eval::is_unstable_const_fn;
|
use crate::check_consts::is_safe_to_expose_on_stable_const_fn;
|
||||||
use crate::errors::UnstableInStable;
|
use crate::errors;
|
||||||
|
|
||||||
type QualifResults<'mir, 'tcx, Q> =
|
type QualifResults<'mir, 'tcx, Q> =
|
||||||
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
|
||||||
@ -274,19 +275,22 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||||||
/// context.
|
/// context.
|
||||||
pub fn check_op_spanned<O: NonConstOp<'tcx>>(&mut self, op: O, span: Span) {
|
pub fn check_op_spanned<O: NonConstOp<'tcx>>(&mut self, op: O, span: Span) {
|
||||||
let gate = match op.status_in_item(self.ccx) {
|
let gate = match op.status_in_item(self.ccx) {
|
||||||
Status::Allowed => return,
|
Status::Unstable { gate, safe_to_expose_on_stable, is_function_call }
|
||||||
|
if self.tcx.features().enabled(gate) =>
|
||||||
Status::Unstable(gate) if self.tcx.features().enabled(gate) => {
|
{
|
||||||
let unstable_in_stable = self.ccx.is_const_stable_const_fn()
|
// Generally this is allowed since the feature gate is enabled -- except
|
||||||
&& !super::rustc_allow_const_fn_unstable(self.tcx, self.def_id(), gate);
|
// if this function wants to be safe-to-expose-on-stable.
|
||||||
if unstable_in_stable {
|
if !safe_to_expose_on_stable
|
||||||
emit_unstable_in_stable_error(self.ccx, span, gate);
|
&& self.enforce_recursive_const_stability()
|
||||||
|
&& !super::rustc_allow_const_fn_unstable(self.tcx, self.def_id(), gate)
|
||||||
|
{
|
||||||
|
emit_unstable_in_stable_exposed_error(self.ccx, span, gate, is_function_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status::Unstable(gate) => Some(gate),
|
Status::Unstable { gate, .. } => Some(gate),
|
||||||
Status::Forbidden => None,
|
Status::Forbidden => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -304,7 +308,13 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
|
|||||||
self.error_emitted = Some(reported);
|
self.error_emitted = Some(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
ops::DiagImportance::Secondary => self.secondary_errors.push(err),
|
ops::DiagImportance::Secondary => {
|
||||||
|
self.secondary_errors.push(err);
|
||||||
|
self.tcx.dcx().span_delayed_bug(
|
||||||
|
span,
|
||||||
|
"compilation must fail when there is a secondary const checker error",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,6 +579,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
|
|
||||||
ty::FnPtr(..) => {
|
ty::FnPtr(..) => {
|
||||||
self.check_op(ops::FnCallIndirect);
|
self.check_op(ops::FnCallIndirect);
|
||||||
|
// We can get here without an error in miri-unleashed mode... might as well
|
||||||
|
// skip the rest of the checks as well then.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -612,6 +624,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
// checks.
|
// checks.
|
||||||
// FIXME(effects) we might consider moving const stability checks to typeck as well.
|
// FIXME(effects) we might consider moving const stability checks to typeck as well.
|
||||||
if tcx.features().effects() {
|
if tcx.features().effects() {
|
||||||
|
// This skips the check below that ensures we only call `const fn`.
|
||||||
is_trait = true;
|
is_trait = true;
|
||||||
|
|
||||||
if let Ok(Some(instance)) =
|
if let Ok(Some(instance)) =
|
||||||
@ -637,6 +650,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
sym::const_trait_impl
|
sym::const_trait_impl
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
// If we allowed this, we're in miri-unleashed mode, so we might
|
||||||
|
// as well skip the remaining checks.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -650,28 +665,72 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
// const-eval of the `begin_panic` fn assumes the argument is `&str`
|
// const-eval of the `begin_panic` fn assumes the argument is `&str`
|
||||||
if tcx.is_lang_item(callee, LangItem::BeginPanic) {
|
if tcx.is_lang_item(callee, LangItem::BeginPanic) {
|
||||||
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
|
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
|
||||||
ty::Ref(_, ty, _) if ty.is_str() => return,
|
ty::Ref(_, ty, _) if ty.is_str() => {}
|
||||||
_ => self.check_op(ops::PanicNonStr),
|
_ => self.check_op(ops::PanicNonStr),
|
||||||
}
|
}
|
||||||
|
// Allow this call, skip all the checks below.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
|
// const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
|
||||||
if tcx.has_attr(callee, sym::rustc_const_panic_str) {
|
if tcx.has_attr(callee, sym::rustc_const_panic_str) {
|
||||||
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
|
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
|
||||||
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
|
ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
|
||||||
{
|
{}
|
||||||
return;
|
_ => {
|
||||||
|
self.check_op(ops::PanicNonStr);
|
||||||
}
|
}
|
||||||
_ => self.check_op(ops::PanicNonStr),
|
|
||||||
}
|
}
|
||||||
|
// Allow this call, skip all the checks below.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can be called on stable via the `vec!` macro.
|
// This can be called on stable via the `vec!` macro.
|
||||||
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
|
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
|
||||||
self.check_op(ops::HeapAllocation);
|
self.check_op(ops::HeapAllocation);
|
||||||
|
// Allow this call, skip all the checks below.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Intrinsics are language primitives, not regular calls, so treat them separately.
|
||||||
|
if let Some(intrinsic) = tcx.intrinsic(callee) {
|
||||||
|
match tcx.lookup_const_stability(callee) {
|
||||||
|
None => {
|
||||||
|
// Non-const intrinsic.
|
||||||
|
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||||
|
}
|
||||||
|
Some(ConstStability { feature: None, const_stable_indirect, .. }) => {
|
||||||
|
// Intrinsic does not need a separate feature gate (we rely on the
|
||||||
|
// regular stability checker). However, we have to worry about recursive
|
||||||
|
// const stability.
|
||||||
|
if !const_stable_indirect && self.enforce_recursive_const_stability() {
|
||||||
|
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
||||||
|
span: self.span,
|
||||||
|
def_path: self.tcx.def_path_str(callee),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(ConstStability {
|
||||||
|
feature: Some(feature),
|
||||||
|
level: StabilityLevel::Unstable { .. },
|
||||||
|
const_stable_indirect,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
self.check_op(ops::IntrinsicUnstable {
|
||||||
|
name: intrinsic.name,
|
||||||
|
feature,
|
||||||
|
const_stable_indirect,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||||
|
// All good.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This completes the checks for intrinsics.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trait functions are not `const fn` so we have to skip them here.
|
||||||
if !tcx.is_const_fn_raw(callee) && !is_trait {
|
if !tcx.is_const_fn_raw(callee) && !is_trait {
|
||||||
self.check_op(ops::FnCallNonConst {
|
self.check_op(ops::FnCallNonConst {
|
||||||
caller,
|
caller,
|
||||||
@ -681,66 +740,68 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
call_source,
|
call_source,
|
||||||
feature: None,
|
feature: None,
|
||||||
});
|
});
|
||||||
|
// If we allowed this, we're in miri-unleashed mode, so we might
|
||||||
|
// as well skip the remaining checks.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the `const fn` we are trying to call is not const-stable, ensure that we have
|
// Finally, stability for regular function calls -- this is the big one.
|
||||||
// the proper feature gate enabled.
|
match tcx.lookup_const_stability(callee) {
|
||||||
if let Some((gate, implied_by)) = is_unstable_const_fn(tcx, callee) {
|
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||||
trace!(?gate, "calling unstable const fn");
|
// All good.
|
||||||
if self.span.allows_unstable(gate) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if let Some(implied_by_gate) = implied_by
|
None | Some(ConstStability { feature: None, .. }) => {
|
||||||
&& self.span.allows_unstable(implied_by_gate)
|
// This doesn't need a separate const-stability check -- const-stability equals
|
||||||
{
|
// regular stability, and regular stability is checked separately.
|
||||||
return;
|
// However, we *do* have to worry about *recursive* const stability.
|
||||||
|
if self.enforce_recursive_const_stability()
|
||||||
|
&& !is_safe_to_expose_on_stable_const_fn(tcx, callee)
|
||||||
|
{
|
||||||
|
self.dcx().emit_err(errors::UnmarkedConstFnExposed {
|
||||||
|
span: self.span,
|
||||||
|
def_path: self.tcx.def_path_str(callee),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Some(ConstStability {
|
||||||
|
feature: Some(feature),
|
||||||
|
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// An unstable const fn with a feature gate.
|
||||||
|
let callee_safe_to_expose_on_stable =
|
||||||
|
is_safe_to_expose_on_stable_const_fn(tcx, callee);
|
||||||
|
|
||||||
// Calling an unstable function *always* requires that the corresponding gate
|
// We only honor `span.allows_unstable` aka `#[allow_internal_unstable]` if
|
||||||
// (or implied gate) be enabled, even if the function has
|
// the callee is safe to expose, to avoid bypassing recursive stability.
|
||||||
// `#[rustc_allow_const_fn_unstable(the_gate)]`.
|
if (self.span.allows_unstable(feature)
|
||||||
let gate_enabled = |gate| tcx.features().enabled(gate);
|
|| implied_feature.is_some_and(|f| self.span.allows_unstable(f)))
|
||||||
let feature_gate_enabled = gate_enabled(gate);
|
&& callee_safe_to_expose_on_stable
|
||||||
let implied_gate_enabled = implied_by.is_some_and(gate_enabled);
|
{
|
||||||
if !feature_gate_enabled && !implied_gate_enabled {
|
return;
|
||||||
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
|
// We can't use `check_op` to check whether the feature is enabled because
|
||||||
// stable `const fn`, that is all that is required.
|
// the logic is a bit different than elsewhere: local functions don't need
|
||||||
if !self.ccx.is_const_stable_const_fn() {
|
// the feature gate, and there might be an "implied" gate that also suffices
|
||||||
trace!("crate not using stability attributes or caller not stably const");
|
// to allow this.
|
||||||
return;
|
let feature_enabled = callee.is_local()
|
||||||
}
|
|| tcx.features().enabled(feature)
|
||||||
|
|| implied_feature.is_some_and(|f| tcx.features().enabled(f));
|
||||||
// Otherwise, we are something const-stable calling a const-unstable fn.
|
// We do *not* honor this if we are in the "danger zone": we have to enforce
|
||||||
if super::rustc_allow_const_fn_unstable(tcx, caller, gate) {
|
// recursive const-stability and the callee is not safe-to-expose. In that
|
||||||
trace!("rustc_allow_const_fn_unstable gate enabled");
|
// case we need `check_op` to do the check.
|
||||||
return;
|
let danger_zone = !callee_safe_to_expose_on_stable
|
||||||
}
|
&& self.enforce_recursive_const_stability();
|
||||||
|
if danger_zone || !feature_enabled {
|
||||||
self.check_op(ops::FnCallUnstable(callee, Some(gate)));
|
self.check_op(ops::FnCallUnstable {
|
||||||
return;
|
def_id: callee,
|
||||||
}
|
feature,
|
||||||
|
safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
|
||||||
// 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).is_some_and(|s| s.is_unstable());
|
|
||||||
if callee_is_unstable_unmarked {
|
|
||||||
trace!("callee_is_unstable_unmarked");
|
|
||||||
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
|
|
||||||
// `extern` functions, and these have no way to get marked `const`. So instead we
|
|
||||||
// use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
|
|
||||||
if self.ccx.is_const_stable_const_fn() || tcx.intrinsic(callee).is_some() {
|
|
||||||
self.check_op(ops::FnCallUnstable(callee, None));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace!("permitting call");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forbid all `Drop` terminators unless the place being dropped is a local with no
|
// Forbid all `Drop` terminators unless the place being dropped is a local with no
|
||||||
@ -785,11 +846,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
|
|
||||||
TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
|
TerminatorKind::InlineAsm { .. } => self.check_op(ops::InlineAsm),
|
||||||
|
|
||||||
TerminatorKind::Yield { .. } => self.check_op(ops::Coroutine(
|
TerminatorKind::Yield { .. } => {
|
||||||
self.tcx
|
self.check_op(ops::Coroutine(
|
||||||
.coroutine_kind(self.body.source.def_id())
|
self.tcx
|
||||||
.expect("Only expected to have a yield in a coroutine"),
|
.coroutine_kind(self.body.source.def_id())
|
||||||
)),
|
.expect("Only expected to have a yield in a coroutine"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
TerminatorKind::CoroutineDrop => {
|
TerminatorKind::CoroutineDrop => {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
@ -819,8 +882,19 @@ fn is_int_bool_float_or_char(ty: Ty<'_>) -> bool {
|
|||||||
ty.is_bool() || ty.is_integral() || ty.is_char() || ty.is_floating_point()
|
ty.is_bool() || ty.is_integral() || ty.is_char() || ty.is_floating_point()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_unstable_in_stable_error(ccx: &ConstCx<'_, '_>, span: Span, gate: Symbol) {
|
fn emit_unstable_in_stable_exposed_error(
|
||||||
|
ccx: &ConstCx<'_, '_>,
|
||||||
|
span: Span,
|
||||||
|
gate: Symbol,
|
||||||
|
is_function_call: bool,
|
||||||
|
) -> ErrorGuaranteed {
|
||||||
let attr_span = ccx.tcx.def_span(ccx.def_id()).shrink_to_lo();
|
let attr_span = ccx.tcx.def_span(ccx.def_id()).shrink_to_lo();
|
||||||
|
|
||||||
ccx.dcx().emit_err(UnstableInStable { gate: gate.to_string(), span, attr_span });
|
ccx.dcx().emit_err(errors::UnstableInStableExposed {
|
||||||
|
gate: gate.to_string(),
|
||||||
|
span,
|
||||||
|
attr_span,
|
||||||
|
is_function_call,
|
||||||
|
is_function_call2: is_function_call,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,12 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
|
|||||||
self.const_kind.expect("`const_kind` must not be called on a non-const fn")
|
self.const_kind.expect("`const_kind` must not be called on a non-const fn")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const_stable_const_fn(&self) -> bool {
|
pub fn enforce_recursive_const_stability(&self) -> bool {
|
||||||
|
// We can skip this if `staged_api` is not enabled, since in such crates
|
||||||
|
// `lookup_const_stability` will always be `None`.
|
||||||
self.const_kind == Some(hir::ConstContext::ConstFn)
|
self.const_kind == Some(hir::ConstContext::ConstFn)
|
||||||
&& self.tcx.features().staged_api()
|
&& self.tcx.features().staged_api()
|
||||||
&& is_const_stable_const_fn(self.tcx, self.def_id().to_def_id())
|
&& is_safe_to_expose_on_stable_const_fn(self.tcx, self.def_id().to_def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_async(&self) -> bool {
|
fn is_async(&self) -> bool {
|
||||||
@ -90,50 +92,38 @@ pub fn rustc_allow_const_fn_unstable(
|
|||||||
attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate)
|
attr::rustc_allow_const_fn_unstable(tcx.sess, attrs).any(|name| name == feature_gate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the given `const fn` is "const-stable".
|
/// Returns `true` if the given `const fn` is "safe to expose on stable".
|
||||||
///
|
///
|
||||||
/// Panics if the given `DefId` does not refer to a `const fn`.
|
/// 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"
|
/// This is relevant within a `staged_api` crate. Unlike with normal features, the use of unstable
|
||||||
/// functions can be called in a const-context by users of the stable compiler. "const-stable"
|
/// const features *recursively* taints the functions that use them. This is to avoid accidentally
|
||||||
/// functions are subject to more stringent restrictions than "const-unstable" functions: They
|
/// exposing e.g. the implementation of an unstable const intrinsic on stable. So we partition the
|
||||||
/// cannot use unstable features and can only call other "const-stable" functions.
|
/// world into two functions: those that are safe to expose on stable (and hence may not use
|
||||||
pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
/// unstable features, not even recursively), and those that are not.
|
||||||
// A default body in a `#[const_trait]` is not const-stable because const
|
pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
// trait fns currently cannot be const-stable. We shouldn't
|
// A default body in a `#[const_trait]` is not const-stable because const trait fns currently
|
||||||
// restrict default bodies to only call const-stable functions.
|
// cannot be const-stable. These functions can't be called from anything stable, so we shouldn't
|
||||||
|
// restrict them to only call const-stable functions.
|
||||||
if tcx.is_const_default_method(def_id) {
|
if tcx.is_const_default_method(def_id) {
|
||||||
|
// FIXME(const_trait_impl): we have to eventually allow some of these if these things can ever be stable.
|
||||||
|
// They should probably behave like regular `const fn` for that...
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Const-stability is only relevant for `const fn`.
|
// Const-stability is only relevant for `const fn`.
|
||||||
assert!(tcx.is_const_fn_raw(def_id));
|
assert!(tcx.is_const_fn_raw(def_id));
|
||||||
|
|
||||||
// A function is only const-stable if it has `#[rustc_const_stable]` or it the trait it belongs
|
|
||||||
// to is const-stable.
|
|
||||||
match tcx.lookup_const_stability(def_id) {
|
match tcx.lookup_const_stability(def_id) {
|
||||||
Some(stab) => stab.is_const_stable(),
|
None => {
|
||||||
None if is_parent_const_stable_trait(tcx, def_id) => {
|
// Only marked functions can be trusted. Note that this may be a function in a
|
||||||
// Remove this when `#![feature(const_trait_impl)]` is stabilized,
|
// non-staged-API crate where no recursive checks were done!
|
||||||
// returning `true` unconditionally.
|
false
|
||||||
tcx.dcx().span_delayed_bug(
|
}
|
||||||
tcx.def_span(def_id),
|
Some(stab) => {
|
||||||
"trait implementations cannot be const stable yet",
|
// We consider things safe-to-expose if they are stable, if they don't have any explicit
|
||||||
);
|
// const stability attribute, or if they are marked as `const_stable_indirect`.
|
||||||
true
|
stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect
|
||||||
}
|
}
|
||||||
None => false, // By default, items are not const stable.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|
||||||
let local_def_id = def_id.expect_local();
|
|
||||||
let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
|
|
||||||
|
|
||||||
let parent_owner_id = tcx.parent_hir_id(hir_id).owner;
|
|
||||||
if !tcx.is_const_trait_impl_raw(parent_owner_id.to_def_id()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
tcx.lookup_const_stability(parent_owner_id).is_some_and(|stab| stab.is_const_stable())
|
|
||||||
}
|
|
||||||
|
@ -26,8 +26,16 @@ use crate::{errors, fluent_generated};
|
|||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
Allowed,
|
Unstable {
|
||||||
Unstable(Symbol),
|
/// The feature that must be enabled to use this operation.
|
||||||
|
gate: Symbol,
|
||||||
|
/// Whether it is allowed to use this operation from stable `const fn`.
|
||||||
|
/// This will usually be `false`.
|
||||||
|
safe_to_expose_on_stable: bool,
|
||||||
|
/// We indicate whether this is a function call, since we can use targeted
|
||||||
|
/// diagnostics for "callee is not safe to expose om stable".
|
||||||
|
is_function_call: bool,
|
||||||
|
},
|
||||||
Forbidden,
|
Forbidden,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,9 +48,9 @@ pub enum DiagImportance {
|
|||||||
Secondary,
|
Secondary,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An operation that is not *always* allowed in a const context.
|
/// An operation that is *not allowed* in a const context.
|
||||||
pub trait NonConstOp<'tcx>: std::fmt::Debug {
|
pub trait NonConstOp<'tcx>: std::fmt::Debug {
|
||||||
/// Returns an enum indicating whether this operation is allowed within the given item.
|
/// Returns an enum indicating whether this operation can be enabled with a feature gate.
|
||||||
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
||||||
Status::Forbidden
|
Status::Forbidden
|
||||||
}
|
}
|
||||||
@ -298,30 +306,78 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||||||
///
|
///
|
||||||
/// Contains the name of the feature that would allow the use of this function.
|
/// Contains the name of the feature that would allow the use of this function.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct FnCallUnstable(pub DefId, pub Option<Symbol>);
|
pub(crate) struct FnCallUnstable {
|
||||||
|
pub def_id: DefId,
|
||||||
|
pub feature: Symbol,
|
||||||
|
pub safe_to_expose_on_stable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
|
||||||
|
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
||||||
|
Status::Unstable {
|
||||||
|
gate: self.feature,
|
||||||
|
safe_to_expose_on_stable: self.safe_to_expose_on_stable,
|
||||||
|
is_function_call: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
let FnCallUnstable(def_id, feature) = *self;
|
let mut err = ccx.dcx().create_err(errors::UnstableConstFn {
|
||||||
|
span,
|
||||||
let mut err = ccx
|
def_path: ccx.tcx.def_path_str(self.def_id),
|
||||||
.dcx()
|
});
|
||||||
.create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
|
|
||||||
|
|
||||||
// FIXME: make this translatable
|
// FIXME: make this translatable
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
if ccx.is_const_stable_const_fn() {
|
err.help(format!("add `#![feature({})]` to the crate attributes to enable", self.feature));
|
||||||
err.help(fluent_generated::const_eval_const_stable);
|
|
||||||
} else if ccx.tcx.sess.is_nightly_build() {
|
|
||||||
if let Some(feature) = feature {
|
|
||||||
err.help(format!("add `#![feature({feature})]` to the crate attributes to enable"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err
|
err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A call to an intrinsic that is just not const-callable at all.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct IntrinsicNonConst {
|
||||||
|
pub name: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
|
||||||
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
|
ccx.dcx().create_err(errors::NonConstIntrinsic {
|
||||||
|
span,
|
||||||
|
name: self.name,
|
||||||
|
kind: ccx.const_kind(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A call to an intrinsic that is just not const-callable at all.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct IntrinsicUnstable {
|
||||||
|
pub name: Symbol,
|
||||||
|
pub feature: Symbol,
|
||||||
|
pub const_stable_indirect: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
|
||||||
|
fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
|
||||||
|
Status::Unstable {
|
||||||
|
gate: self.feature,
|
||||||
|
safe_to_expose_on_stable: self.const_stable_indirect,
|
||||||
|
// We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`,
|
||||||
|
// that's not a trivial change!
|
||||||
|
is_function_call: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
|
||||||
|
ccx.dcx().create_err(errors::UnstableIntrinsic {
|
||||||
|
span,
|
||||||
|
name: self.name,
|
||||||
|
feature: self.feature,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Coroutine(pub hir::CoroutineKind);
|
pub(crate) struct Coroutine(pub hir::CoroutineKind);
|
||||||
impl<'tcx> NonConstOp<'tcx> for Coroutine {
|
impl<'tcx> NonConstOp<'tcx> for Coroutine {
|
||||||
@ -331,7 +387,11 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
|
|||||||
hir::CoroutineSource::Block,
|
hir::CoroutineSource::Block,
|
||||||
) = self.0
|
) = self.0
|
||||||
{
|
{
|
||||||
Status::Unstable(sym::const_async_blocks)
|
Status::Unstable {
|
||||||
|
gate: sym::const_async_blocks,
|
||||||
|
safe_to_expose_on_stable: false,
|
||||||
|
is_function_call: false,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Status::Forbidden
|
Status::Forbidden
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ use crate::check_consts::rustc_allow_const_fn_unstable;
|
|||||||
/// elaboration.
|
/// elaboration.
|
||||||
pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
|
pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
|
||||||
// Const-stable functions must always use the stable live drop checker...
|
// Const-stable functions must always use the stable live drop checker...
|
||||||
if ccx.is_const_stable_const_fn() {
|
if ccx.enforce_recursive_const_stability() {
|
||||||
// ...except if they have the feature flag set via `rustc_allow_const_fn_unstable`.
|
// ...except if they have the feature flag set via `rustc_allow_const_fn_unstable`.
|
||||||
return rustc_allow_const_fn_unstable(
|
return rustc_allow_const_fn_unstable(
|
||||||
ccx.tcx,
|
ccx.tcx,
|
||||||
|
@ -1,25 +1,8 @@
|
|||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::symbol::Symbol;
|
|
||||||
use {rustc_attr as attr, rustc_hir as hir};
|
|
||||||
|
|
||||||
/// Whether the `def_id` is an unstable const fn and what feature gate(s) are necessary to enable
|
|
||||||
/// it.
|
|
||||||
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<(Symbol, Option<Symbol>)> {
|
|
||||||
if tcx.is_const_fn_raw(def_id) {
|
|
||||||
let const_stab = tcx.lookup_const_stability(def_id)?;
|
|
||||||
match const_stab.level {
|
|
||||||
attr::StabilityLevel::Unstable { implied_by, .. } => {
|
|
||||||
Some((const_stab.feature, implied_by))
|
|
||||||
}
|
|
||||||
attr::StabilityLevel::Stable { .. } => None,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
let parent_id = tcx.local_parent(def_id);
|
let parent_id = tcx.local_parent(def_id);
|
||||||
|
@ -219,7 +219,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// "Intercept" a function call, because we have something special to do for it.
|
/// "Intercept" a function call, because we have something special to do for it.
|
||||||
/// All `#[rustc_do_not_const_check]` functions should be hooked here.
|
/// All `#[rustc_do_not_const_check]` functions MUST be hooked here.
|
||||||
/// If this returns `Some` function, which may be `instance` or a different function with
|
/// If this returns `Some` function, which may be `instance` or a different function with
|
||||||
/// compatible arguments, then evaluation should continue with that function.
|
/// compatible arguments, then evaluation should continue with that function.
|
||||||
/// If this returns `None`, the function call has been handled and the function has returned.
|
/// If this returns `None`, the function call has been handled and the function has returned.
|
||||||
|
@ -14,7 +14,7 @@ use rustc_middle::mir::interpret::{
|
|||||||
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
|
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, Mutability, Ty};
|
use rustc_middle::ty::{self, Mutability, Ty};
|
||||||
use rustc_span::Span;
|
use rustc_span::{Span, Symbol};
|
||||||
use rustc_target::abi::WrappingRange;
|
use rustc_target::abi::WrappingRange;
|
||||||
use rustc_target::abi::call::AdjustForForeignAbiError;
|
use rustc_target::abi::call::AdjustForForeignAbiError;
|
||||||
|
|
||||||
@ -44,11 +44,15 @@ pub(crate) struct MutablePtrInFinal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_unstable_in_stable)]
|
#[diag(const_eval_unstable_in_stable_exposed)]
|
||||||
pub(crate) struct UnstableInStable {
|
pub(crate) struct UnstableInStableExposed {
|
||||||
pub gate: String,
|
pub gate: String,
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
#[help(const_eval_is_function_call)]
|
||||||
|
pub is_function_call: bool,
|
||||||
|
/// Need to duplicate the field so that fluent also provides it as a variable...
|
||||||
|
pub is_function_call2: bool,
|
||||||
#[suggestion(
|
#[suggestion(
|
||||||
const_eval_unstable_sugg,
|
const_eval_unstable_sugg,
|
||||||
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
|
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
|
||||||
@ -117,6 +121,34 @@ pub(crate) struct UnstableConstFn {
|
|||||||
pub def_path: String,
|
pub def_path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(const_eval_unstable_intrinsic)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct UnstableIntrinsic {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Symbol,
|
||||||
|
pub feature: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(const_eval_unmarked_const_fn_exposed)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct UnmarkedConstFnExposed {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub def_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(const_eval_unmarked_intrinsic_exposed)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct UnmarkedIntrinsicExposed {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub def_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
|
#[diag(const_eval_mutable_ref_escaping, code = E0764)]
|
||||||
pub(crate) struct MutableRefEscaping {
|
pub(crate) struct MutableRefEscaping {
|
||||||
@ -153,6 +185,15 @@ pub(crate) struct NonConstFnCall {
|
|||||||
pub kind: ConstContext,
|
pub kind: ConstContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(const_eval_non_const_intrinsic)]
|
||||||
|
pub(crate) struct NonConstIntrinsic {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Symbol,
|
||||||
|
pub kind: ConstContext,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(const_eval_unallowed_op_in_const_context)]
|
#[diag(const_eval_unallowed_op_in_const_context)]
|
||||||
pub(crate) struct UnallowedOpInConstContext {
|
pub(crate) struct UnallowedOpInConstContext {
|
||||||
|
@ -866,7 +866,9 @@ impl SyntaxExtension {
|
|||||||
})
|
})
|
||||||
.unwrap_or_else(|| (None, helper_attrs));
|
.unwrap_or_else(|| (None, helper_attrs));
|
||||||
let stability = attr::find_stability(sess, attrs, span);
|
let stability = attr::find_stability(sess, attrs, span);
|
||||||
let const_stability = attr::find_const_stability(sess, attrs, span);
|
// We set `is_const_fn` false to avoid getting any implicit const stability.
|
||||||
|
let const_stability =
|
||||||
|
attr::find_const_stability(sess, attrs, span, /* is_const_fn */ false);
|
||||||
let body_stability = attr::find_body_stability(sess, attrs);
|
let body_stability = attr::find_body_stability(sess, attrs);
|
||||||
if let Some((_, sp)) = const_stability {
|
if let Some((_, sp)) = const_stability {
|
||||||
sess.dcx().emit_err(errors::MacroConstStability {
|
sess.dcx().emit_err(errors::MacroConstStability {
|
||||||
|
@ -617,11 +617,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||||||
DuplicatesOk, EncodeCrossCrate::Yes,
|
DuplicatesOk, EncodeCrossCrate::Yes,
|
||||||
"allow_internal_unstable side-steps feature gating and stability checks",
|
"allow_internal_unstable side-steps feature gating and stability checks",
|
||||||
),
|
),
|
||||||
gated!(
|
|
||||||
rustc_allow_const_fn_unstable, Normal,
|
|
||||||
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
|
|
||||||
"rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
|
|
||||||
),
|
|
||||||
gated!(
|
gated!(
|
||||||
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
|
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
|
||||||
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
|
EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
|
||||||
@ -838,6 +833,15 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||||||
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
|
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
|
||||||
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_const_stable_indirect, Normal,
|
||||||
|
template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
|
||||||
|
),
|
||||||
|
gated!(
|
||||||
|
rustc_allow_const_fn_unstable, Normal,
|
||||||
|
template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
|
||||||
|
"rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes, Layout related:
|
// Internal attributes, Layout related:
|
||||||
|
@ -3128,7 +3128,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
Some(stability) if stability.is_const_unstable() => {
|
Some(stability) if stability.is_const_unstable() => {
|
||||||
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
||||||
// corresponding feature gate.
|
// corresponding feature gate.
|
||||||
self.features().enabled(stability.feature)
|
stability.feature.is_some_and(|f| self.features().enabled(f))
|
||||||
}
|
}
|
||||||
// functions without const stability are either stable user written
|
// functions without const stability are either stable user written
|
||||||
// const fn or the user is using feature gates and we thus don't
|
// const fn or the user is using feature gates and we thus don't
|
||||||
|
@ -99,6 +99,10 @@ passes_collapse_debuginfo =
|
|||||||
passes_confusables = attribute should be applied to an inherent method
|
passes_confusables = attribute should be applied to an inherent method
|
||||||
.label = not an inherent method
|
.label = not an inherent method
|
||||||
|
|
||||||
|
passes_const_stable_not_stable =
|
||||||
|
attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
|
||||||
|
.label = attribute specified here
|
||||||
|
|
||||||
passes_continue_labeled_block =
|
passes_continue_labeled_block =
|
||||||
`continue` pointing to a labeled block
|
`continue` pointing to a labeled block
|
||||||
.label = labeled blocks cannot be `continue`'d
|
.label = labeled blocks cannot be `continue`'d
|
||||||
@ -465,10 +469,10 @@ passes_may_dangle =
|
|||||||
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
`#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl
|
||||||
|
|
||||||
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
|
passes_maybe_string_interpolation = you might have meant to use string interpolation in this string literal
|
||||||
|
|
||||||
passes_missing_const_err =
|
passes_missing_const_err =
|
||||||
attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
.help = make the function or method const
|
.help = make the function or method const
|
||||||
.label = attribute specified here
|
|
||||||
|
|
||||||
passes_missing_const_stab_attr =
|
passes_missing_const_stab_attr =
|
||||||
{$descr} has missing const stability attribute
|
{$descr} has missing const stability attribute
|
||||||
|
@ -1574,12 +1574,20 @@ pub(crate) struct DuplicateFeatureErr {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub feature: Symbol,
|
pub feature: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_missing_const_err)]
|
#[diag(passes_missing_const_err)]
|
||||||
pub(crate) struct MissingConstErr {
|
pub(crate) struct MissingConstErr {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[help]
|
#[help]
|
||||||
pub fn_sig_span: Span,
|
pub fn_sig_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(passes_const_stable_not_stable)]
|
||||||
|
pub(crate) struct ConstStableNotStable {
|
||||||
|
#[primary_span]
|
||||||
|
pub fn_sig_span: Span,
|
||||||
#[label]
|
#[label]
|
||||||
pub const_span: Span,
|
pub const_span: Span,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
|
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
|
||||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
use rustc_hir::{Constness, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||||
use rustc_middle::hir::nested_filter;
|
use rustc_middle::hir::nested_filter;
|
||||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||||
@ -27,7 +27,6 @@ use rustc_session::lint;
|
|||||||
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
|
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::symbol::{Symbol, sym};
|
use rustc_span::symbol::{Symbol, sym};
|
||||||
use rustc_target::spec::abi::Abi;
|
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
@ -107,6 +106,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
|
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
|
||||||
|
is_foreign_item: bool,
|
||||||
kind: AnnotationKind,
|
kind: AnnotationKind,
|
||||||
inherit_deprecation: InheritDeprecation,
|
inherit_deprecation: InheritDeprecation,
|
||||||
inherit_const_stability: InheritConstStability,
|
inherit_const_stability: InheritConstStability,
|
||||||
@ -163,30 +163,62 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
|
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
|
||||||
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
|
let const_stab = attr::find_const_stability(
|
||||||
|
self.tcx.sess,
|
||||||
|
attrs,
|
||||||
|
item_sp,
|
||||||
|
fn_sig.is_some_and(|s| s.header.is_const()),
|
||||||
|
);
|
||||||
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
|
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
|
||||||
let mut const_span = None;
|
|
||||||
|
|
||||||
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
|
// If the current node is a function with const stability attributes (directly given or
|
||||||
self.index.const_stab_map.insert(def_id, const_stab);
|
// implied), check if the function/method is const or the parent impl block is const.
|
||||||
const_span = Some(const_span_node);
|
if let Some(fn_sig) = fn_sig
|
||||||
const_stab
|
|
||||||
});
|
|
||||||
|
|
||||||
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
|
|
||||||
// check if the function/method is const or the parent impl block is const
|
|
||||||
if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig)
|
|
||||||
&& fn_sig.header.abi != Abi::RustIntrinsic
|
|
||||||
&& !fn_sig.header.is_const()
|
&& !fn_sig.header.is_const()
|
||||||
|
// We have to exclude foreign items as they might be intrinsics. Sadly we can't check
|
||||||
|
// their ABI; `fn_sig.abi` is *not* correct for foreign functions.
|
||||||
|
&& !is_foreign_item
|
||||||
|
&& const_stab.is_some()
|
||||||
&& (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
|
&& (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id()))
|
||||||
|
{
|
||||||
|
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is marked const *stable*, it must also be regular-stable.
|
||||||
|
if let Some((const_stab, const_span)) = const_stab
|
||||||
|
&& let Some(fn_sig) = fn_sig
|
||||||
|
&& const_stab.is_const_stable()
|
||||||
|
&& !stab.is_some_and(|(s, _)| s.is_stable())
|
||||||
{
|
{
|
||||||
self.tcx
|
self.tcx
|
||||||
.dcx()
|
.dcx()
|
||||||
.emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
|
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stable *language* features shouldn't be used as unstable library features.
|
||||||
|
// (Not doing this for stable library features is checked by tidy.)
|
||||||
|
if let Some((
|
||||||
|
ConstStability { level: Unstable { .. }, feature: Some(feature), .. },
|
||||||
|
const_span,
|
||||||
|
)) = const_stab
|
||||||
|
{
|
||||||
|
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
||||||
|
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
|
||||||
|
span: const_span,
|
||||||
|
item_sp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let const_stab = const_stab.map(|(const_stab, _span)| {
|
||||||
|
self.index.const_stab_map.insert(def_id, const_stab);
|
||||||
|
const_stab
|
||||||
|
});
|
||||||
|
|
||||||
// `impl const Trait for Type` items forward their const stability to their
|
// `impl const Trait for Type` items forward their const stability to their
|
||||||
// immediate children.
|
// immediate children.
|
||||||
|
// FIXME(effects): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
|
||||||
|
// Currently, once that is set, we do not inherit anything from the parent any more.
|
||||||
if const_stab.is_none() {
|
if const_stab.is_none() {
|
||||||
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
||||||
if let Some(parent) = self.parent_const_stab {
|
if let Some(parent) = self.parent_const_stab {
|
||||||
@ -247,6 +279,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stable *language* features shouldn't be used as unstable library features.
|
||||||
|
// (Not doing this for stable library features is checked by tidy.)
|
||||||
if let Stability { level: Unstable { .. }, feature } = stab {
|
if let Stability { level: Unstable { .. }, feature } = stab {
|
||||||
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
||||||
self.tcx
|
self.tcx
|
||||||
@ -260,21 +294,13 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
self.index.implications.insert(implied_by, feature);
|
self.index.implications.insert(implied_by, feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab {
|
|
||||||
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
|
||||||
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
|
|
||||||
span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span
|
|
||||||
item_sp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(ConstStability {
|
if let Some(ConstStability {
|
||||||
level: Unstable { implied_by: Some(implied_by), .. },
|
level: Unstable { implied_by: Some(implied_by), .. },
|
||||||
feature,
|
feature,
|
||||||
..
|
..
|
||||||
}) = const_stab
|
}) = const_stab
|
||||||
{
|
{
|
||||||
self.index.implications.insert(implied_by, feature);
|
self.index.implications.insert(implied_by, feature.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.index.stab_map.insert(def_id, stab);
|
self.index.stab_map.insert(def_id, stab);
|
||||||
@ -372,6 +398,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
ctor_def_id,
|
ctor_def_id,
|
||||||
i.span,
|
i.span,
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -390,6 +417,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
i.owner_id.def_id,
|
i.owner_id.def_id,
|
||||||
i.span,
|
i.span,
|
||||||
fn_sig,
|
fn_sig,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
kind,
|
kind,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
const_stab_inherit,
|
const_stab_inherit,
|
||||||
@ -409,6 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
ti.owner_id.def_id,
|
ti.owner_id.def_id,
|
||||||
ti.span,
|
ti.span,
|
||||||
fn_sig,
|
fn_sig,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -432,6 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
ii.owner_id.def_id,
|
ii.owner_id.def_id,
|
||||||
ii.span,
|
ii.span,
|
||||||
fn_sig,
|
fn_sig,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
kind,
|
kind,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -447,6 +477,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
var.def_id,
|
var.def_id,
|
||||||
var.span,
|
var.span,
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -457,6 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
ctor_def_id,
|
ctor_def_id,
|
||||||
var.span,
|
var.span,
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -475,6 +507,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
s.def_id,
|
s.def_id,
|
||||||
s.span,
|
s.span,
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -486,10 +519,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
|
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
|
||||||
|
let fn_sig = match &i.kind {
|
||||||
|
rustc_hir::ForeignItemKind::Fn(fn_sig, ..) => Some(fn_sig),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
self.annotate(
|
self.annotate(
|
||||||
i.owner_id.def_id,
|
i.owner_id.def_id,
|
||||||
i.span,
|
i.span,
|
||||||
None,
|
fn_sig,
|
||||||
|
/* is_foreign_item */ true,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -512,6 +550,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||||||
p.def_id,
|
p.def_id,
|
||||||
p.span,
|
p.span,
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
kind,
|
kind,
|
||||||
InheritDeprecation::No,
|
InheritDeprecation::No,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -540,7 +579,9 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
|
fn check_missing_or_wrong_const_stability(&self, def_id: LocalDefId, span: Span) {
|
||||||
|
// The visitor runs for "unstable-if-unmarked" crates, but we don't yet support
|
||||||
|
// that on the const side.
|
||||||
if !self.tcx.features().staged_api() {
|
if !self.tcx.features().staged_api() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -553,11 +594,12 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|
let is_const = self.tcx.is_const_fn_raw(def_id.to_def_id())
|
||||||
|| self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
|
|| self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
|
||||||
let is_stable =
|
let is_stable =
|
||||||
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
|
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
|
||||||
let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();
|
let missing_const_stability_attribute =
|
||||||
|
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.feature.is_none());
|
||||||
|
|
||||||
if is_const && is_stable && missing_const_stability_attribute {
|
if is_const && is_stable && missing_const_stability_attribute {
|
||||||
let descr = self.tcx.def_descr(def_id.to_def_id());
|
let descr = self.tcx.def_descr(def_id.to_def_id());
|
||||||
@ -587,7 +629,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure stable `const fn` have a const stability attribute.
|
// Ensure stable `const fn` have a const stability attribute.
|
||||||
self.check_missing_const_stability(i.owner_id.def_id, i.span);
|
self.check_missing_or_wrong_const_stability(i.owner_id.def_id, i.span);
|
||||||
|
|
||||||
intravisit::walk_item(self, i)
|
intravisit::walk_item(self, i)
|
||||||
}
|
}
|
||||||
@ -601,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
|||||||
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
|
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
|
||||||
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
|
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
|
||||||
self.check_missing_stability(ii.owner_id.def_id, ii.span);
|
self.check_missing_stability(ii.owner_id.def_id, ii.span);
|
||||||
self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
|
self.check_missing_or_wrong_const_stability(ii.owner_id.def_id, ii.span);
|
||||||
}
|
}
|
||||||
intravisit::walk_impl_item(self, ii);
|
intravisit::walk_impl_item(self, ii);
|
||||||
}
|
}
|
||||||
@ -670,6 +712,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
|
|||||||
CRATE_DEF_ID,
|
CRATE_DEF_ID,
|
||||||
tcx.hir().span(CRATE_HIR_ID),
|
tcx.hir().span(CRATE_HIR_ID),
|
||||||
None,
|
None,
|
||||||
|
/* is_foreign_item */ false,
|
||||||
AnnotationKind::Required,
|
AnnotationKind::Required,
|
||||||
InheritDeprecation::Yes,
|
InheritDeprecation::Yes,
|
||||||
InheritConstStability::No,
|
InheritConstStability::No,
|
||||||
@ -732,12 +775,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||||||
// For implementations of traits, check the stability of each item
|
// For implementations of traits, check the stability of each item
|
||||||
// individually as it's possible to have a stable trait with unstable
|
// individually as it's possible to have a stable trait with unstable
|
||||||
// items.
|
// items.
|
||||||
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
hir::ItemKind::Impl(hir::Impl {
|
||||||
|
constness,
|
||||||
|
of_trait: Some(ref t),
|
||||||
|
self_ty,
|
||||||
|
items,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.staged_api() {
|
if features.staged_api() {
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||||
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
||||||
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
|
let const_stab = attr::find_const_stability(
|
||||||
|
self.tcx.sess,
|
||||||
|
attrs,
|
||||||
|
item.span,
|
||||||
|
matches!(constness, Constness::Const),
|
||||||
|
);
|
||||||
|
|
||||||
// If this impl block has an #[unstable] attribute, give an
|
// If this impl block has an #[unstable] attribute, give an
|
||||||
// error if all involved types and traits are stable, because
|
// error if all involved types and traits are stable, because
|
||||||
|
@ -1660,6 +1660,7 @@ symbols! {
|
|||||||
rustc_confusables,
|
rustc_confusables,
|
||||||
rustc_const_panic_str,
|
rustc_const_panic_str,
|
||||||
rustc_const_stable,
|
rustc_const_stable,
|
||||||
|
rustc_const_stable_indirect,
|
||||||
rustc_const_unstable,
|
rustc_const_unstable,
|
||||||
rustc_conversion_suggestion,
|
rustc_conversion_suggestion,
|
||||||
rustc_deallocator,
|
rustc_deallocator,
|
||||||
|
@ -103,7 +103,7 @@ impl<T> RawVec<T, Global> {
|
|||||||
/// `RawVec` with capacity `usize::MAX`. Useful for implementing
|
/// `RawVec` with capacity `usize::MAX`. Useful for implementing
|
||||||
/// delayed allocation.
|
/// delayed allocation.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self::new_in(Global)
|
Self::new_in(Global)
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||||||
/// Like `new`, but parameterized over the choice of allocator for
|
/// Like `new`, but parameterized over the choice of allocator for
|
||||||
/// the returned `RawVec`.
|
/// the returned `RawVec`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
|
||||||
pub const fn new_in(alloc: A) -> Self {
|
pub const fn new_in(alloc: A) -> Self {
|
||||||
Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
|
Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
|
||||||
}
|
}
|
||||||
@ -409,7 +409,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
|
|||||||
|
|
||||||
impl<A: Allocator> RawVecInner<A> {
|
impl<A: Allocator> RawVecInner<A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81"))]
|
||||||
const fn new_in(alloc: A, align: usize) -> Self {
|
const fn new_in(alloc: A, align: usize) -> Self {
|
||||||
let ptr = unsafe { core::mem::transmute(align) };
|
let ptr = unsafe { core::mem::transmute(align) };
|
||||||
// `cap: 0` means "unallocated". zero-sized types are ignored.
|
// `cap: 0` means "unallocated". zero-sized types are ignored.
|
||||||
|
@ -66,7 +66,6 @@ impl Layout {
|
|||||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||||
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
|
||||||
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
|
||||||
if Layout::is_size_align_valid(size, align) {
|
if Layout::is_size_align_valid(size, align) {
|
||||||
// SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
|
// SAFETY: Layout::is_size_align_valid checks the preconditions for this call.
|
||||||
@ -127,7 +126,6 @@ impl Layout {
|
|||||||
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
|
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
|
||||||
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
check_library_ub,
|
check_library_ub,
|
||||||
@ -159,7 +157,7 @@ impl Layout {
|
|||||||
#[must_use = "this returns the minimum alignment, \
|
#[must_use = "this returns the minimum alignment, \
|
||||||
without modifying the layout"]
|
without modifying the layout"]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(ptr_alignment_type)]
|
#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(ptr_alignment_type))]
|
||||||
pub const fn align(&self) -> usize {
|
pub const fn align(&self) -> usize {
|
||||||
self.align.as_usize()
|
self.align.as_usize()
|
||||||
}
|
}
|
||||||
|
@ -2287,6 +2287,7 @@ impl<T> SyncUnsafeCell<T> {
|
|||||||
|
|
||||||
/// Unwraps the value, consuming the cell.
|
/// Unwraps the value, consuming the cell.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "sync_unsafe_cell", issue = "95439")]
|
||||||
pub const fn into_inner(self) -> T {
|
pub const fn into_inner(self) -> T {
|
||||||
self.value.into_inner()
|
self.value.into_inner()
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||||||
/// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
|
/// assert_eq!(LazyCell::into_inner(lazy).ok(), Some("HELLO, WORLD!".to_string()));
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
|
#[unstable(feature = "lazy_cell_into_inner", issue = "125623")]
|
||||||
|
#[rustc_const_unstable(feature = "lazy_cell_into_inner", issue = "125623")]
|
||||||
pub const fn into_inner(this: Self) -> Result<T, F> {
|
pub const fn into_inner(this: Self) -> Result<T, F> {
|
||||||
match this.state.into_inner() {
|
match this.state.into_inner() {
|
||||||
State::Init(data) => Ok(data),
|
State::Init(data) => Ok(data),
|
||||||
|
@ -1770,7 +1770,7 @@ const fn len_utf16(code: u32) -> usize {
|
|||||||
/// Panics if the buffer is not large enough.
|
/// Panics if the buffer is not large enough.
|
||||||
/// A buffer of length four is large enough to encode any `char`.
|
/// A buffer of length four is large enough to encode any `char`.
|
||||||
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
|
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_char_encode_utf8", since = "1.83.0"))]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
|
@ -137,11 +137,11 @@ enum FromBytesWithNulErrorKind {
|
|||||||
|
|
||||||
// FIXME: const stability attributes should not be required here, I think
|
// FIXME: const stability attributes should not be required here, I think
|
||||||
impl FromBytesWithNulError {
|
impl FromBytesWithNulError {
|
||||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
|
||||||
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
|
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
|
||||||
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
|
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
|
||||||
}
|
}
|
||||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0"))]
|
||||||
const fn not_nul_terminated() -> FromBytesWithNulError {
|
const fn not_nul_terminated() -> FromBytesWithNulError {
|
||||||
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
|
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
|
||||||
}
|
}
|
||||||
@ -730,7 +730,7 @@ impl AsRef<CStr> for CStr {
|
|||||||
/// located within `isize::MAX` from `ptr`.
|
/// located within `isize::MAX` from `ptr`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "cstr_internals", issue = "none")]
|
#[unstable(feature = "cstr_internals", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
|
||||||
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const unsafe fn strlen(ptr: *const c_char) -> usize {
|
const unsafe fn strlen(ptr: *const c_char) -> usize {
|
||||||
const fn strlen_ct(s: *const c_char) -> usize {
|
const fn strlen_ct(s: *const c_char) -> usize {
|
||||||
|
@ -333,7 +333,10 @@ pub struct Arguments<'a> {
|
|||||||
#[unstable(feature = "fmt_internals", issue = "none")]
|
#[unstable(feature = "fmt_internals", issue = "none")]
|
||||||
impl<'a> Arguments<'a> {
|
impl<'a> Arguments<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")
|
||||||
|
)]
|
||||||
pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self {
|
pub const fn new_const<const N: usize>(pieces: &'a [&'static str; N]) -> Self {
|
||||||
const { assert!(N <= 1) };
|
const { assert!(N <= 1) };
|
||||||
Arguments { pieces, fmt: None, args: &[] }
|
Arguments { pieces, fmt: None, args: &[] }
|
||||||
@ -438,6 +441,7 @@ impl<'a> Arguments<'a> {
|
|||||||
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
|
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
pub const fn as_str(&self) -> Option<&'static str> {
|
pub const fn as_str(&self) -> Option<&'static str> {
|
||||||
match (self.pieces, self.args) {
|
match (self.pieces, self.args) {
|
||||||
([], []) => Some(""),
|
([], []) => Some(""),
|
||||||
|
@ -506,7 +506,7 @@ pub const fn black_box<T>(dummy: T) -> T {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "hint_must_use", issue = "94745")]
|
#[unstable(feature = "hint_must_use", issue = "94745")]
|
||||||
#[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "hint_must_use", issue = "94745"))]
|
||||||
#[must_use] // <-- :)
|
#[must_use] // <-- :)
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub const fn must_use<T>(value: T) -> T {
|
pub const fn must_use<T>(value: T) -> T {
|
||||||
|
@ -14,9 +14,10 @@
|
|||||||
//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
|
//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
|
||||||
//!
|
//!
|
||||||
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
|
//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
|
||||||
//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
|
//! `#[rustc_const_stable_indirect]` needs to be added to the intrinsic (`#[rustc_const_unstable]`
|
||||||
//! without T-lang consultation, because it bakes a feature into the language that cannot be
|
//! can be removed then). Such a change should not be done without T-lang consultation, because it
|
||||||
//! replicated in user code without compiler support.
|
//! may bake a feature into the language that cannot be replicated in user code without compiler
|
||||||
|
//! support.
|
||||||
//!
|
//!
|
||||||
//! # Volatiles
|
//! # Volatiles
|
||||||
//!
|
//!
|
||||||
@ -943,7 +944,11 @@ extern "rust-intrinsic" {
|
|||||||
/// reach code marked with this function.
|
/// reach code marked with this function.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`].
|
/// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`].
|
||||||
#[rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unreachable() -> !;
|
pub fn unreachable() -> !;
|
||||||
}
|
}
|
||||||
@ -958,7 +963,8 @@ extern "rust-intrinsic" {
|
|||||||
/// own, or if it does not enable any significant optimizations.
|
/// own, or if it does not enable any significant optimizations.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`].
|
/// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`].
|
||||||
#[rustc_const_stable(feature = "const_assume", since = "1.77.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
@ -980,7 +986,8 @@ pub const unsafe fn assume(b: bool) {
|
|||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
///
|
///
|
||||||
/// This intrinsic does not have a stable counterpart.
|
/// This intrinsic does not have a stable counterpart.
|
||||||
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_likely", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
@ -1000,7 +1007,8 @@ pub const fn likely(b: bool) -> bool {
|
|||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
///
|
///
|
||||||
/// This intrinsic does not have a stable counterpart.
|
/// This intrinsic does not have a stable counterpart.
|
||||||
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_likely", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
@ -1041,7 +1049,8 @@ extern "rust-intrinsic" {
|
|||||||
/// This will statically either panic, or do nothing.
|
/// This will statically either panic, or do nothing.
|
||||||
///
|
///
|
||||||
/// This intrinsic does not have a stable counterpart.
|
/// This intrinsic does not have a stable counterpart.
|
||||||
#[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn assert_inhabited<T>();
|
pub fn assert_inhabited<T>();
|
||||||
@ -1050,7 +1059,8 @@ extern "rust-intrinsic" {
|
|||||||
/// zero-initialization: This will statically either panic, or do nothing.
|
/// zero-initialization: This will statically either panic, or do nothing.
|
||||||
///
|
///
|
||||||
/// This intrinsic does not have a stable counterpart.
|
/// This intrinsic does not have a stable counterpart.
|
||||||
#[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn assert_zero_valid<T>();
|
pub fn assert_zero_valid<T>();
|
||||||
@ -1058,7 +1068,8 @@ extern "rust-intrinsic" {
|
|||||||
/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
|
/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
|
||||||
///
|
///
|
||||||
/// This intrinsic does not have a stable counterpart.
|
/// This intrinsic does not have a stable counterpart.
|
||||||
#[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn assert_mem_uninitialized_valid<T>();
|
pub fn assert_mem_uninitialized_valid<T>();
|
||||||
@ -1071,7 +1082,8 @@ extern "rust-intrinsic" {
|
|||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
///
|
///
|
||||||
/// Consider using [`core::panic::Location::caller`] instead.
|
/// Consider using [`core::panic::Location::caller`] instead.
|
||||||
#[rustc_const_stable(feature = "const_caller_location", since = "1.79.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn caller_location() -> &'static crate::panic::Location<'static>;
|
pub fn caller_location() -> &'static crate::panic::Location<'static>;
|
||||||
@ -1085,7 +1097,8 @@ extern "rust-intrinsic" {
|
|||||||
/// it does not require an `unsafe` block.
|
/// it does not require an `unsafe` block.
|
||||||
/// Therefore, implementations must not require the user to uphold
|
/// Therefore, implementations must not require the user to uphold
|
||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn forget<T: ?Sized>(_: T);
|
pub fn forget<T: ?Sized>(_: T);
|
||||||
@ -1391,7 +1404,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// This is not expected to ever be exposed directly to users, rather it
|
/// This is not expected to ever be exposed directly to users, rather it
|
||||||
/// may eventually be exposed through some more-constrained API.
|
/// may eventually be exposed through some more-constrained API.
|
||||||
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
|
pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
|
||||||
|
|
||||||
@ -1408,7 +1422,8 @@ extern "rust-intrinsic" {
|
|||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
|
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
|
||||||
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn needs_drop<T: ?Sized>() -> bool;
|
pub fn needs_drop<T: ?Sized>() -> bool;
|
||||||
@ -1430,7 +1445,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`pointer::offset`].
|
/// The stabilized version of this intrinsic is [`pointer::offset`].
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
|
pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
|
||||||
|
|
||||||
@ -1448,7 +1464,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
|
/// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
|
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
|
|
||||||
@ -2131,7 +2148,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `count_ones` method. For example,
|
/// primitives via the `count_ones` method. For example,
|
||||||
/// [`u32::count_ones`]
|
/// [`u32::count_ones`]
|
||||||
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn ctpop<T: Copy>(x: T) -> u32;
|
pub fn ctpop<T: Copy>(x: T) -> u32;
|
||||||
@ -2172,7 +2190,8 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_leading = ctlz(x);
|
/// let num_leading = ctlz(x);
|
||||||
/// assert_eq!(num_leading, 16);
|
/// assert_eq!(num_leading, 16);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn ctlz<T: Copy>(x: T) -> u32;
|
pub fn ctlz<T: Copy>(x: T) -> u32;
|
||||||
@ -2194,7 +2213,8 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_leading = unsafe { ctlz_nonzero(x) };
|
/// let num_leading = unsafe { ctlz_nonzero(x) };
|
||||||
/// assert_eq!(num_leading, 3);
|
/// assert_eq!(num_leading, 3);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
|
pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
|
||||||
|
|
||||||
@ -2234,7 +2254,8 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_trailing = cttz(x);
|
/// let num_trailing = cttz(x);
|
||||||
/// assert_eq!(num_trailing, 16);
|
/// assert_eq!(num_trailing, 16);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn cttz<T: Copy>(x: T) -> u32;
|
pub fn cttz<T: Copy>(x: T) -> u32;
|
||||||
@ -2256,7 +2277,8 @@ extern "rust-intrinsic" {
|
|||||||
/// let num_trailing = unsafe { cttz_nonzero(x) };
|
/// let num_trailing = unsafe { cttz_nonzero(x) };
|
||||||
/// assert_eq!(num_trailing, 3);
|
/// assert_eq!(num_trailing, 3);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
|
pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
|
||||||
|
|
||||||
@ -2270,7 +2292,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `swap_bytes` method. For example,
|
/// primitives via the `swap_bytes` method. For example,
|
||||||
/// [`u32::swap_bytes`]
|
/// [`u32::swap_bytes`]
|
||||||
#[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn bswap<T: Copy>(x: T) -> T;
|
pub fn bswap<T: Copy>(x: T) -> T;
|
||||||
@ -2285,7 +2308,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `reverse_bits` method. For example,
|
/// primitives via the `reverse_bits` method. For example,
|
||||||
/// [`u32::reverse_bits`]
|
/// [`u32::reverse_bits`]
|
||||||
#[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn bitreverse<T: Copy>(x: T) -> T;
|
pub fn bitreverse<T: Copy>(x: T) -> T;
|
||||||
@ -2311,7 +2335,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_add` method. For example,
|
/// primitives via the `overflowing_add` method. For example,
|
||||||
/// [`u32::overflowing_add`]
|
/// [`u32::overflowing_add`]
|
||||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||||
@ -2326,7 +2351,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_sub` method. For example,
|
/// primitives via the `overflowing_sub` method. For example,
|
||||||
/// [`u32::overflowing_sub`]
|
/// [`u32::overflowing_sub`]
|
||||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||||
@ -2341,7 +2367,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `overflowing_mul` method. For example,
|
/// primitives via the `overflowing_mul` method. For example,
|
||||||
/// [`u32::overflowing_mul`]
|
/// [`u32::overflowing_mul`]
|
||||||
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
|
||||||
@ -2360,7 +2387,11 @@ extern "rust-intrinsic" {
|
|||||||
/// Safe wrappers for this intrinsic are available on the integer
|
/// Safe wrappers for this intrinsic are available on the integer
|
||||||
/// primitives via the `checked_div` method. For example,
|
/// primitives via the `checked_div` method. For example,
|
||||||
/// [`u32::checked_div`]
|
/// [`u32::checked_div`]
|
||||||
#[rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
|
pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
|
||||||
/// Returns the remainder of an unchecked division, resulting in
|
/// Returns the remainder of an unchecked division, resulting in
|
||||||
@ -2369,7 +2400,11 @@ extern "rust-intrinsic" {
|
|||||||
/// Safe wrappers for this intrinsic are available on the integer
|
/// Safe wrappers for this intrinsic are available on the integer
|
||||||
/// primitives via the `checked_rem` method. For example,
|
/// primitives via the `checked_rem` method. For example,
|
||||||
/// [`u32::checked_rem`]
|
/// [`u32::checked_rem`]
|
||||||
#[rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
|
pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
|
||||||
|
|
||||||
@ -2379,7 +2414,8 @@ extern "rust-intrinsic" {
|
|||||||
/// Safe wrappers for this intrinsic are available on the integer
|
/// Safe wrappers for this intrinsic are available on the integer
|
||||||
/// primitives via the `checked_shl` method. For example,
|
/// primitives via the `checked_shl` method. For example,
|
||||||
/// [`u32::checked_shl`]
|
/// [`u32::checked_shl`]
|
||||||
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
|
pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
|
||||||
/// Performs an unchecked right shift, resulting in undefined behavior when
|
/// Performs an unchecked right shift, resulting in undefined behavior when
|
||||||
@ -2388,7 +2424,8 @@ extern "rust-intrinsic" {
|
|||||||
/// Safe wrappers for this intrinsic are available on the integer
|
/// Safe wrappers for this intrinsic are available on the integer
|
||||||
/// primitives via the `checked_shr` method. For example,
|
/// primitives via the `checked_shr` method. For example,
|
||||||
/// [`u32::checked_shr`]
|
/// [`u32::checked_shr`]
|
||||||
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
|
pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
|
||||||
|
|
||||||
@ -2397,7 +2434,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stable counterpart of this intrinsic is `unchecked_add` on the various
|
/// The stable counterpart of this intrinsic is `unchecked_add` on the various
|
||||||
/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
|
/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
|
||||||
#[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
|
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
|
||||||
|
|
||||||
@ -2406,7 +2444,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
|
/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
|
||||||
/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
|
/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
|
||||||
#[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
|
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
|
||||||
|
|
||||||
@ -2415,7 +2454,8 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
|
/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
|
||||||
/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
|
/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
|
||||||
#[rustc_const_stable(feature = "unchecked_math", since = "1.79.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
|
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
|
||||||
|
|
||||||
@ -2429,7 +2469,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `rotate_left` method. For example,
|
/// primitives via the `rotate_left` method. For example,
|
||||||
/// [`u32::rotate_left`]
|
/// [`u32::rotate_left`]
|
||||||
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
|
pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
|
||||||
@ -2444,7 +2485,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `rotate_right` method. For example,
|
/// primitives via the `rotate_right` method. For example,
|
||||||
/// [`u32::rotate_right`]
|
/// [`u32::rotate_right`]
|
||||||
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
|
pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
|
||||||
@ -2459,7 +2501,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_add` method. For example,
|
/// primitives via the `wrapping_add` method. For example,
|
||||||
/// [`u32::wrapping_add`]
|
/// [`u32::wrapping_add`]
|
||||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
|
pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
|
||||||
@ -2473,7 +2516,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_sub` method. For example,
|
/// primitives via the `wrapping_sub` method. For example,
|
||||||
/// [`u32::wrapping_sub`]
|
/// [`u32::wrapping_sub`]
|
||||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
|
pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
|
||||||
@ -2487,7 +2531,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `wrapping_mul` method. For example,
|
/// primitives via the `wrapping_mul` method. For example,
|
||||||
/// [`u32::wrapping_mul`]
|
/// [`u32::wrapping_mul`]
|
||||||
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
|
pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
|
||||||
@ -2502,7 +2547,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `saturating_add` method. For example,
|
/// primitives via the `saturating_add` method. For example,
|
||||||
/// [`u32::saturating_add`]
|
/// [`u32::saturating_add`]
|
||||||
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
|
pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
|
||||||
@ -2516,7 +2562,8 @@ extern "rust-intrinsic" {
|
|||||||
/// The stabilized versions of this intrinsic are available on the integer
|
/// The stabilized versions of this intrinsic are available on the integer
|
||||||
/// primitives via the `saturating_sub` method. For example,
|
/// primitives via the `saturating_sub` method. For example,
|
||||||
/// [`u32::saturating_sub`]
|
/// [`u32::saturating_sub`]
|
||||||
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
|
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
|
||||||
@ -2527,7 +2574,8 @@ extern "rust-intrinsic" {
|
|||||||
/// This intrinsic can *only* be called where the pointer is a local without
|
/// This intrinsic can *only* be called where the pointer is a local without
|
||||||
/// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
|
/// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
|
||||||
/// trivially obeys runtime-MIR rules about derefs in operands.
|
/// trivially obeys runtime-MIR rules about derefs in operands.
|
||||||
#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn read_via_copy<T>(ptr: *const T) -> T;
|
pub fn read_via_copy<T>(ptr: *const T) -> T;
|
||||||
|
|
||||||
@ -2537,7 +2585,8 @@ extern "rust-intrinsic" {
|
|||||||
/// This intrinsic can *only* be called where the pointer is a local without
|
/// This intrinsic can *only* be called where the pointer is a local without
|
||||||
/// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
|
/// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
|
||||||
/// that it trivially obeys runtime-MIR rules about derefs in operands.
|
/// that it trivially obeys runtime-MIR rules about derefs in operands.
|
||||||
#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn write_via_move<T>(ptr: *mut T, value: T);
|
pub fn write_via_move<T>(ptr: *mut T, value: T);
|
||||||
|
|
||||||
@ -2550,7 +2599,8 @@ extern "rust-intrinsic" {
|
|||||||
/// any safety invariants.
|
/// any safety invariants.
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
|
/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
|
||||||
#[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_safe_intrinsic]
|
#[rustc_safe_intrinsic]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
|
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
|
||||||
@ -2584,7 +2634,8 @@ extern "rust-intrinsic" {
|
|||||||
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
||||||
|
|
||||||
/// See documentation of `<*const T>::offset_from` for details.
|
/// See documentation of `<*const T>::offset_from` for details.
|
||||||
#[rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
||||||
|
|
||||||
@ -2850,7 +2901,8 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
|
|||||||
/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the
|
/// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the
|
||||||
/// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
|
/// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
|
||||||
/// primarily used by [`ub_checks::assert_unsafe_precondition`].
|
/// primarily used by [`ub_checks::assert_unsafe_precondition`].
|
||||||
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // just for UB checks
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
@ -2935,7 +2987,8 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
|
|||||||
/// The stabilized version of this intrinsic is [`core::mem::size_of`].
|
/// The stabilized version of this intrinsic is [`core::mem::size_of`].
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_intrinsic_must_be_overridden]
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
pub const fn size_of<T>() -> usize {
|
pub const fn size_of<T>() -> usize {
|
||||||
@ -2952,7 +3005,8 @@ pub const fn size_of<T>() -> usize {
|
|||||||
/// The stabilized version of this intrinsic is [`core::mem::align_of`].
|
/// The stabilized version of this intrinsic is [`core::mem::align_of`].
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_intrinsic_must_be_overridden]
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
pub const fn min_align_of<T>() -> usize {
|
pub const fn min_align_of<T>() -> usize {
|
||||||
@ -3065,7 +3119,8 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128 {
|
|||||||
/// change the possible layouts of pointers.
|
/// change the possible layouts of pointers.
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_intrinsic_must_be_overridden]
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P {
|
pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P {
|
||||||
@ -3090,7 +3145,11 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
|
|||||||
/// This is used to implement functions like `ptr::metadata`.
|
/// This is used to implement functions like `ptr::metadata`.
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
#[rustc_intrinsic_must_be_overridden]
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
|
pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
|
||||||
@ -3197,7 +3256,15 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
|
|||||||
#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
|
#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
|
||||||
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(bootstrap),
|
||||||
|
rustc_const_unstable(feature = "core_intrinsics", issue = "none")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
@ -3301,7 +3368,15 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
|
|||||||
#[rustc_diagnostic_item = "ptr_copy"]
|
#[rustc_diagnostic_item = "ptr_copy"]
|
||||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
|
#[cfg_attr(
|
||||||
|
bootstrap,
|
||||||
|
rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(bootstrap),
|
||||||
|
rustc_const_unstable(feature = "core_intrinsics", issue = "none")
|
||||||
|
)]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
@ -3382,7 +3457,8 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
|||||||
#[rustc_diagnostic_item = "ptr_write_bytes"]
|
#[rustc_diagnostic_item = "ptr_write_bytes"]
|
||||||
pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
||||||
}
|
}
|
||||||
@ -3643,6 +3719,7 @@ pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 {
|
|||||||
|
|
||||||
/// Inform Miri that a given pointer definitely has a certain alignment.
|
/// Inform Miri that a given pointer definitely has a certain alignment.
|
||||||
#[cfg(miri)]
|
#[cfg(miri)]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) {
|
pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) {
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
/// Miri-provided extern function to promise that a given pointer is properly aligned for
|
/// Miri-provided extern function to promise that a given pointer is properly aligned for
|
||||||
|
@ -346,7 +346,6 @@ pub trait IntoIterator {
|
|||||||
fn into_iter(self) -> Self::IntoIter;
|
fn into_iter(self) -> Self::IntoIter;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<I: Iterator> IntoIterator for I {
|
impl<I: Iterator> IntoIterator for I {
|
||||||
type Item = I::Item;
|
type Item = I::Item;
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
//
|
//
|
||||||
// Library features:
|
// Library features:
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))]
|
||||||
#![feature(array_ptr_get)]
|
#![feature(array_ptr_get)]
|
||||||
#![feature(asm_experimental_arch)]
|
#![feature(asm_experimental_arch)]
|
||||||
#![feature(const_align_of_val)]
|
#![feature(const_align_of_val)]
|
||||||
@ -121,11 +122,8 @@
|
|||||||
#![feature(const_eval_select)]
|
#![feature(const_eval_select)]
|
||||||
#![feature(const_exact_div)]
|
#![feature(const_exact_div)]
|
||||||
#![feature(const_float_methods)]
|
#![feature(const_float_methods)]
|
||||||
#![feature(const_fmt_arguments_new)]
|
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_index_range_slice_index)]
|
|
||||||
#![feature(const_likely)]
|
|
||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_midpoint)]
|
#![feature(const_num_midpoint)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
@ -144,6 +142,7 @@
|
|||||||
#![feature(const_typed_swap)]
|
#![feature(const_typed_swap)]
|
||||||
#![feature(const_ub_checks)]
|
#![feature(const_ub_checks)]
|
||||||
#![feature(const_unicode_case_lookup)]
|
#![feature(const_unicode_case_lookup)]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
#![feature(coverage_attribute)]
|
#![feature(coverage_attribute)]
|
||||||
#![feature(do_not_recommend)]
|
#![feature(do_not_recommend)]
|
||||||
#![feature(internal_impls_macro)]
|
#![feature(internal_impls_macro)]
|
||||||
@ -159,6 +158,7 @@
|
|||||||
#![feature(ptr_alignment_type)]
|
#![feature(ptr_alignment_type)]
|
||||||
#![feature(ptr_metadata)]
|
#![feature(ptr_metadata)]
|
||||||
#![feature(set_ptr_value)]
|
#![feature(set_ptr_value)]
|
||||||
|
#![feature(slice_as_chunks)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(str_internals)]
|
#![feature(str_internals)]
|
||||||
#![feature(str_split_inclusive_remainder)]
|
#![feature(str_split_inclusive_remainder)]
|
||||||
|
@ -373,6 +373,7 @@ impl IpAddr {
|
|||||||
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
|
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ip", issue = "27709")]
|
#[unstable(feature = "ip", issue = "27709")]
|
||||||
|
#[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn is_benchmarking(&self) -> bool {
|
pub const fn is_benchmarking(&self) -> bool {
|
||||||
|
@ -288,7 +288,6 @@ impl f128 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub(crate) const fn abs_private(self) -> f128 {
|
pub(crate) const fn abs_private(self) -> f128 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -319,7 +318,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
(self == f128::INFINITY) | (self == f128::NEG_INFINITY)
|
(self == f128::INFINITY) | (self == f128::NEG_INFINITY)
|
||||||
}
|
}
|
||||||
@ -346,7 +344,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
// the comparison is not true, exactly as desired.
|
// the comparison is not true, exactly as desired.
|
||||||
@ -380,7 +377,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
}
|
}
|
||||||
@ -412,7 +408,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
}
|
}
|
||||||
@ -437,7 +432,6 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let bits = self.to_bits();
|
let bits = self.to_bits();
|
||||||
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
match (bits & Self::MAN_MASK, bits & Self::EXP_MASK) {
|
||||||
@ -915,7 +909,6 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_bits(self) -> u128 {
|
pub const fn to_bits(self) -> u128 {
|
||||||
// SAFETY: `u128` is a plain old datatype so we can always transmute to it.
|
// SAFETY: `u128` is a plain old datatype so we can always transmute to it.
|
||||||
@ -964,7 +957,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn from_bits(v: u128) -> Self {
|
pub const fn from_bits(v: u128) -> Self {
|
||||||
// It turns out the safety issues with sNaN were overblown! Hooray!
|
// It turns out the safety issues with sNaN were overblown! Hooray!
|
||||||
// SAFETY: `u128` is a plain old datatype so we can always transmute from it.
|
// SAFETY: `u128` is a plain old datatype so we can always transmute from it.
|
||||||
@ -991,7 +983,6 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_be_bytes(self) -> [u8; 16] {
|
pub const fn to_be_bytes(self) -> [u8; 16] {
|
||||||
self.to_bits().to_be_bytes()
|
self.to_bits().to_be_bytes()
|
||||||
@ -1017,7 +1008,6 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_le_bytes(self) -> [u8; 16] {
|
pub const fn to_le_bytes(self) -> [u8; 16] {
|
||||||
self.to_bits().to_le_bytes()
|
self.to_bits().to_le_bytes()
|
||||||
@ -1054,7 +1044,6 @@ impl f128 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_ne_bytes(self) -> [u8; 16] {
|
pub const fn to_ne_bytes(self) -> [u8; 16] {
|
||||||
self.to_bits().to_ne_bytes()
|
self.to_bits().to_ne_bytes()
|
||||||
@ -1082,7 +1071,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn from_be_bytes(bytes: [u8; 16]) -> Self {
|
pub const fn from_be_bytes(bytes: [u8; 16]) -> Self {
|
||||||
Self::from_bits(u128::from_be_bytes(bytes))
|
Self::from_bits(u128::from_be_bytes(bytes))
|
||||||
}
|
}
|
||||||
@ -1109,7 +1097,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
|
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
|
||||||
Self::from_bits(u128::from_le_bytes(bytes))
|
Self::from_bits(u128::from_le_bytes(bytes))
|
||||||
}
|
}
|
||||||
@ -1146,7 +1133,6 @@ impl f128 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f128", issue = "116909")]
|
#[unstable(feature = "f128", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f128", issue = "116909")]
|
|
||||||
pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self {
|
pub const fn from_ne_bytes(bytes: [u8; 16]) -> Self {
|
||||||
Self::from_bits(u128::from_ne_bytes(bytes))
|
Self::from_bits(u128::from_ne_bytes(bytes))
|
||||||
}
|
}
|
||||||
|
@ -282,7 +282,6 @@ impl f16 {
|
|||||||
// concerns about portability, so this implementation is for
|
// concerns about portability, so this implementation is for
|
||||||
// private use internally.
|
// private use internally.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub(crate) const fn abs_private(self) -> f16 {
|
pub(crate) const fn abs_private(self) -> f16 {
|
||||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||||
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
|
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
|
||||||
@ -310,7 +309,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn is_infinite(self) -> bool {
|
pub const fn is_infinite(self) -> bool {
|
||||||
(self == f16::INFINITY) | (self == f16::NEG_INFINITY)
|
(self == f16::INFINITY) | (self == f16::NEG_INFINITY)
|
||||||
}
|
}
|
||||||
@ -336,7 +334,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn is_finite(self) -> bool {
|
pub const fn is_finite(self) -> bool {
|
||||||
// There's no need to handle NaN separately: if self is NaN,
|
// There's no need to handle NaN separately: if self is NaN,
|
||||||
// the comparison is not true, exactly as desired.
|
// the comparison is not true, exactly as desired.
|
||||||
@ -368,7 +365,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn is_subnormal(self) -> bool {
|
pub const fn is_subnormal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Subnormal)
|
matches!(self.classify(), FpCategory::Subnormal)
|
||||||
}
|
}
|
||||||
@ -398,7 +394,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn is_normal(self) -> bool {
|
pub const fn is_normal(self) -> bool {
|
||||||
matches!(self.classify(), FpCategory::Normal)
|
matches!(self.classify(), FpCategory::Normal)
|
||||||
}
|
}
|
||||||
@ -422,7 +417,6 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn classify(self) -> FpCategory {
|
pub const fn classify(self) -> FpCategory {
|
||||||
let b = self.to_bits();
|
let b = self.to_bits();
|
||||||
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
|
||||||
@ -901,7 +895,6 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_bits(self) -> u16 {
|
pub const fn to_bits(self) -> u16 {
|
||||||
// SAFETY: `u16` is a plain old datatype so we can always transmute to it.
|
// SAFETY: `u16` is a plain old datatype so we can always transmute to it.
|
||||||
@ -949,7 +942,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn from_bits(v: u16) -> Self {
|
pub const fn from_bits(v: u16) -> Self {
|
||||||
// It turns out the safety issues with sNaN were overblown! Hooray!
|
// It turns out the safety issues with sNaN were overblown! Hooray!
|
||||||
// SAFETY: `u16` is a plain old datatype so we can always transmute from it.
|
// SAFETY: `u16` is a plain old datatype so we can always transmute from it.
|
||||||
@ -975,7 +967,6 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_be_bytes(self) -> [u8; 2] {
|
pub const fn to_be_bytes(self) -> [u8; 2] {
|
||||||
self.to_bits().to_be_bytes()
|
self.to_bits().to_be_bytes()
|
||||||
@ -1000,7 +991,6 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_le_bytes(self) -> [u8; 2] {
|
pub const fn to_le_bytes(self) -> [u8; 2] {
|
||||||
self.to_bits().to_le_bytes()
|
self.to_bits().to_le_bytes()
|
||||||
@ -1038,7 +1028,6 @@ impl f16 {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||||
pub const fn to_ne_bytes(self) -> [u8; 2] {
|
pub const fn to_ne_bytes(self) -> [u8; 2] {
|
||||||
self.to_bits().to_ne_bytes()
|
self.to_bits().to_ne_bytes()
|
||||||
@ -1062,7 +1051,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
|
pub const fn from_be_bytes(bytes: [u8; 2]) -> Self {
|
||||||
Self::from_bits(u16::from_be_bytes(bytes))
|
Self::from_bits(u16::from_be_bytes(bytes))
|
||||||
}
|
}
|
||||||
@ -1085,7 +1073,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
|
pub const fn from_le_bytes(bytes: [u8; 2]) -> Self {
|
||||||
Self::from_bits(u16::from_le_bytes(bytes))
|
Self::from_bits(u16::from_le_bytes(bytes))
|
||||||
}
|
}
|
||||||
@ -1119,7 +1106,6 @@ impl f16 {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "f16", issue = "116909")]
|
#[unstable(feature = "f16", issue = "116909")]
|
||||||
#[rustc_const_unstable(feature = "f16", issue = "116909")]
|
|
||||||
pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
|
pub const fn from_ne_bytes(bytes: [u8; 2]) -> Self {
|
||||||
Self::from_bits(u16::from_ne_bytes(bytes))
|
Self::from_bits(u16::from_ne_bytes(bytes))
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ macro_rules! try_opt {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow_internal_unstable(const_likely)]
|
#[cfg_attr(bootstrap, allow_internal_unstable(const_likely))]
|
||||||
macro_rules! unlikely {
|
macro_rules! unlikely {
|
||||||
($e: expr) => {
|
($e: expr) => {
|
||||||
intrinsics::unlikely($e)
|
intrinsics::unlikely($e)
|
||||||
@ -1397,7 +1397,7 @@ from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[unstable(issue = "none", feature = "std_internals")]
|
#[unstable(issue = "none", feature = "std_internals")]
|
||||||
#[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_from_str", since = "1.82.0"))]
|
||||||
pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
|
pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
|
||||||
radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
|
radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
|
||||||
}
|
}
|
||||||
@ -1416,6 +1416,7 @@ fn from_str_radix_panic_rt(radix: u32) -> ! {
|
|||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[cold]
|
#[cold]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn from_str_radix_panic(radix: u32) {
|
const fn from_str_radix_panic(radix: u32) {
|
||||||
// The only difference between these two functions is their panic message.
|
// The only difference between these two functions is their panic message.
|
||||||
intrinsics::const_eval_select((radix,), from_str_radix_panic_ct, from_str_radix_panic_rt);
|
intrinsics::const_eval_select((radix,), from_str_radix_panic_ct, from_str_radix_panic_rt);
|
||||||
|
@ -3009,7 +3009,7 @@ macro_rules! uint_impl {
|
|||||||
// overflow cases it instead ends up returning the maximum value
|
// overflow cases it instead ends up returning the maximum value
|
||||||
// of the type, and can return 0 for 0.
|
// of the type, and can return 0 for 0.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_pow", since = "1.50.0"))]
|
||||||
const fn one_less_than_next_power_of_two(self) -> Self {
|
const fn one_less_than_next_power_of_two(self) -> Self {
|
||||||
if self <= 1 { return 0; }
|
if self <= 1 { return 0; }
|
||||||
|
|
||||||
|
@ -168,6 +168,7 @@ impl<'a> PanicMessage<'a> {
|
|||||||
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
|
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
|
||||||
pub const fn as_str(&self) -> Option<&'static str> {
|
pub const fn as_str(&self) -> Option<&'static str> {
|
||||||
self.message.as_str()
|
self.message.as_str()
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,8 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[lang = "panic_fmt"] // needed for const-evaluated panics
|
#[lang = "panic_fmt"] // needed for const-evaluated panics
|
||||||
#[rustc_do_not_const_check] // hooked by const-eval
|
#[rustc_do_not_const_check] // hooked by const-eval
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||||
if cfg!(feature = "panic_immediate_abort") {
|
if cfg!(feature = "panic_immediate_abort") {
|
||||||
super::intrinsics::abort()
|
super::intrinsics::abort()
|
||||||
@ -84,7 +85,9 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
|||||||
// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
|
// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
|
||||||
// which causes a "panic in a function that cannot unwind".
|
// which causes a "panic in a function that cannot unwind".
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
|
pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
|
||||||
#[inline] // this should always be inlined into `panic_nounwind_fmt`
|
#[inline] // this should always be inlined into `panic_nounwind_fmt`
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
@ -131,7 +134,8 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
|
|||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
#[lang = "panic"] // used by lints and miri for panics
|
#[lang = "panic"] // used by lints and miri for panics
|
||||||
pub const fn panic(expr: &'static str) -> ! {
|
pub const fn panic(expr: &'static str) -> ! {
|
||||||
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
|
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
|
||||||
@ -169,7 +173,8 @@ macro_rules! panic_const {
|
|||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
#[lang = stringify!($lang)]
|
#[lang = stringify!($lang)]
|
||||||
pub const fn $lang() -> ! {
|
pub const fn $lang() -> ! {
|
||||||
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
|
// Use Arguments::new_const instead of format_args!("{expr}") to potentially
|
||||||
@ -216,7 +221,8 @@ panic_const! {
|
|||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
|
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn panic_nounwind(expr: &'static str) -> ! {
|
pub const fn panic_nounwind(expr: &'static str) -> ! {
|
||||||
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false);
|
panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false);
|
||||||
}
|
}
|
||||||
@ -232,7 +238,8 @@ pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn panic_explicit() -> ! {
|
pub const fn panic_explicit() -> ! {
|
||||||
panic_display(&"explicit panic");
|
panic_display(&"explicit panic");
|
||||||
}
|
}
|
||||||
@ -249,7 +256,8 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[rustc_diagnostic_item = "panic_str_2015"]
|
#[rustc_diagnostic_item = "panic_str_2015"]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn panic_str_2015(expr: &str) -> ! {
|
pub const fn panic_str_2015(expr: &str) -> ! {
|
||||||
panic_display(&expr);
|
panic_display(&expr);
|
||||||
}
|
}
|
||||||
@ -259,7 +267,8 @@ pub const fn panic_str_2015(expr: &str) -> ! {
|
|||||||
#[rustc_do_not_const_check] // hooked by const-eval
|
#[rustc_do_not_const_check] // hooked by const-eval
|
||||||
// enforce a &&str argument in const-check and hook this by const-eval
|
// enforce a &&str argument in const-check and hook this by const-eval
|
||||||
#[rustc_const_panic_str]
|
#[rustc_const_panic_str]
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
|
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
|
||||||
panic_fmt(format_args!("{}", *x));
|
panic_fmt(format_args!("{}", *x));
|
||||||
}
|
}
|
||||||
@ -327,8 +336,9 @@ fn panic_in_cleanup() -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This function is used instead of panic_fmt in const eval.
|
/// This function is used instead of panic_fmt in const eval.
|
||||||
#[lang = "const_panic_fmt"]
|
#[lang = "const_panic_fmt"] // needed by const-eval machine to replace calls to `panic_fmt` lang item
|
||||||
#[rustc_const_unstable(feature = "panic_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "panic_internals", issue = "none"))]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
|
||||||
pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||||
if let Some(msg) = fmt.as_str() {
|
if let Some(msg) = fmt.as_str() {
|
||||||
// The panic_display function is hooked by const eval.
|
// The panic_display function is hooked by const eval.
|
||||||
|
@ -41,7 +41,7 @@ impl Alignment {
|
|||||||
/// This provides the same numerical value as [`mem::align_of`],
|
/// This provides the same numerical value as [`mem::align_of`],
|
||||||
/// but in an `Alignment` instead of a `usize`.
|
/// but in an `Alignment` instead of a `usize`.
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn of<T>() -> Self {
|
pub const fn of<T>() -> Self {
|
||||||
// SAFETY: rustc ensures that type alignment is always a power of two.
|
// SAFETY: rustc ensures that type alignment is always a power of two.
|
||||||
@ -53,7 +53,7 @@ impl Alignment {
|
|||||||
///
|
///
|
||||||
/// Note that `0` is not a power of two, nor a valid alignment.
|
/// Note that `0` is not a power of two, nor a valid alignment.
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new(align: usize) -> Option<Self> {
|
pub const fn new(align: usize) -> Option<Self> {
|
||||||
if align.is_power_of_two() {
|
if align.is_power_of_two() {
|
||||||
@ -73,7 +73,7 @@ impl Alignment {
|
|||||||
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
|
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
|
||||||
/// It must *not* be zero.
|
/// It must *not* be zero.
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const unsafe fn new_unchecked(align: usize) -> Self {
|
pub const unsafe fn new_unchecked(align: usize) -> Self {
|
||||||
assert_unsafe_precondition!(
|
assert_unsafe_precondition!(
|
||||||
@ -89,7 +89,7 @@ impl Alignment {
|
|||||||
|
|
||||||
/// Returns the alignment as a [`usize`].
|
/// Returns the alignment as a [`usize`].
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn as_usize(self) -> usize {
|
pub const fn as_usize(self) -> usize {
|
||||||
self.0 as usize
|
self.0 as usize
|
||||||
@ -97,7 +97,7 @@ impl Alignment {
|
|||||||
|
|
||||||
/// Returns the alignment as a <code>[NonZero]<[usize]></code>.
|
/// Returns the alignment as a <code>[NonZero]<[usize]></code>.
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn as_nonzero(self) -> NonZero<usize> {
|
pub const fn as_nonzero(self) -> NonZero<usize> {
|
||||||
// SAFETY: All the discriminants are non-zero.
|
// SAFETY: All the discriminants are non-zero.
|
||||||
@ -118,7 +118,7 @@ impl Alignment {
|
|||||||
/// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
|
/// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn log2(self) -> u32 {
|
pub const fn log2(self) -> u32 {
|
||||||
self.as_nonzero().trailing_zeros()
|
self.as_nonzero().trailing_zeros()
|
||||||
@ -148,7 +148,7 @@ impl Alignment {
|
|||||||
/// assert_ne!(one.mask(Alignment::of::<Align4>().mask()), one);
|
/// assert_ne!(one.mask(Alignment::of::<Align4>().mask()), one);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
|
||||||
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn mask(self) -> usize {
|
pub const fn mask(self) -> usize {
|
||||||
// SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
|
// SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
|
||||||
|
@ -39,6 +39,7 @@ impl<T: ?Sized> *const T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
|
||||||
const fn const_impl(ptr: *const u8) -> bool {
|
const fn const_impl(ptr: *const u8) -> bool {
|
||||||
match (ptr).guaranteed_eq(null_mut()) {
|
match (ptr).guaranteed_eq(null_mut()) {
|
||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
@ -113,7 +114,7 @@ impl<T: ?Sized> *const T {
|
|||||||
/// println!("{:?}", unsafe { &*bad });
|
/// println!("{:?}", unsafe { &*bad });
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "set_ptr_value", issue = "75091")]
|
#[unstable(feature = "set_ptr_value", issue = "75091")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
|
pub const fn with_metadata_of<U>(self, meta: *const U) -> *const U
|
||||||
@ -409,6 +410,7 @@ impl<T: ?Sized> *const T {
|
|||||||
T: Sized,
|
T: Sized,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
|
const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: isize, size: usize) -> bool {
|
fn runtime(this: *const (), count: isize, size: usize) -> bool {
|
||||||
@ -761,6 +763,7 @@ impl<T: ?Sized> *const T {
|
|||||||
where
|
where
|
||||||
T: Sized,
|
T: Sized,
|
||||||
{
|
{
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool {
|
const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool {
|
||||||
fn runtime(this: *const (), origin: *const ()) -> bool {
|
fn runtime(this: *const (), origin: *const ()) -> bool {
|
||||||
this >= origin
|
this >= origin
|
||||||
@ -902,6 +905,7 @@ impl<T: ?Sized> *const T {
|
|||||||
{
|
{
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
||||||
@ -1010,6 +1014,7 @@ impl<T: ?Sized> *const T {
|
|||||||
{
|
{
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
||||||
@ -1622,6 +1627,7 @@ impl<T: ?Sized> *const T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||||
const fn const_impl(ptr: *const (), align: usize) -> bool {
|
const fn const_impl(ptr: *const (), align: usize) -> bool {
|
||||||
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
||||||
ptr.align_offset(align) == 0
|
ptr.align_offset(align) == 0
|
||||||
|
@ -92,7 +92,7 @@ pub trait Thin = Pointee<Metadata = ()>;
|
|||||||
///
|
///
|
||||||
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
|
/// assert_eq!(std::ptr::metadata("foo"), 3_usize);
|
||||||
/// ```
|
/// ```
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
||||||
ptr_metadata(ptr)
|
ptr_metadata(ptr)
|
||||||
@ -106,7 +106,7 @@ pub const fn metadata<T: ?Sized>(ptr: *const T) -> <T as Pointee>::Metadata {
|
|||||||
///
|
///
|
||||||
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
|
/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
|
||||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_raw_parts<T: ?Sized>(
|
pub const fn from_raw_parts<T: ?Sized>(
|
||||||
data_pointer: *const impl Thin,
|
data_pointer: *const impl Thin,
|
||||||
@ -120,7 +120,7 @@ pub const fn from_raw_parts<T: ?Sized>(
|
|||||||
///
|
///
|
||||||
/// See the documentation of [`from_raw_parts`] for more details.
|
/// See the documentation of [`from_raw_parts`] for more details.
|
||||||
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
#[unstable(feature = "ptr_metadata", issue = "81513")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_raw_parts_mut<T: ?Sized>(
|
pub const fn from_raw_parts_mut<T: ?Sized>(
|
||||||
data_pointer: *mut impl Thin,
|
data_pointer: *mut impl Thin,
|
||||||
|
@ -591,8 +591,8 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
|
|||||||
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
|
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
|
|
||||||
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn without_provenance<T>(addr: usize) -> *const T {
|
pub const fn without_provenance<T>(addr: usize) -> *const T {
|
||||||
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
|
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
|
||||||
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
|
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
|
||||||
@ -613,8 +613,8 @@ pub const fn without_provenance<T>(addr: usize) -> *const T {
|
|||||||
/// some other means.
|
/// some other means.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
|
|
||||||
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn dangling<T>() -> *const T {
|
pub const fn dangling<T>() -> *const T {
|
||||||
without_provenance(mem::align_of::<T>())
|
without_provenance(mem::align_of::<T>())
|
||||||
}
|
}
|
||||||
@ -634,8 +634,8 @@ pub const fn dangling<T>() -> *const T {
|
|||||||
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
|
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
|
|
||||||
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
|
pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
|
||||||
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
|
// An int-to-pointer transmute currently has exactly the intended semantics: it creates a
|
||||||
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
|
// pointer without provenance. Note that this is *not* a stable guarantee about transmute
|
||||||
@ -656,8 +656,8 @@ pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
|
|||||||
/// some other means.
|
/// some other means.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "stable_things_using_strict_provenance", since = "1.61.0")]
|
|
||||||
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
#[stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
|
#[rustc_const_stable(feature = "strict_provenance", since = "CURRENT_RUSTC_VERSION")]
|
||||||
pub const fn dangling_mut<T>() -> *mut T {
|
pub const fn dangling_mut<T>() -> *mut T {
|
||||||
without_provenance_mut(mem::align_of::<T>())
|
without_provenance_mut(mem::align_of::<T>())
|
||||||
}
|
}
|
||||||
@ -1854,6 +1854,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
|||||||
/// Any questions go to @nagisa.
|
/// Any questions go to @nagisa.
|
||||||
#[allow(ptr_to_integer_transmute_in_consts)]
|
#[allow(ptr_to_integer_transmute_in_consts)]
|
||||||
#[lang = "align_offset"]
|
#[lang = "align_offset"]
|
||||||
|
#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
|
||||||
pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
|
pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
|
||||||
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
|
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
|
||||||
// 1, where the method versions of these operations are not inlined.
|
// 1, where the method versions of these operations are not inlined.
|
||||||
|
@ -94,7 +94,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
|
/// // This dereference is UB. The pointer only has provenance for `x` but points to `y`.
|
||||||
/// println!("{:?}", unsafe { &*bad });
|
/// println!("{:?}", unsafe { &*bad });
|
||||||
#[unstable(feature = "set_ptr_value", issue = "75091")]
|
#[unstable(feature = "set_ptr_value", issue = "75091")]
|
||||||
#[rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
|
||||||
#[must_use = "returns a new pointer rather than modifying its argument"]
|
#[must_use = "returns a new pointer rather than modifying its argument"]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
pub const fn with_metadata_of<U>(self, meta: *const U) -> *mut U
|
||||||
@ -405,6 +405,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
T: Sized,
|
T: Sized,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
|
const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: isize, size: usize) -> bool {
|
fn runtime(this: *const (), count: isize, size: usize) -> bool {
|
||||||
@ -984,6 +985,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
{
|
{
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
||||||
@ -1092,6 +1094,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
{
|
{
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
fn runtime(this: *const (), count: usize, size: usize) -> bool {
|
||||||
@ -1871,6 +1874,7 @@ impl<T: ?Sized> *mut T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
|
||||||
const fn const_impl(ptr: *mut (), align: usize) -> bool {
|
const fn const_impl(ptr: *mut (), align: usize) -> bool {
|
||||||
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
// We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
|
||||||
ptr.align_offset(align) == 0
|
ptr.align_offset(align) == 0
|
||||||
|
@ -1508,7 +1508,6 @@ impl<T> NonNull<[T]> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
#[unstable(feature = "slice_ptr_get", issue = "74265")]
|
||||||
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
|
|
||||||
pub const fn as_non_null_ptr(self) -> NonNull<T> {
|
pub const fn as_non_null_ptr(self) -> NonNull<T> {
|
||||||
self.cast()
|
self.cast()
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ impl<T: ?Sized> Unique<T> {
|
|||||||
|
|
||||||
/// Creates a new `Unique` if `ptr` is non-null.
|
/// Creates a new `Unique` if `ptr` is non-null.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "ptr_internals", issue = "none")]
|
||||||
pub const fn new(ptr: *mut T) -> Option<Self> {
|
pub const fn new(ptr: *mut T) -> Option<Self> {
|
||||||
if let Some(pointer) = NonNull::new(ptr) {
|
if let Some(pointer) = NonNull::new(ptr) {
|
||||||
Some(Unique { pointer, _marker: PhantomData })
|
Some(Unique { pointer, _marker: PhantomData })
|
||||||
|
@ -346,6 +346,8 @@ pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool {
|
|||||||
/// If any of these loads produces something for which `contains_nonascii`
|
/// If any of these loads produces something for which `contains_nonascii`
|
||||||
/// (above) returns true, then we know the answer is false.
|
/// (above) returns true, then we know the answer is false.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_raw_ptr_comparison, const_pointer_is_aligned)] // only in a debug assertion
|
||||||
|
#[rustc_allow_const_fn_unstable(const_align_offset)] // behavior does not change when `align_offset` fails
|
||||||
const fn is_ascii(s: &[u8]) -> bool {
|
const fn is_ascii(s: &[u8]) -> bool {
|
||||||
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
const USIZE_SIZE: usize = mem::size_of::<usize>();
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ where
|
|||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
|
const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
|
||||||
// FIXME(const-hack): once integer formatting in panics is possible, we
|
// FIXME(const-hack): once integer formatting in panics is possible, we
|
||||||
// should use the same implementation at compiletime and runtime.
|
// should use the same implementation at compiletime and runtime.
|
||||||
@ -52,6 +53,7 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
|
|||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
|
const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
|
||||||
// FIXME(const-hack): once integer formatting in panics is possible, we
|
// FIXME(const-hack): once integer formatting in panics is possible, we
|
||||||
// should use the same implementation at compiletime and runtime.
|
// should use the same implementation at compiletime and runtime.
|
||||||
@ -73,6 +75,7 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
|
|||||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
|
||||||
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
#[cfg_attr(feature = "panic_immediate_abort", inline)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
const fn slice_index_order_fail(index: usize, end: usize) -> ! {
|
const fn slice_index_order_fail(index: usize, end: usize) -> ! {
|
||||||
// FIXME(const-hack): once integer formatting in panics is possible, we
|
// FIXME(const-hack): once integer formatting in panics is possible, we
|
||||||
// should use the same implementation at compiletime and runtime.
|
// should use the same implementation at compiletime and runtime.
|
||||||
@ -310,7 +313,6 @@ unsafe impl<T> SliceIndex<[T]> for usize {
|
|||||||
|
|
||||||
/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
|
/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
|
||||||
/// than there are for a general `Range<usize>` (which might be `100..3`).
|
/// than there are for a general `Range<usize>` (which might be `100..3`).
|
||||||
#[rustc_const_unstable(feature = "const_index_range_slice_index", issue = "none")]
|
|
||||||
unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
|
unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
|
||||||
type Output = [T];
|
type Output = [T];
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const USIZE_BYTES: usize = mem::size_of::<usize>();
|
|||||||
/// bytes where the borrow propagated all the way to the most significant
|
/// bytes where the borrow propagated all the way to the most significant
|
||||||
/// bit."
|
/// bit."
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
|
||||||
const fn contains_zero_byte(x: usize) -> bool {
|
const fn contains_zero_byte(x: usize) -> bool {
|
||||||
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
|
x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@ const fn contains_zero_byte(x: usize) -> bool {
|
|||||||
/// Returns the first index matching the byte `x` in `text`.
|
/// Returns the first index matching the byte `x` in `text`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
|
||||||
pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
|
pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
|
||||||
// Fast path for small slices.
|
// Fast path for small slices.
|
||||||
if text.len() < 2 * USIZE_BYTES {
|
if text.len() < 2 * USIZE_BYTES {
|
||||||
@ -34,7 +34,7 @@ pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
|
||||||
const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
|
const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
|
|||||||
|
|
||||||
#[rustc_allow_const_fn_unstable(const_cmp)]
|
#[rustc_allow_const_fn_unstable(const_cmp)]
|
||||||
#[rustc_allow_const_fn_unstable(const_align_offset)]
|
#[rustc_allow_const_fn_unstable(const_align_offset)]
|
||||||
#[rustc_const_stable(feature = "const_memchr", since = "1.65.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
|
||||||
const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> {
|
const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> {
|
||||||
// Scan for a single byte value by reading two `usize` words at a time.
|
// Scan for a single byte value by reading two `usize` words at a time.
|
||||||
//
|
//
|
||||||
|
@ -1265,6 +1265,7 @@ impl<T> [T] {
|
|||||||
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
|
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
|
pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
|
||||||
@ -1310,6 +1311,7 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
|
/// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -1344,6 +1346,7 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
|
/// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -1422,6 +1425,7 @@ impl<T> [T] {
|
|||||||
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
|
/// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
|
pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
|
||||||
@ -1462,6 +1466,7 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(v, &[1, 1, 2, 2, 9]);
|
/// assert_eq!(v, &[1, 1, 2, 2, 9]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -1502,6 +1507,7 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(v, &[9, 1, 1, 2, 2]);
|
/// assert_eq!(v, &[9, 1, 1, 2, 2]);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
#[unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
|
#[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -2122,7 +2122,8 @@ macro_rules! atomic_int {
|
|||||||
$stable_access:meta,
|
$stable_access:meta,
|
||||||
$stable_from:meta,
|
$stable_from:meta,
|
||||||
$stable_nand:meta,
|
$stable_nand:meta,
|
||||||
$const_stable:meta,
|
$const_stable_new:meta,
|
||||||
|
$const_stable_into_inner:meta,
|
||||||
$diagnostic_item:meta,
|
$diagnostic_item:meta,
|
||||||
$s_int_type:literal,
|
$s_int_type:literal,
|
||||||
$extra_feature:expr,
|
$extra_feature:expr,
|
||||||
@ -2204,7 +2205,7 @@ macro_rules! atomic_int {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[$stable]
|
#[$stable]
|
||||||
#[$const_stable]
|
#[$const_stable_new]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(v: $int_type) -> Self {
|
pub const fn new(v: $int_type) -> Self {
|
||||||
Self {v: UnsafeCell::new(v)}
|
Self {v: UnsafeCell::new(v)}
|
||||||
@ -2406,7 +2407,7 @@ macro_rules! atomic_int {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[$stable_access]
|
#[$stable_access]
|
||||||
#[rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0")]
|
#[$const_stable_into_inner]
|
||||||
pub const fn into_inner(self) -> $int_type {
|
pub const fn into_inner(self) -> $int_type {
|
||||||
self.v.into_inner()
|
self.v.into_inner()
|
||||||
}
|
}
|
||||||
@ -3054,6 +3055,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI8"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI8"),
|
||||||
"i8",
|
"i8",
|
||||||
"",
|
"",
|
||||||
@ -3072,6 +3074,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU8"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU8"),
|
||||||
"u8",
|
"u8",
|
||||||
"",
|
"",
|
||||||
@ -3090,6 +3093,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI16"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI16"),
|
||||||
"i16",
|
"i16",
|
||||||
"",
|
"",
|
||||||
@ -3108,6 +3112,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU16"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU16"),
|
||||||
"u16",
|
"u16",
|
||||||
"",
|
"",
|
||||||
@ -3126,6 +3131,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI32"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI32"),
|
||||||
"i32",
|
"i32",
|
||||||
"",
|
"",
|
||||||
@ -3144,6 +3150,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU32"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU32"),
|
||||||
"u32",
|
"u32",
|
||||||
"",
|
"",
|
||||||
@ -3162,6 +3169,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI64"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI64"),
|
||||||
"i64",
|
"i64",
|
||||||
"",
|
"",
|
||||||
@ -3180,6 +3188,7 @@ atomic_int! {
|
|||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
stable(feature = "integer_atomics_stable", since = "1.34.0"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU64"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU64"),
|
||||||
"u64",
|
"u64",
|
||||||
"",
|
"",
|
||||||
@ -3197,7 +3206,8 @@ atomic_int! {
|
|||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
|
rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"),
|
||||||
"i128",
|
"i128",
|
||||||
"#![feature(integer_atomics)]\n\n",
|
"#![feature(integer_atomics)]\n\n",
|
||||||
@ -3215,7 +3225,8 @@ atomic_int! {
|
|||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
unstable(feature = "integer_atomics", issue = "99069"),
|
unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
|
rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
|
rustc_const_unstable(feature = "integer_atomics", issue = "99069"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"),
|
||||||
"u128",
|
"u128",
|
||||||
"#![feature(integer_atomics)]\n\n",
|
"#![feature(integer_atomics)]\n\n",
|
||||||
@ -3238,6 +3249,7 @@ macro_rules! atomic_int_ptr_sized {
|
|||||||
stable(feature = "atomic_from", since = "1.23.0"),
|
stable(feature = "atomic_from", since = "1.23.0"),
|
||||||
stable(feature = "atomic_nand", since = "1.27.0"),
|
stable(feature = "atomic_nand", since = "1.27.0"),
|
||||||
rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
|
rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicIsize"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicIsize"),
|
||||||
"isize",
|
"isize",
|
||||||
"",
|
"",
|
||||||
@ -3256,6 +3268,7 @@ macro_rules! atomic_int_ptr_sized {
|
|||||||
stable(feature = "atomic_from", since = "1.23.0"),
|
stable(feature = "atomic_from", since = "1.23.0"),
|
||||||
stable(feature = "atomic_nand", since = "1.27.0"),
|
stable(feature = "atomic_nand", since = "1.27.0"),
|
||||||
rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
|
rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"),
|
||||||
|
rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"),
|
||||||
cfg_attr(not(test), rustc_diagnostic_item = "AtomicUsize"),
|
cfg_attr(not(test), rustc_diagnostic_item = "AtomicUsize"),
|
||||||
"usize",
|
"usize",
|
||||||
"",
|
"",
|
||||||
|
@ -106,6 +106,7 @@ impl<T: Sized> Exclusive<T> {
|
|||||||
|
|
||||||
/// Unwrap the value contained in the `Exclusive`
|
/// Unwrap the value contained in the `Exclusive`
|
||||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
|
#[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn into_inner(self) -> T {
|
pub const fn into_inner(self) -> T {
|
||||||
@ -129,6 +130,7 @@ impl<T: ?Sized> Exclusive<T> {
|
|||||||
/// access to the underlying value, but _pinned_ `Exclusive`s only
|
/// access to the underlying value, but _pinned_ `Exclusive`s only
|
||||||
/// produce _pinned_ access to the underlying value.
|
/// produce _pinned_ access to the underlying value.
|
||||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
|
#[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
|
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
|
||||||
@ -152,6 +154,7 @@ impl<T: ?Sized> Exclusive<T> {
|
|||||||
/// a _pinned mutable_ reference to a `T`. This allows you to skip
|
/// a _pinned mutable_ reference to a `T`. This allows you to skip
|
||||||
/// building an `Exclusive` with [`Exclusive::new`].
|
/// building an `Exclusive` with [`Exclusive::new`].
|
||||||
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
|
#[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
|
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
|
||||||
|
@ -321,7 +321,7 @@ impl<'a> ContextBuilder<'a> {
|
|||||||
/// Creates a ContextBuilder from a Waker.
|
/// Creates a ContextBuilder from a Waker.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "local_waker", issue = "118959")]
|
#[unstable(feature = "local_waker", issue = "118959")]
|
||||||
#[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))]
|
||||||
pub const fn from_waker(waker: &'a Waker) -> Self {
|
pub const fn from_waker(waker: &'a Waker) -> Self {
|
||||||
// SAFETY: LocalWaker is just Waker without thread safety
|
// SAFETY: LocalWaker is just Waker without thread safety
|
||||||
let local_waker = unsafe { transmute(waker) };
|
let local_waker = unsafe { transmute(waker) };
|
||||||
@ -379,7 +379,7 @@ impl<'a> ContextBuilder<'a> {
|
|||||||
/// Builds the `Context`.
|
/// Builds the `Context`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "local_waker", issue = "118959")]
|
#[unstable(feature = "local_waker", issue = "118959")]
|
||||||
#[rustc_const_stable(feature = "const_waker", since = "1.82.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_waker", since = "1.82.0"))]
|
||||||
pub const fn build(self) -> Context<'a> {
|
pub const fn build(self) -> Context<'a> {
|
||||||
let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
|
let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
|
||||||
Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
|
Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
|
||||||
|
@ -47,7 +47,7 @@ use crate::intrinsics::{self, const_eval_select};
|
|||||||
/// order to call it. Since the precompiled standard library is built with full debuginfo and these
|
/// order to call it. Since the precompiled standard library is built with full debuginfo and these
|
||||||
/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
|
/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
|
||||||
/// debuginfo to have a measurable compile-time impact on debug builds.
|
/// debuginfo to have a measurable compile-time impact on debug builds.
|
||||||
#[allow_internal_unstable(const_ub_checks)] // permit this to be called in stably-const fn
|
#[cfg_attr(bootstrap, allow_internal_unstable(const_ub_checks))] // permit this to be called in stably-const fn
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[unstable(feature = "ub_checks", issue = "none")]
|
#[unstable(feature = "ub_checks", issue = "none")]
|
||||||
macro_rules! assert_unsafe_precondition {
|
macro_rules! assert_unsafe_precondition {
|
||||||
@ -64,7 +64,8 @@ macro_rules! assert_unsafe_precondition {
|
|||||||
#[rustc_no_mir_inline]
|
#[rustc_no_mir_inline]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_ptr_is_null, const_ub_checks)] // only for UB checks
|
||||||
const fn precondition_check($($name:$ty),*) {
|
const fn precondition_check($($name:$ty),*) {
|
||||||
if !$e {
|
if !$e {
|
||||||
::core::panicking::panic_nounwind(
|
::core::panicking::panic_nounwind(
|
||||||
@ -90,8 +91,9 @@ pub use intrinsics::ub_checks as check_library_ub;
|
|||||||
///
|
///
|
||||||
/// The intention is to not do that when running in the interpreter, as that one has its own
|
/// The intention is to not do that when running in the interpreter, as that one has its own
|
||||||
/// language UB checks which generally produce better errors.
|
/// language UB checks which generally produce better errors.
|
||||||
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
pub(crate) const fn check_language_ub() -> bool {
|
pub(crate) const fn check_language_ub() -> bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn runtime() -> bool {
|
fn runtime() -> bool {
|
||||||
@ -116,6 +118,7 @@ pub(crate) const fn check_language_ub() -> bool {
|
|||||||
/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
|
/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
|
||||||
/// check is anyway not executed in `const`.
|
/// check is anyway not executed in `const`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
||||||
pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool {
|
pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool {
|
||||||
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
|
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
|
||||||
}
|
}
|
||||||
@ -132,6 +135,7 @@ pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool {
|
|||||||
/// Note that in const-eval this function just returns `true` and therefore must
|
/// Note that in const-eval this function just returns `true` and therefore must
|
||||||
/// only be used with `assert_unsafe_precondition!`, similar to `is_aligned_and_not_null`.
|
/// only be used with `assert_unsafe_precondition!`, similar to `is_aligned_and_not_null`.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
|
||||||
pub(crate) const fn is_nonoverlapping(
|
pub(crate) const fn is_nonoverlapping(
|
||||||
src: *const (),
|
src: *const (),
|
||||||
dst: *const (),
|
dst: *const (),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
|
#![cfg_attr(bootstrap, feature(const_likely))]
|
||||||
#![cfg_attr(bootstrap, feature(strict_provenance))]
|
#![cfg_attr(bootstrap, feature(strict_provenance))]
|
||||||
#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
|
#![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
|
||||||
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||||
@ -22,7 +23,6 @@
|
|||||||
#![feature(const_eval_select)]
|
#![feature(const_eval_select)]
|
||||||
#![feature(const_hash)]
|
#![feature(const_hash)]
|
||||||
#![feature(const_heap)]
|
#![feature(const_heap)]
|
||||||
#![feature(const_likely)]
|
|
||||||
#![feature(const_nonnull_new)]
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_midpoint)]
|
#![feature(const_num_midpoint)]
|
||||||
#![feature(const_option_ext)]
|
#![feature(const_option_ext)]
|
||||||
|
@ -116,7 +116,7 @@ fn to_state(current: StateAndQueue) -> usize {
|
|||||||
|
|
||||||
impl Once {
|
impl Once {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
|
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_once_new", since = "1.32.0"))]
|
||||||
pub const fn new() -> Once {
|
pub const fn new() -> Once {
|
||||||
Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) }
|
Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) }
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ const KEY_SENTVAL: usize = 0;
|
|||||||
const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
|
const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
|
||||||
|
|
||||||
impl LazyKey {
|
impl LazyKey {
|
||||||
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))]
|
||||||
pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> LazyKey {
|
pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> LazyKey {
|
||||||
LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor }
|
LazyKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor }
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ struct Value<T: 'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Storage<T> {
|
impl<T: 'static> Storage<T> {
|
||||||
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))]
|
||||||
pub const fn new() -> Storage<T> {
|
pub const fn new() -> Storage<T> {
|
||||||
Storage { key: LazyKey::new(Some(destroy_value::<T>)), marker: PhantomData }
|
Storage { key: LazyKey::new(Some(destroy_value::<T>)), marker: PhantomData }
|
||||||
}
|
}
|
||||||
|
@ -237,7 +237,7 @@ impl<T: 'static> LocalKey<T> {
|
|||||||
reason = "recently added to create a key",
|
reason = "recently added to create a key",
|
||||||
issue = "none"
|
issue = "none"
|
||||||
)]
|
)]
|
||||||
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
|
#[cfg_attr(bootstrap, rustc_const_unstable(feature = "thread_local_internals", issue = "none"))]
|
||||||
pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> {
|
pub const unsafe fn new(inner: fn(Option<&mut Option<T>>) -> *const T) -> LocalKey<T> {
|
||||||
LocalKey { inner }
|
LocalKey { inner }
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ use arrayvec::ArrayVec;
|
|||||||
use rustc_ast::MetaItemInner;
|
use rustc_ast::MetaItemInner;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||||
use rustc_const_eval::const_eval::is_unstable_const_fn;
|
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||||
@ -641,12 +640,11 @@ impl Item {
|
|||||||
asyncness: ty::Asyncness,
|
asyncness: ty::Asyncness,
|
||||||
) -> hir::FnHeader {
|
) -> hir::FnHeader {
|
||||||
let sig = tcx.fn_sig(def_id).skip_binder();
|
let sig = tcx.fn_sig(def_id).skip_binder();
|
||||||
let constness =
|
let constness = if tcx.is_const_fn_raw(def_id) {
|
||||||
if tcx.is_const_fn(def_id) || is_unstable_const_fn(tcx, def_id).is_some() {
|
hir::Constness::Const
|
||||||
hir::Constness::Const
|
} else {
|
||||||
} else {
|
hir::Constness::NotConst
|
||||||
hir::Constness::NotConst
|
};
|
||||||
};
|
|
||||||
let asyncness = match asyncness {
|
let asyncness = match asyncness {
|
||||||
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
|
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
|
||||||
ty::Asyncness::No => hir::IsAsync::NotAsync,
|
ty::Asyncness::No => hir::IsAsync::NotAsync,
|
||||||
@ -664,9 +662,7 @@ impl Item {
|
|||||||
safety
|
safety
|
||||||
},
|
},
|
||||||
abi,
|
abi,
|
||||||
constness: if tcx.is_const_fn(def_id)
|
constness: if tcx.is_const_fn_raw(def_id) {
|
||||||
|| is_unstable_const_fn(tcx, def_id).is_some()
|
|
||||||
{
|
|
||||||
hir::Constness::Const
|
hir::Constness::Const
|
||||||
} else {
|
} else {
|
||||||
hir::Constness::NotConst
|
hir::Constness::NotConst
|
||||||
|
@ -1010,7 +1010,9 @@ fn render_stability_since_raw_with_extra(
|
|||||||
// don't display const unstable if entirely unstable
|
// don't display const unstable if entirely unstable
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let unstable = if let Some(n) = issue {
|
let unstable = if let Some(n) = issue
|
||||||
|
&& let Some(feature) = feature
|
||||||
|
{
|
||||||
format!(
|
format!(
|
||||||
"<a \
|
"<a \
|
||||||
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
|
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
|
||||||
|
@ -37,7 +37,6 @@ extern crate rustc_abi;
|
|||||||
extern crate rustc_ast;
|
extern crate rustc_ast;
|
||||||
extern crate rustc_ast_pretty;
|
extern crate rustc_ast_pretty;
|
||||||
extern crate rustc_attr;
|
extern crate rustc_attr;
|
||||||
extern crate rustc_const_eval;
|
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
extern crate rustc_driver;
|
extern crate rustc_driver;
|
||||||
extern crate rustc_errors;
|
extern crate rustc_errors;
|
||||||
|
@ -89,10 +89,4 @@ impl Bar {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const2", since = "1.2.0")]
|
#[rustc_const_stable(feature = "const2", since = "1.2.0")]
|
||||||
pub const fn stable_impl() -> u32 { 42 }
|
pub const fn stable_impl() -> u32 { 42 }
|
||||||
|
|
||||||
// Show const-stability even for unstable functions.
|
|
||||||
//@ matches 'foo/struct.Bar.html' '//span[@class="since"]' '^const: 1.3.0$'
|
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
|
||||||
#[rustc_const_stable(feature = "const3", since = "1.3.0")]
|
|
||||||
pub const fn const_stable_unstable() -> u32 { 42 }
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ struct Value;
|
|||||||
|
|
||||||
static settings_dir: String = format!("");
|
static settings_dir: String = format!("");
|
||||||
//~^ ERROR cannot call non-const fn
|
//~^ ERROR cannot call non-const fn
|
||||||
//~| ERROR is not yet stable as a const
|
|
||||||
|
|
||||||
fn from_string(_: String) -> Value {
|
fn from_string(_: String) -> Value {
|
||||||
Value
|
Value
|
||||||
|
@ -1,12 +1,3 @@
|
|||||||
error: `Arguments::<'a>::new_const` is not yet stable as a const fn
|
|
||||||
--> $DIR/issue-64453.rs:4:31
|
|
||||||
|
|
|
||||||
LL | static settings_dir: String = format!("");
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: add `#![feature(const_fmt_arguments_new)]` to the crate attributes to enable
|
|
||||||
= note: this error originates in the macro `$crate::__export::format_args` which comes from the expansion of the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `format` in statics
|
error[E0015]: cannot call non-const fn `format` in statics
|
||||||
--> $DIR/issue-64453.rs:4:31
|
--> $DIR/issue-64453.rs:4:31
|
||||||
|
|
|
|
||||||
@ -18,7 +9,7 @@ LL | static settings_dir: String = format!("");
|
|||||||
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0507]: cannot move out of static item `settings_dir`
|
error[E0507]: cannot move out of static item `settings_dir`
|
||||||
--> $DIR/issue-64453.rs:14:37
|
--> $DIR/issue-64453.rs:13:37
|
||||||
|
|
|
|
||||||
LL | let settings_data = from_string(settings_dir);
|
LL | let settings_data = from_string(settings_dir);
|
||||||
| ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
|
| ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
|
||||||
@ -28,7 +19,7 @@ help: consider cloning the value if the performance cost is acceptable
|
|||||||
LL | let settings_data = from_string(settings_dir.clone());
|
LL | let settings_data = from_string(settings_dir.clone());
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0015, E0507.
|
Some errors have detailed explanations: E0015, E0507.
|
||||||
For more information about an error, try `rustc --explain E0015`.
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#![feature(staged_api, rustc_attrs, intrinsics)]
|
|
||||||
#![stable(since="1.0.0", feature = "stable")]
|
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
#[unstable(feature = "unstable", issue = "42")]
|
|
||||||
#[rustc_const_stable(feature = "stable", since = "1.0.0")]
|
|
||||||
#[rustc_nounwind]
|
|
||||||
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unstable(feature = "unstable", issue = "42")]
|
|
||||||
#[rustc_const_stable(feature = "stable", since = "1.0.0")]
|
|
||||||
pub const fn some_unstable_fn() {}
|
|
26
tests/ui/consts/auxiliary/unstable_intrinsic.rs
Normal file
26
tests/ui/consts/auxiliary/unstable_intrinsic.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#![feature(staged_api, rustc_attrs, intrinsics)]
|
||||||
|
#![stable(since="1.0.0", feature = "stable")]
|
||||||
|
|
||||||
|
#[stable(since="1.0.0", feature = "stable")]
|
||||||
|
pub mod old_way {
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[unstable(feature = "unstable", issue = "42")]
|
||||||
|
pub fn size_of_val<T>(x: *const T) -> usize;
|
||||||
|
|
||||||
|
#[unstable(feature = "unstable", issue = "42")]
|
||||||
|
#[rustc_const_unstable(feature = "unstable", issue = "42")]
|
||||||
|
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(since="1.0.0", feature = "stable")]
|
||||||
|
pub mod new_way {
|
||||||
|
#[unstable(feature = "unstable", issue = "42")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
|
||||||
|
#[unstable(feature = "unstable", issue = "42")]
|
||||||
|
#[rustc_const_unstable(feature = "unstable", issue = "42")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
we're apparently really bad at it",
|
we're apparently really bad at it",
|
||||||
issue = "none")]
|
issue = "none")]
|
||||||
|
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api, foo)]
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature="foo", issue = "none")]
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
||||||
@ -11,7 +11,7 @@ const fn foo() -> u32 { 42 }
|
|||||||
|
|
||||||
fn meh() -> u32 { 42 }
|
fn meh() -> u32 { 42 }
|
||||||
|
|
||||||
const fn bar() -> u32 { foo() } //~ ERROR `foo` is not yet stable as a const fn
|
const fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
|
||||||
|
|
||||||
fn a() {
|
fn a() {
|
||||||
let _: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed
|
let _: &'static u32 = &foo(); //~ ERROR temporary value dropped while borrowed
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
error: `foo` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
|
||||||
--> $DIR/dont_promote_unstable_const_fn.rs:14:25
|
--> $DIR/dont_promote_unstable_const_fn.rs:14:25
|
||||||
|
|
|
|
||||||
LL | const fn bar() -> u32 { foo() }
|
LL | const fn bar() -> u32 { foo() }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= help: add `#![feature(foo)]` to the crate attributes to enable
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo)]
|
||||||
|
LL | const fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/dont_promote_unstable_const_fn.rs:17:28
|
--> $DIR/dont_promote_unstable_const_fn.rs:17:28
|
||||||
|
@ -11,8 +11,11 @@
|
|||||||
#[repr(simd)] struct f32x4([f32; 4]);
|
#[repr(simd)] struct f32x4([f32; 4]);
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[stable(feature = "foo", since = "1.3.37")]
|
||||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||||
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
|
||||||
|
|
||||||
|
#[stable(feature = "foo", since = "1.3.37")]
|
||||||
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
|
||||||
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
fn simd_extract<T, U>(x: T, idx: u32) -> U;
|
||||||
}
|
}
|
||||||
|
76
tests/ui/consts/const-unstable-intrinsic.rs
Normal file
76
tests/ui/consts/const-unstable-intrinsic.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//! Ensure that unstable intrinsics can actually not be called,
|
||||||
|
//! neither within a crate nor cross-crate.
|
||||||
|
//@ aux-build:unstable_intrinsic.rs
|
||||||
|
#![feature(staged_api, rustc_attrs, intrinsics)]
|
||||||
|
#![stable(since="1.0.0", feature = "stable")]
|
||||||
|
#![feature(local)]
|
||||||
|
|
||||||
|
extern crate unstable_intrinsic;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const_main();
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn const_main() {
|
||||||
|
let x = 42;
|
||||||
|
unsafe {
|
||||||
|
unstable_intrinsic::old_way::size_of_val(&x);
|
||||||
|
//~^ERROR: unstable library feature 'unstable'
|
||||||
|
//~|ERROR: cannot call non-const intrinsic
|
||||||
|
unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||||
|
//~^ERROR: unstable library feature 'unstable'
|
||||||
|
//~|ERROR: not yet stable as a const intrinsic
|
||||||
|
unstable_intrinsic::new_way::size_of_val(&x);
|
||||||
|
//~^ERROR: unstable library feature 'unstable'
|
||||||
|
//~|ERROR: cannot be (indirectly) exposed to stable
|
||||||
|
unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||||
|
//~^ERROR: unstable library feature 'unstable'
|
||||||
|
//~|ERROR: not yet stable as a const intrinsic
|
||||||
|
|
||||||
|
old_way::size_of_val(&x);
|
||||||
|
//~^ERROR: cannot call non-const intrinsic
|
||||||
|
old_way::min_align_of_val(&x);
|
||||||
|
//~^ERROR: cannot use `#[feature(local)]`
|
||||||
|
new_way::size_of_val(&x);
|
||||||
|
//~^ERROR: cannot be (indirectly) exposed to stable
|
||||||
|
new_way::min_align_of_val(&x);
|
||||||
|
//~^ERROR: cannot use `#[feature(local)]`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(since="1.0.0", feature = "stable")]
|
||||||
|
pub mod old_way {
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[unstable(feature = "local", issue = "42")]
|
||||||
|
pub fn size_of_val<T>(x: *const T) -> usize;
|
||||||
|
|
||||||
|
#[unstable(feature = "local", issue = "42")]
|
||||||
|
#[rustc_const_unstable(feature = "local", issue = "42")]
|
||||||
|
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(since="1.0.0", feature = "stable")]
|
||||||
|
pub mod new_way {
|
||||||
|
#[unstable(feature = "local", issue = "42")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
|
||||||
|
#[unstable(feature = "local", issue = "42")]
|
||||||
|
#[rustc_const_unstable(feature = "local", issue = "42")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||||
|
#[inline]
|
||||||
|
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
||||||
|
// Const stability attributes are not inherited from parent items.
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { copy(src, dst, count) }
|
||||||
|
//~^ ERROR cannot call non-const intrinsic
|
||||||
|
}
|
127
tests/ui/consts/const-unstable-intrinsic.stderr
Normal file
127
tests/ui/consts/const-unstable-intrinsic.stderr
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
error[E0658]: use of unstable library feature 'unstable'
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::old_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: use of unstable library feature 'unstable'
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:20:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: use of unstable library feature 'unstable'
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:23:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::new_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error[E0658]: use of unstable library feature 'unstable'
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
|
error: cannot call non-const intrinsic `size_of_val` in constant functions
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::old_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:20:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::old_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:23:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::new_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||||
|
|
||||||
|
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||||
|
|
|
||||||
|
LL | unstable_intrinsic::new_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: cannot call non-const intrinsic `size_of_val` in constant functions
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:30:9
|
||||||
|
|
|
||||||
|
LL | old_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:32:9
|
||||||
|
|
|
||||||
|
LL | old_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn const_main() {
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(local)]
|
||||||
|
LL | const fn const_main() {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:34:9
|
||||||
|
|
|
||||||
|
LL | new_way::size_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
|
||||||
|
|
||||||
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:36:9
|
||||||
|
|
|
||||||
|
LL | new_way::min_align_of_val(&x);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn const_main() {
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(local)]
|
||||||
|
LL | const fn const_main() {
|
||||||
|
|
|
||||||
|
|
||||||
|
error: cannot call non-const intrinsic `copy` in constant functions
|
||||||
|
--> $DIR/const-unstable-intrinsic.rs:74:14
|
||||||
|
|
|
||||||
|
LL | unsafe { copy(src, dst, count) }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 13 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
@ -5,9 +5,11 @@
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[stable(feature = "dummy", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||||
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
|
|
||||||
|
#[stable(feature = "dummy", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/copy-intrinsic.rs:28:5
|
--> $DIR/copy-intrinsic.rs:30:5
|
||||||
|
|
|
|
||||||
LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1);
|
LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/copy-intrinsic.rs:37:5
|
--> $DIR/copy-intrinsic.rs:39:5
|
||||||
|
|
|
|
||||||
LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
|
LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/copy-intrinsic.rs:44:5
|
--> $DIR/copy-intrinsic.rs:46:5
|
||||||
|
|
|
|
||||||
LL | copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
LL | copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/copy-intrinsic.rs:50:5
|
--> $DIR/copy-intrinsic.rs:52:5
|
||||||
|
|
|
|
||||||
LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
LL | copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
#![feature(intrinsics, staged_api)]
|
|
||||||
#![stable(feature = "core", since = "1.6.0")]
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
|
|
||||||
// Const stability attributes are not inherited from parent items.
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { copy(src, dst, count) }
|
|
||||||
//~^ ERROR cannot call non-const fn
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,11 +0,0 @@
|
|||||||
error[E0015]: cannot call non-const fn `copy::copy::<T>` in constant functions
|
|
||||||
--> $DIR/intrinsic_without_const_stab.rs:13:14
|
|
||||||
|
|
|
||||||
LL | unsafe { copy(src, dst, count) }
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
|
@ -1,15 +0,0 @@
|
|||||||
#![feature(intrinsics, staged_api)]
|
|
||||||
#![stable(feature = "core", since = "1.6.0")]
|
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
|
|
||||||
#[inline]
|
|
||||||
pub const unsafe fn stuff<T>(src: *const T, dst: *mut T, count: usize) {
|
|
||||||
unsafe { copy(src, dst, count) } //~ ERROR cannot call non-const fn
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,11 +0,0 @@
|
|||||||
error[E0015]: cannot call non-const fn `copy::<T>` in constant functions
|
|
||||||
--> $DIR/intrinsic_without_const_stab_fail.rs:12:14
|
|
||||||
|
|
|
||||||
LL | unsafe { copy(src, dst, count) }
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
|
@ -5,7 +5,7 @@
|
|||||||
issue = "none")]
|
issue = "none")]
|
||||||
|
|
||||||
#![feature(foo, foo2)]
|
#![feature(foo, foo2)]
|
||||||
#![feature(const_async_blocks, staged_api)]
|
#![feature(const_async_blocks, staged_api, rustc_attrs)]
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature="foo", issue = "none")]
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
||||||
@ -14,33 +14,55 @@ const fn foo() -> u32 { 42 }
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
|
const fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
|
||||||
|
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature = "foo2", issue = "none")]
|
||||||
const fn foo2() -> u32 { 42 }
|
const fn foo2() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
|
const fn bar2() -> u32 { foo2() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// conformity is required
|
// conformity is required
|
||||||
const fn bar3() -> u32 {
|
const fn bar3() -> u32 {
|
||||||
let x = async { 13 };
|
let x = async { 13 };
|
||||||
//~^ ERROR const-stable function cannot use `#[feature(const_async_blocks)]`
|
//~^ ERROR cannot use `#[feature(const_async_blocks)]`
|
||||||
foo()
|
foo()
|
||||||
//~^ ERROR is not yet stable as a const fn
|
//~^ ERROR cannot use `#[feature(foo)]`
|
||||||
}
|
}
|
||||||
|
|
||||||
// check whether this function cannot be called even with the feature gate active
|
// check whether this function cannot be called even with the feature gate active
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature = "foo2", issue = "none")]
|
||||||
const fn foo2_gated() -> u32 { 42 }
|
const fn foo2_gated() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
|
const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
|
// Functions without any attribute are checked like stable functions,
|
||||||
|
// even if they are in a stable module.
|
||||||
|
mod stable {
|
||||||
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
}
|
||||||
|
// And same for const-unstable functions that are marked as "stable_indirect".
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
||||||
|
#[rustc_const_stable_indirect]
|
||||||
|
const fn stable_indirect() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
|
// These functiuons *can* be called from fully stable functions.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
const fn bar2_gated_exposed() -> u32 {
|
||||||
|
stable::bar2_gated_stable_indirect() + stable_indirect()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,51 +1,127 @@
|
|||||||
error: `foo` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
|
||||||
--> $DIR/min_const_fn_libstd_stability.rs:17:25
|
--> $DIR/min_const_fn_libstd_stability.rs:17:25
|
||||||
|
|
|
|
||||||
LL | const fn bar() -> u32 { foo() }
|
LL | const fn bar() -> u32 { foo() }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo)]
|
||||||
|
LL | const fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_fn_libstd_stability.rs:25:26
|
--> $DIR/min_const_fn_libstd_stability.rs:26:26
|
||||||
|
|
|
|
||||||
LL | const fn bar2() -> u32 { foo2() }
|
LL | const fn bar2() -> u32 { foo2() }
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn bar2() -> u32 { foo2() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const fn bar2() -> u32 { foo2() }
|
||||||
|
|
|
||||||
|
|
||||||
error: const-stable function cannot use `#[feature(const_async_blocks)]`
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]`
|
||||||
--> $DIR/min_const_fn_libstd_stability.rs:31:13
|
--> $DIR/min_const_fn_libstd_stability.rs:32:13
|
||||||
|
|
|
|
||||||
LL | let x = async { 13 };
|
LL | let x = async { 13 };
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: if the function is not (yet) meant to be stable, make this function unstably const
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
|
||||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
LL | const fn bar3() -> u32 {
|
LL | const fn bar3() -> u32 {
|
||||||
|
|
|
|
||||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (but requires team approval)
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
|
||||||
LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
|
LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
|
||||||
LL | const fn bar3() -> u32 {
|
LL | const fn bar3() -> u32 {
|
||||||
|
|
|
|
||||||
|
|
||||||
error: `foo` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
|
||||||
--> $DIR/min_const_fn_libstd_stability.rs:33:5
|
--> $DIR/min_const_fn_libstd_stability.rs:34:5
|
||||||
|
|
|
|
||||||
LL | foo()
|
LL | foo()
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn bar3() -> u32 {
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo)]
|
||||||
|
LL | const fn bar3() -> u32 {
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2_gated` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_fn_libstd_stability.rs:44:32
|
--> $DIR/min_const_fn_libstd_stability.rs:46:32
|
||||||
|
|
|
|
||||||
LL | const fn bar2_gated() -> u32 { foo2_gated() }
|
LL | const fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
|
--> $DIR/min_const_fn_libstd_stability.rs:53:63
|
||||||
|
|
|
||||||
|
LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
|
--> $DIR/min_const_fn_libstd_stability.rs:59:37
|
||||||
|
|
|
||||||
|
LL | const fn stable_indirect() -> u32 { foo2_gated() }
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const fn stable_indirect() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const fn stable_indirect() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
@ -13,24 +13,26 @@ const unsafe fn foo() -> u32 { 42 }
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR not yet stable as a const fn
|
const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR cannot use `#[feature(foo)]`
|
||||||
|
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature = "foo2", issue = "none")]
|
||||||
const unsafe fn foo2() -> u32 { 42 }
|
const unsafe fn foo2() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR not yet stable as a const fn
|
const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
// check whether this function cannot be called even with the feature gate active
|
// check whether this function cannot be called even with the feature gate active
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature = "foo2", issue = "none")]
|
||||||
const unsafe fn foo2_gated() -> u32 { 42 }
|
const unsafe fn foo2_gated() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
||||||
//~^ ERROR not yet stable as a const fn
|
//~^ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,26 +1,56 @@
|
|||||||
error: `foo` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41
|
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:16:41
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
|
LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo)]
|
||||||
|
LL | const unsafe fn bar() -> u32 { unsafe { foo() } }
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:24:42
|
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:25:42
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
|
LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } }
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2_gated` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:33:48
|
--> $DIR/min_const_unsafe_fn_libstd_stability.rs:35:48
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } }
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -13,23 +13,25 @@ const fn foo() -> u32 { 42 }
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar() -> u32 { foo() } //~ ERROR not yet stable as a const fn
|
const unsafe fn bar() -> u32 { foo() } //~ ERROR cannot use `#[feature(foo)]`
|
||||||
|
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature="foo2", issue = "none")]
|
||||||
const fn foo2() -> u32 { 42 }
|
const fn foo2() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar2() -> u32 { foo2() } //~ ERROR not yet stable as a const fn
|
const unsafe fn bar2() -> u32 { foo2() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
// check whether this function cannot be called even with the feature gate active
|
// check whether this function cannot be called even with the feature gate active
|
||||||
#[unstable(feature = "foo2", issue = "none")]
|
#[unstable(feature = "foo2", issue = "none")]
|
||||||
|
#[rustc_const_unstable(feature="foo2", issue = "none")]
|
||||||
const fn foo2_gated() -> u32 { 42 }
|
const fn foo2_gated() -> u32 { 42 }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||||
// can't call non-min_const_fn
|
// can't call non-min_const_fn
|
||||||
const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR not yet stable as a const fn
|
const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR cannot use `#[feature(foo2)]`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,26 +1,56 @@
|
|||||||
error: `foo` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32
|
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:16:32
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar() -> u32 { foo() }
|
LL | const unsafe fn bar() -> u32 { foo() }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo)]
|
||||||
|
LL | const unsafe fn bar() -> u32 { foo() }
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:24:33
|
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:25:33
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar2() -> u32 { foo2() }
|
LL | const unsafe fn bar2() -> u32 { foo2() }
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar2() -> u32 { foo2() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const unsafe fn bar2() -> u32 { foo2() }
|
||||||
|
|
|
||||||
|
|
||||||
error: `foo2_gated` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(foo2)]`
|
||||||
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:33:39
|
--> $DIR/min_const_unsafe_fn_libstd_stability2.rs:35:39
|
||||||
|
|
|
|
||||||
LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
|
LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||||
|
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(foo2)]
|
||||||
|
LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() }
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api, rustc_attrs)]
|
||||||
#![stable(feature = "foo", since = "1.0.0")]
|
#![stable(feature = "foo", since = "1.0.0")]
|
||||||
|
|
||||||
#[stable(feature = "foo", since = "1.0.0")]
|
#[stable(feature = "foo", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
||||||
pub fn foo() {}
|
pub fn foo() {}
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
|
||||||
#[stable(feature = "bar", since = "1.0.0")]
|
#[stable(feature = "bar", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
||||||
pub fn bar() {}
|
pub fn bar() {}
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
|
||||||
#[stable(feature = "potato", since = "1.0.0")]
|
#[stable(feature = "potato", since = "1.0.0")]
|
||||||
pub struct Potato;
|
pub struct Potato;
|
||||||
@ -19,23 +19,23 @@ impl Potato {
|
|||||||
#[stable(feature = "salad", since = "1.0.0")]
|
#[stable(feature = "salad", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_salad", issue = "none")]
|
#[rustc_const_unstable(feature = "const_salad", issue = "none")]
|
||||||
pub fn salad(&self) -> &'static str { "mmmmmm" }
|
pub fn salad(&self) -> &'static str { "mmmmmm" }
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
|
||||||
#[stable(feature = "roasted", since = "1.0.0")]
|
#[stable(feature = "roasted", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_roasted", issue = "none")]
|
#[rustc_const_unstable(feature = "const_roasted", issue = "none")]
|
||||||
pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "bar", since = "1.0.0")]
|
#[stable(feature = "bar", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
||||||
pub extern "C" fn bar_c() {}
|
pub extern "C" fn bar_c() {}
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
|
||||||
#[stable(feature = "foo", since = "1.0.0")]
|
#[stable(feature = "foo", since = "1.0.0")]
|
||||||
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
||||||
pub extern "C" fn foo_c() {}
|
pub extern "C" fn foo_c() {}
|
||||||
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
|
||||||
|
|
||||||
#[stable(feature = "foobar", since = "1.0.0")]
|
#[stable(feature = "foobar", since = "1.0.0")]
|
||||||
@ -45,3 +45,20 @@ pub const fn foobar() {}
|
|||||||
#[stable(feature = "barfoo", since = "1.0.0")]
|
#[stable(feature = "barfoo", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
pub const fn barfoo() {}
|
pub const fn barfoo() {}
|
||||||
|
|
||||||
|
// `rustc_const_stable` also requires the function to be stable.
|
||||||
|
|
||||||
|
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
|
const fn barfoo_unmarked() {}
|
||||||
|
//~^ ERROR can only be applied to functions that are declared `#[stable]`
|
||||||
|
|
||||||
|
#[unstable(feature = "unstable", issue = "none")]
|
||||||
|
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
|
pub const fn barfoo_unstable() {}
|
||||||
|
//~^ ERROR can only be applied to functions that are declared `#[stable]`
|
||||||
|
|
||||||
|
// `#[rustc_const_stable_indirect]` also requires a const fn
|
||||||
|
#[rustc_const_stable_indirect]
|
||||||
|
#[unstable(feature = "unstable", issue = "none")]
|
||||||
|
pub fn not_a_const_fn() {}
|
||||||
|
//~^ ERROR require the function or method to be `const`
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:7:1
|
--> $DIR/rustc-const-stability-require-const.rs:7:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
|
||||||
| -------------------------------------------------------------- attribute specified here
|
|
||||||
LL | pub fn foo() {}
|
LL | pub fn foo() {}
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -12,11 +10,9 @@ help: make the function or method const
|
|||||||
LL | pub fn foo() {}
|
LL | pub fn foo() {}
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:12:1
|
--> $DIR/rustc-const-stability-require-const.rs:12:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
|
||||||
| ------------------------------------------------------------- attribute specified here
|
|
||||||
LL | pub fn bar() {}
|
LL | pub fn bar() {}
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -26,11 +22,9 @@ help: make the function or method const
|
|||||||
LL | pub fn bar() {}
|
LL | pub fn bar() {}
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:21:5
|
--> $DIR/rustc-const-stability-require-const.rs:21:5
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")]
|
|
||||||
| ---------------------------------------------------------------- attribute specified here
|
|
||||||
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
|
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -40,11 +34,9 @@ help: make the function or method const
|
|||||||
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
|
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:26:5
|
--> $DIR/rustc-const-stability-require-const.rs:26:5
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
|
|
||||||
| ------------------------------------------------------------------ attribute specified here
|
|
||||||
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -54,11 +46,9 @@ help: make the function or method const
|
|||||||
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:32:1
|
--> $DIR/rustc-const-stability-require-const.rs:32:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
|
|
||||||
| ------------------------------------------------------------- attribute specified here
|
|
||||||
LL | pub extern "C" fn bar_c() {}
|
LL | pub extern "C" fn bar_c() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -68,11 +58,9 @@ help: make the function or method const
|
|||||||
LL | pub extern "C" fn bar_c() {}
|
LL | pub extern "C" fn bar_c() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
--> $DIR/rustc-const-stability-require-const.rs:37:1
|
--> $DIR/rustc-const-stability-require-const.rs:37:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
|
||||||
| -------------------------------------------------------------- attribute specified here
|
|
||||||
LL | pub extern "C" fn foo_c() {}
|
LL | pub extern "C" fn foo_c() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
@ -82,5 +70,33 @@ help: make the function or method const
|
|||||||
LL | pub extern "C" fn foo_c() {}
|
LL | pub extern "C" fn foo_c() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
|
||||||
|
--> $DIR/rustc-const-stability-require-const.rs:52:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
|
| ---------------------------------------------------------------- attribute specified here
|
||||||
|
LL | const fn barfoo_unmarked() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]`
|
||||||
|
--> $DIR/rustc-const-stability-require-const.rs:57:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
|
| ---------------------------------------------------------------- attribute specified here
|
||||||
|
LL | pub const fn barfoo_unstable() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||||
|
--> $DIR/rustc-const-stability-require-const.rs:63:1
|
||||||
|
|
|
||||||
|
LL | pub fn not_a_const_fn() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: make the function or method const
|
||||||
|
--> $DIR/rustc-const-stability-require-const.rs:63:1
|
||||||
|
|
|
||||||
|
LL | pub fn not_a_const_fn() {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 9 previous errors
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
//@ aux-build:unstable_but_const_stable.rs
|
|
||||||
|
|
||||||
extern crate unstable_but_const_stable;
|
|
||||||
use unstable_but_const_stable::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
some_unstable_fn(); //~ERROR use of unstable library feature
|
|
||||||
unsafe { write_bytes(4 as *mut u8, 0, 0) }; //~ERROR use of unstable library feature
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn const_main() {
|
|
||||||
some_unstable_fn(); //~ERROR use of unstable library feature
|
|
||||||
unsafe { write_bytes(4 as *mut u8, 0, 0) }; //~ERROR use of unstable library feature
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
error[E0658]: use of unstable library feature 'unstable'
|
|
||||||
--> $DIR/unstable-const-stable.rs:7:5
|
|
||||||
|
|
|
||||||
LL | some_unstable_fn();
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
|
||||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error[E0658]: use of unstable library feature 'unstable'
|
|
||||||
--> $DIR/unstable-const-stable.rs:8:14
|
|
||||||
|
|
|
||||||
LL | unsafe { write_bytes(4 as *mut u8, 0, 0) };
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
|
||||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error[E0658]: use of unstable library feature 'unstable'
|
|
||||||
--> $DIR/unstable-const-stable.rs:12:5
|
|
||||||
|
|
|
||||||
LL | some_unstable_fn();
|
|
||||||
| ^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
|
||||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error[E0658]: use of unstable library feature 'unstable'
|
|
||||||
--> $DIR/unstable-const-stable.rs:13:14
|
|
||||||
|
|
|
||||||
LL | unsafe { write_bytes(4 as *mut u8, 0, 0) };
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
|
|
||||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,3 +1,17 @@
|
|||||||
|
error: can't mark as unstable using an already stable feature
|
||||||
|
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
||||||
|
LL | const fn my_fun() {}
|
||||||
|
| -------------------- the stability attribute annotates this item
|
||||||
|
|
|
||||||
|
help: consider removing the attribute
|
||||||
|
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: can't mark as unstable using an already stable feature
|
error: can't mark as unstable using an already stable feature
|
||||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
||||||
|
|
|
|
||||||
@ -13,19 +27,5 @@ help: consider removing the attribute
|
|||||||
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: can't mark as unstable using an already stable feature
|
|
||||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
|
||||||
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
|
||||||
LL | const fn my_fun() {}
|
|
||||||
| -------------------- the stability attribute annotates this item
|
|
||||||
|
|
|
||||||
help: consider removing the attribute
|
|
||||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
|
||||||
|
|
|
||||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const fn nothing(){}
|
|||||||
#[rustc_const_stable(since = "1.0", feature = "const_hey")]
|
#[rustc_const_stable(since = "1.0", feature = "const_hey")]
|
||||||
pub const fn hey() {
|
pub const fn hey() {
|
||||||
const_eval_select((), nothing, log);
|
const_eval_select((), nothing, log);
|
||||||
//~^ ERROR `const_eval_select` is not yet stable as a const fn
|
//~^ ERROR cannot use `#[feature(const_eval_select)]`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
error: `const_eval_select` is not yet stable as a const fn
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_eval_select)]`
|
||||||
--> $DIR/const-eval-select-stability.rs:17:5
|
--> $DIR/const-eval-select-stability.rs:17:5
|
||||||
|
|
|
|
||||||
LL | const_eval_select((), nothing, log);
|
LL | const_eval_select((), nothing, log);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: const-stable functions can only call other const-stable functions
|
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||||
|
|
|
||||||
|
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||||
|
LL | pub const fn hey() {
|
||||||
|
|
|
||||||
|
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||||
|
|
|
||||||
|
LL + #[rustc_allow_const_fn_unstable(const_eval_select)]
|
||||||
|
LL | pub const fn hey() {
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -14,4 +14,3 @@ pub const fn foobar() -> u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const VAR: u32 = foobar();
|
const VAR: u32 = foobar();
|
||||||
//~^ ERROR: `foobar` is not yet stable as a const fn
|
|
||||||
|
@ -4,13 +4,5 @@ error: feature `const_bar` implying `const_foobar` does not exist
|
|||||||
LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")]
|
LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `foobar` is not yet stable as a const fn
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/const-stability-attribute-implies-missing.rs:16:18
|
|
||||||
|
|
|
||||||
LL | const VAR: u32 = foobar();
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: add `#![feature(const_foobar)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//@ compile-flags: -Znext-solver
|
//@ compile-flags: -Znext-solver
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
|
#![feature(const_trait_impl, effects, rustc_attrs, intrinsics)] //~ WARN the feature `effects` is incomplete
|
||||||
#![stable(feature = "stable", since = "1.0.0")]
|
#![stable(feature = "stable", since = "1.0.0")]
|
||||||
|
|
||||||
#[stable(feature = "stable", since = "1.0.0")]
|
#[stable(feature = "stable", since = "1.0.0")]
|
||||||
@ -31,4 +31,15 @@ impl const Bar for Foo {
|
|||||||
fn fun() {}
|
fn fun() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "stable", since = "1.0.0")]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
//~^ ERROR function has missing const stability attribute
|
||||||
|
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[stable(feature = "stable", since = "1.0.0")]
|
||||||
|
#[rustc_const_stable_indirect]
|
||||||
|
pub fn min_align_of_val<T>(x: *const T) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/missing-const-stability.rs:3:30
|
--> $DIR/missing-const-stability.rs:3:30
|
||||||
|
|
|
|
||||||
LL | #![feature(const_trait_impl, effects)]
|
LL | #![feature(const_trait_impl, effects, rustc_attrs, intrinsics)]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||||
@ -22,11 +22,17 @@ LL | | fn fun() {}
|
|||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
|
error: function has missing const stability attribute
|
||||||
|
--> $DIR/missing-const-stability.rs:36:1
|
||||||
|
|
|
||||||
|
LL | pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: associated function has missing const stability attribute
|
error: associated function has missing const stability attribute
|
||||||
--> $DIR/missing-const-stability.rs:16:5
|
--> $DIR/missing-const-stability.rs:16:5
|
||||||
|
|
|
|
||||||
LL | pub const fn foo() {}
|
LL | pub const fn foo() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 3 previous errors; 1 warning emitted
|
error: aborting due to 4 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ trait Copy {}
|
|||||||
impl Copy for bool {}
|
impl Copy for bool {}
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[stable(feature = "test", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||||
fn unreachable() -> !;
|
fn unreachable() -> !;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ trait Copy {}
|
|||||||
impl Copy for bool {}
|
impl Copy for bool {}
|
||||||
|
|
||||||
extern "rust-intrinsic" {
|
extern "rust-intrinsic" {
|
||||||
|
#[stable(feature = "test", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
#[rustc_const_stable(feature = "test", since = "1.0.0")]
|
||||||
fn unreachable() -> !;
|
fn unreachable() -> !;
|
||||||
}
|
}
|
||||||
|
@ -19,3 +19,12 @@ pub struct Unstable;
|
|||||||
impl const MyTrait for Unstable {
|
impl const MyTrait for Unstable {
|
||||||
fn func() {}
|
fn func() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub struct Unstable2;
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "unstable2", issue = "none")]
|
||||||
|
impl const MyTrait for Unstable2 {
|
||||||
|
fn func() {}
|
||||||
|
}
|
||||||
|
@ -515,7 +515,7 @@ trait StructuralPartialEq {}
|
|||||||
|
|
||||||
const fn drop<T: ~const Destruct>(_: T) {}
|
const fn drop<T: ~const Destruct>(_: T) {}
|
||||||
|
|
||||||
#[rustc_const_stable(feature = "const_eval_select", since = "1.0.0")]
|
#[rustc_const_stable_indirect]
|
||||||
#[rustc_intrinsic_must_be_overridden]
|
#[rustc_intrinsic_must_be_overridden]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
const fn const_eval_select<ARG: Tuple, F, G, RET>(
|
const fn const_eval_select<ARG: Tuple, F, G, RET>(
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
//@ compile-flags: -Znext-solver
|
//@ compile-flags: -Znext-solver
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(const_fmt_arguments_new)]
|
|
||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error[E0015]: cannot call non-const fn `_print` in constant functions
|
error[E0015]: cannot call non-const fn `_print` in constant functions
|
||||||
--> $DIR/issue-79450.rs:11:9
|
--> $DIR/issue-79450.rs:10:9
|
||||||
|
|
|
|
||||||
LL | println!("lul");
|
LL | println!("lul");
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
//@ compile-flags: -Znext-solver
|
//@ compile-flags: -Znext-solver
|
||||||
|
|
||||||
#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
|
#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
|
||||||
|
#![cfg_attr(unstable, feature(local_feature))]
|
||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
@ -16,8 +17,8 @@ use staged_api::*;
|
|||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
|
#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))]
|
||||||
#[cfg_attr(stable, rustc_const_stable(feature = "foo", since = "1.0.0"))]
|
#[cfg_attr(stable, rustc_const_stable(feature = "local_feature", since = "1.0.0"))]
|
||||||
impl const MyTrait for Foo {
|
impl const MyTrait for Foo {
|
||||||
//[stable]~^ ERROR trait implementations cannot be const stable yet
|
//[stable]~^ ERROR trait implementations cannot be const stable yet
|
||||||
fn func() {}
|
fn func() {}
|
||||||
@ -32,32 +33,43 @@ fn non_const_context() {
|
|||||||
#[unstable(feature = "none", issue = "none")]
|
#[unstable(feature = "none", issue = "none")]
|
||||||
const fn const_context() {
|
const fn const_context() {
|
||||||
Unstable::func();
|
Unstable::func();
|
||||||
//[stable]~^ ERROR not yet stable as a const fn
|
//[unstable]~^ ERROR cannot use `#[feature(unstable)]`
|
||||||
|
//[stable]~^^ ERROR not yet stable as a const fn
|
||||||
Foo::func();
|
Foo::func();
|
||||||
//[unstable]~^ ERROR not yet stable as a const fn
|
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
|
||||||
// ^ fails, because the `foo` feature is not active
|
//[stable]~^^ cannot be (indirectly) exposed to stable
|
||||||
|
// We get the error on `stable` since this is a trait function.
|
||||||
|
Unstable2::func();
|
||||||
|
//~^ ERROR not yet stable as a const fn
|
||||||
|
// ^ fails, because the `unstable2` feature is not active
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg_attr(unstable, rustc_const_unstable(feature = "foo", issue = "none"))]
|
#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))]
|
||||||
pub const fn const_context_not_const_stable() {
|
pub const fn const_context_not_const_stable() {
|
||||||
//[stable]~^ ERROR function has missing const stability attribute
|
//[stable]~^ ERROR function has missing const stability attribute
|
||||||
Unstable::func();
|
Unstable::func();
|
||||||
//[stable]~^ ERROR not yet stable as a const fn
|
//[stable]~^ ERROR not yet stable as a const fn
|
||||||
Foo::func();
|
Foo::func();
|
||||||
//[unstable]~^ ERROR not yet stable as a const fn
|
//[stable]~^ cannot be (indirectly) exposed to stable
|
||||||
// ^ fails, because the `foo` feature is not active
|
// We get the error on `stable` since this is a trait function.
|
||||||
|
Unstable2::func();
|
||||||
|
//~^ ERROR not yet stable as a const fn
|
||||||
|
// ^ fails, because the `unstable2` feature is not active
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "cheese", since = "1.0.0")]
|
#[rustc_const_stable(feature = "cheese", since = "1.0.0")]
|
||||||
const fn stable_const_context() {
|
const fn stable_const_context() {
|
||||||
Unstable::func();
|
Unstable::func();
|
||||||
//~^ ERROR not yet stable as a const fn
|
//[unstable]~^ ERROR cannot use `#[feature(unstable)]`
|
||||||
|
//[stable]~^^ ERROR not yet stable as a const fn
|
||||||
Foo::func();
|
Foo::func();
|
||||||
//[unstable]~^ ERROR not yet stable as a const fn
|
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
|
||||||
|
//[stable]~^^ cannot be (indirectly) exposed to stable
|
||||||
|
// We get the error on `stable` since this is a trait function.
|
||||||
const_context_not_const_stable()
|
const_context_not_const_stable()
|
||||||
//[unstable]~^ ERROR not yet stable as a const fn
|
//[unstable]~^ ERROR cannot use `#[feature(local_feature)]`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user