remove const-support for align_offset and is_aligned
As part of the recent discussion to stabilize `ptr.is_null()` in const context, the general vibe was that it's okay for a const function to panic when the same operation would work at runtime (that's just a case of "dynamically detecting that something is not supported as a const operation"), but it is *not* okay for a const function to just return a different result.
Following that, `is_aligned` and `is_aligned_to` have their const status revoked in this PR, since they do return actively wrong results at const time. In the future we can consider having a new intrinsic or so that can check whether a pointer is "guaranteed to be aligned", but the current implementation based on `align_offset` does not have the behavior we want.
In fact `align_offset` itself behaves quite strangely in const, and that support needs a bunch of special hacks. That doesn't seem worth it. Instead, the users that can fall back to a different implementation should just use const_eval_select directly, and everything else should not be made const-callable. So this PR does exactly that, and entirely removes const support for align_offset.
Closes some tracking issues by removing the associated features:
Closes https://github.com/rust-lang/rust/issues/90962
Closes https://github.com/rust-lang/rust/issues/104203
Cc `@rust-lang/wg-const-eval` `@rust-lang/libs-api`
Operations like is_aligned would return actively wrong results at compile-time,
i.e. calling it on the same pointer at compiletime and runtime could yield
different results. That's no good.
Instead of having hacks to make align_offset kind-of work in const-eval, just
use const_eval_select in the few places where it makes sense, which also ensures
those places are all aware they need to make sure the fallback behavior is
consistent.
better test for const HashMap; remove const_hash leftovers
The existing `const_with_hasher` test is kind of silly since the HashMap it constructs can never contain any elements. So this adjusts the test to construct a usable HashMap, which is a bit non-trivial since the default hash builder cannot be built in `const`. `BuildHasherDefault::new()` helps but is unstable (https://github.com/rust-lang/rust/issues/123197), so we also have a test that does not involve that type.
The second commit removes the last remnants of https://github.com/rust-lang/rust/issues/104061, since they aren't actually useful -- without const traits, you can't do any hashing in `const`.
Cc ``@rust-lang/libs-api`` ``@rust-lang/wg-const-eval``
Closes#104061
Related to https://github.com/rust-lang/rust/issues/102575
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.
Run most `core::num` tests in const context too
This adds some infrastructure for something I was going to use in #131566, but it felt worthwhile enough on its own to merge/discuss separately.
Essentially, right now we tend to rely on UI tests to ensure that things work in const context, rather than just using library tests. This uses a few simple macro tricks to make it *relatively* painless to execute tests in both runtime and compile-time context. And this only applies to the numeric tests, and not anything else.
Recommended to review without whitespace in the diff.
cc `@RalfJung`
merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate
https://github.com/rust-lang/rust/issues/76205 has been closed a while ago, but there are still some functions that reference it. Those functions are all unstable *and* const-unstable. There's no good reason to use a separate feature gate for their const-stability, so this PR moves their const-stability under the same gate as their regular stability, and therefore removes the remaining references to https://github.com/rust-lang/rust/issues/76205.
core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments.
Adds:
- `Ipv4Address::from_octets([u8;4])`
- `Ipv6Address::from_octets([u8;16])`
- `Ipv6Address::from_segments([u16;8])`
equivalent to the existing `From` impls.
Advantages:
- Consistent with `to_bits, from_bits`.
- More discoverable than the `From` impls.
- Helps with type inference: it's common to want to convert byte slices to IP addrs. If you try this
```rust
fn foo(x: &[u8]) -> Ipv4Addr {
Ipv4Addr::from(foo.try_into().unwrap())
}
```
it [doesn't work](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0e2873312de275a58fa6e33d1b213bec). You have to write `Ipv4Addr::from(<[u8;4]>::try_from(x).unwrap())` instead, which is not great. With `from_octets` it is able to infer the right types.
Found this while porting [smoltcp](https://github.com/smoltcp-rs/smoltcp/) from its own IP address types to the `core::net` types.
~~Tracking issues #27709 #76205~~
Tracking issue: https://github.com/rust-lang/rust/issues/131360
Stabilize const `ptr::write*` and `mem::replace`
Since `const_mut_refs` and `const_refs_to_cell` have been stabilized, we may now also stabilize the ability to write to places during const evaluation inside our library API. So, we now propose the `const fn` version of `ptr::write` and its variants. This allows us to also stabilize `mem::replace` and `ptr::replace`.
- const `mem::replace`: https://github.com/rust-lang/rust/issues/83164#issuecomment-2338660862
- const `ptr::write{,_bytes,_unaligned}`: https://github.com/rust-lang/rust/issues/86302#issuecomment-2330275266
Their implementation requires an additional internal stabilization of `const_intrinsic_forget`, which is required for `*::write*` and thus `*::replace`. Thus we const-stabilize the internal intrinsics `forget`, `write_bytes`, and `write_via_move`.
Implement `debug_more_non_exhaustive`
This implements the ACP at https://github.com/rust-lang/libs-team/issues/248, adding `.finish_non_exhaustive()` for `DebugTuple`, `DebugSet`, `DebugList`, and `DebugMap`.
Also used this as an opportunity to make some documentation and tests more readable by using raw strings instead of escaped quotes.
Tracking issue: https://github.com/rust-lang/rust/issues/127942
Rather than writing character at a time, optimise Debug implementation
for core::ascii::Char such that it writes the entire representation as
with a single write_str call.
With that, add tests for Display and Debug implementations.
Stabilize `const_waker`
Closes: https://github.com/rust-lang/rust/issues/102012.
For `local_waker` and `context_ext` related things, I just ~~moved them to dedicated feature gates and reused their own tracking issue (maybe it's better to open a new one later, but at least they should not be tracked under https://github.com/rust-lang/rust/issues/102012 from the beginning IMO.)~~ reused their own feature gates as suggested by ``@tgross35.``
``@rustbot`` label: +T-libs-api
r? libs-api
add `is_multiple_of` for unsigned integer types
tracking issue: https://github.com/rust-lang/rust/issues/128101
This adds the `.is_multiple_of` method on unsigned integers.
Returns `true` if `self` is an integer multiple of `rhs`, and false otherwise.
This function is equivalent to `self % rhs == 0`, except that it will not panic for `rhs == 0`. Instead, `0.is_multiple_of(0) == true`, and for any non-zero `n`, `n.is_multiple_of(0) == false`.
Stabilize const `{integer}::from_str_radix` i.e. `const_int_from_str`
This PR stabilizes the feature `const_int_from_str`.
- ACP Issue: rust-lang/libs-team#74
- Implementation PR: rust-lang/rust#99322
- Part of Tracking Issue: rust-lang/rust#59133
API Change Diff:
```diff
impl {integer} {
- pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
+ pub const fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError>;
}
impl ParseIntError {
- pub fn kind(&self) -> &IntErrorKind;
+ pub const fn kind(&self) -> &IntErrorKind;
}
```
This makes it easier to parse integers at compile-time, e.g.
the example from the Tracking Issue:
```rust
env!("SOMETHING").parse::<usize>().unwrap()
```
could now be achived with
```rust
match usize::from_str_radix(env!("SOMETHING"), 10) {
Ok(val) => val,
Err(err) => panic!("Invalid value for SOMETHING environment variable."),
}
```
rather than having to depend on a library that implements or manually implement the parsing at compile-time.
---
Checklist based on [Libs Stabilization Guide - When there's const involved](https://std-dev-guide.rust-lang.org/development/stabilization.html#when-theres-const-involved)
I am treating this as a [partial stabilization](https://std-dev-guide.rust-lang.org/development/stabilization.html#partial-stabilizations) as it shares a tracking issue (and is rather small), so directly opening the partial stabilization PR for the subset (feature `const_int_from_str`) being stabilized.
- [x] ping Constant Evaluation WG
- [x] no unsafe involved
- [x] no `#[allow_internal_unstable]`
- [ ] usage of `intrinsic::const_eval_select` rust-lang/rust#124625 in `from_str_radix_assert` to change the error message between compile-time and run-time
- [ ] [rust-labg/libs-api FCP](https://github.com/rust-lang/rust/pull/124941#issuecomment-2207021921)