-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make slice->str conversion and related functions const
#90607
Conversation
library/core/src/str/validations.rs
Outdated
// algorithm correctness can not depend on `align_offset` returning non-max values. | ||
// | ||
// As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. | ||
let align = unsafe { const_eval_select((v, usize_bytes), ctfe_align, rt_align) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems better to put this inside align_offset itself, since the justification should work for all calls to it, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I think it would be great to put this inside align_offset
itself, wouldn't this allow for user code to behave differently in const
and non-const
context?
const fn is_likely_called_in_ctfe() -> bool {
let arr = [0u8; 2];
(&arr[0] as *const u8).align_offset(2) == usize::MAX
&& (&arr[1] as *const u8).align_offset(2) == usize::MAX
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually even (&0u8 as *const u8).align_offset(1) == usize::MAX
will do. Basically while const_eval_select
in the caller of align_offset
shouldn't change behaviour, const_eval_select
in align_offset
itself clearly changes it's return value depending on whatever it's called at runtime or compile time.
Sadly, it seems that we don't want to allow this, right? :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const_eval_select
inalign_offset
itself clearly changes it's return value depending on whatever it's called at runtime or compile time.Sadly, it seems that we don't want to allow this, right? :(
Actually, the docs specifically state
If it is not possible to align the pointer, the implementation returns usize::MAX. It is permissible for the implementation to always return usize::MAX. Only your algorithm’s performance can depend on getting a usable offset here, not its correctness.
There are no guarantees whatsoever that offsetting the pointer will not overflow or go beyond the allocation that the pointer points into. It is up to the caller to ensure that the returned offset is correct in all terms other than alignment.
The only reason align_offset
even exists is because I wanted to enable miri to do such trickery back when it wasn't able to do ptr2int conversions.
So, we can definitely make align_offset
behave this way in const fn, as long as we have a tracking issue for the const stabilization that specifically raises this concern before we bake it into a stabilized function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can make a follow-up PR then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a slight preference for doing a PR for just align_offset
first, since then this PR does less work, but if you prefer to first merge this one I'm ok with that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can do either way if you prefer align_offset
first, then so be it :)
Upd: I've opened #90958
…oli-obk Mark `<*const _>::align_offset` and `<*mut _>::align_offset` as `const fn` This PR marks the following APIs as `const`: ```rust impl<T> *const T { pub const fn align_offset(self, align: usize) -> usize; } impl<T> *mut T { pub const fn align_offset(self, align: usize) -> usize; } ``` `const` implementation simply returns `usize::MAX`. --- Previous discussion: rust-lang#90607 (comment) --- r? `@oli-obk`
This commit makes the following functions from `core::str` `const fn`: - `from_utf8[_mut]` (`feature(const_str_from_utf8)`) - `from_utf8_unchecked_mut` (`feature(const_str_from_utf8_unchecked_mut)`) - `Utf8Error::{valid_up_to,error_len}` (`feature(const_str_from_utf8)`)
f27d3c6
to
cf6f64a
Compare
@bors r+ rollup |
📌 Commit cf6f64a has been approved by |
wait, shouldn't we create a tracking issue first? Upd: I've filled in the tracking issues, not sure how |
…_utf8_unchecked_mut` features
Oops thanks! @bors r+ rollup |
📌 Commit 573a00e has been approved by |
…=oli-obk Make slice->str conversion and related functions `const` This PR marks the following APIs as `const`: ```rust // core::str pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>; pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error>; pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str; impl Utf8Error { pub const fn valid_up_to(&self) -> usize; pub const fn error_len(&self) -> Option<usize>; } ``` Everything but `from_utf8_unchecked_mut` uses `const_str_from_utf8` feature gate, `from_utf8_unchecked_mut` uses `const_str_from_utf8_unchecked_mut` feature gate. --- I'm not sure why `from_utf8_unchecked_mut` was left out being non-`const`, considering that `from_utf8_unchecked` is not only `const`, but **`const` stable**. --- r? `@oli-obk` (performance-only `const_eval_select` use)
…=oli-obk Make slice->str conversion and related functions `const` This PR marks the following APIs as `const`: ```rust // core::str pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error>; pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error>; pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str; impl Utf8Error { pub const fn valid_up_to(&self) -> usize; pub const fn error_len(&self) -> Option<usize>; } ``` Everything but `from_utf8_unchecked_mut` uses `const_str_from_utf8` feature gate, `from_utf8_unchecked_mut` uses `const_str_from_utf8_unchecked_mut` feature gate. --- I'm not sure why `from_utf8_unchecked_mut` was left out being non-`const`, considering that `from_utf8_unchecked` is not only `const`, but **`const` stable**. --- r? ``@oli-obk`` (performance-only `const_eval_select` use)
Rollup of 8 pull requests Successful merges: - rust-lang#90386 (Add `-Zassert-incr-state` to assert state of incremental cache) - rust-lang#90438 (Clean up mess for --show-coverage documentation) - rust-lang#90480 (Mention `Vec::remove` in `Vec::swap_remove`'s docs) - rust-lang#90607 (Make slice->str conversion and related functions `const`) - rust-lang#90750 (rustdoc: Replace where-bounded Clean impl with simple function) - rust-lang#90895 (require full validity when determining the discriminant of a value) - rust-lang#90989 (Avoid suggesting literal formatting that turns into member access) - rust-lang#91002 (rustc: Remove `#[rustc_synthetic]`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This PR marks the following APIs as
const
:Everything but
from_utf8_unchecked_mut
usesconst_str_from_utf8
feature gate,from_utf8_unchecked_mut
usesconst_str_from_utf8_unchecked_mut
feature gate.I'm not sure why
from_utf8_unchecked_mut
was left out being non-const
, considering thatfrom_utf8_unchecked
is not onlyconst
, butconst
stable.r? @oli-obk (performance-only
const_eval_select
use)