mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
a0215d8e46
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.
93 lines
3.6 KiB
Rust
93 lines
3.6 KiB
Rust
#![crate_name = "foo"]
|
|
|
|
#![stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
#![feature(foo, foo2)]
|
|
#![feature(staged_api)]
|
|
|
|
//@ has 'foo/fn.foo.html' '//pre' 'pub fn foo() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: unstable)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
|
pub const fn foo() -> u32 { 42 }
|
|
|
|
//@ has 'foo/fn.foo_unsafe.html' '//pre' 'pub unsafe fn foo_unsafe() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: unstable)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
|
pub const unsafe fn foo_unsafe() -> u32 { 42 }
|
|
|
|
//@ has 'foo/fn.foo2.html' '//pre' 'pub const fn foo2() -> u32'
|
|
//@ !hasraw - '//span[@class="since"]'
|
|
#[unstable(feature = "humans", issue = "none")]
|
|
pub const fn foo2() -> u32 { 42 }
|
|
|
|
//@ has 'foo/fn.foo3.html' '//pre' 'pub const fn foo3() -> u32'
|
|
//@ !hasraw - '//span[@class="since"]'
|
|
#[unstable(feature = "humans", issue = "none")]
|
|
#[rustc_const_unstable(feature = "humans", issue = "none")]
|
|
pub const fn foo3() -> u32 { 42 }
|
|
|
|
//@ has 'foo/fn.bar2.html' '//pre' 'pub const fn bar2() -> u32'
|
|
//@ has - //span '1.0.0 (const: 1.0.0)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
|
pub const fn bar2() -> u32 { 42 }
|
|
|
|
|
|
//@ has 'foo/fn.foo2_gated.html' '//pre' 'pub const unsafe fn foo2_gated() -> u32'
|
|
//@ !hasraw - '//span[@class="since"]'
|
|
#[unstable(feature = "foo2", issue = "none")]
|
|
pub const unsafe fn foo2_gated() -> u32 { 42 }
|
|
|
|
//@ has 'foo/fn.bar2_gated.html' '//pre' 'pub const unsafe fn bar2_gated() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: 1.0.0)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
|
pub const unsafe fn bar2_gated() -> u32 { 42 }
|
|
|
|
#[unstable(
|
|
feature = "humans",
|
|
reason = "who ever let humans program computers, we're apparently really bad at it",
|
|
issue = "none",
|
|
)]
|
|
pub mod unstable {
|
|
//@ has 'foo/unstable/fn.bar_not_gated.html' '//pre' 'pub const unsafe fn bar_not_gated() -> u32'
|
|
//@ !hasraw - '//span[@class="since"]'
|
|
pub const unsafe fn bar_not_gated() -> u32 { 42 }
|
|
}
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
pub struct Foo;
|
|
|
|
impl Foo {
|
|
//@ has 'foo/struct.Foo.html' '//*[@id="method.gated"]/h4[@class="code-header"]' 'pub fn gated() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: unstable)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
|
pub const fn gated() -> u32 { 42 }
|
|
|
|
//@ has 'foo/struct.Foo.html' '//*[@id="method.gated_unsafe"]/h4[@class="code-header"]' 'pub unsafe fn gated_unsafe() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: unstable)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_unstable(feature="foo", issue = "none")]
|
|
pub const unsafe fn gated_unsafe() -> u32 { 42 }
|
|
|
|
//@ has 'foo/struct.Foo.html' '//*[@id="method.stable_impl"]/h4[@class="code-header"]' 'pub const fn stable_impl() -> u32'
|
|
//@ has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_stable(feature = "const2", since = "1.2.0")]
|
|
pub const fn stable_impl() -> u32 { 42 }
|
|
}
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
pub struct Bar;
|
|
|
|
impl Bar {
|
|
// Show non-const stabilities that are the same as the enclosing item.
|
|
//@ has 'foo/struct.Bar.html' '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[rustc_const_stable(feature = "const2", since = "1.2.0")]
|
|
pub const fn stable_impl() -> u32 { 42 }
|
|
}
|