diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2024-10-07 15:37:06 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-07 15:37:06 +1100 |
| commit | dd4f062b0765a8a152b184f03b08645cac20e0e7 (patch) | |
| tree | 2aa89f538c63107b20b85b346930abf32ba393d5 /tests | |
| parent | a964a9227787447016894268152bff79ee76a36b (diff) | |
| parent | d793766a6199d9b7339633ad0296af63c7b4f9b8 (diff) | |
Rollup merge of #128399 - mammothbane:master, r=Amanieu,tgross35
liballoc: introduce String, Vec const-slicing
This change `const`-qualifies many methods on `Vec` and `String`, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice`.
## Motivation
This is to support simultaneous variance over ownership and constness. I have an enum type that may contain either `String` or `&str`, and I want to produce a `&str` from it in a possibly-`const` context.
```rust
enum StrOrString<'s> {
Str(&'s str),
String(String),
}
impl<'s> StrOrString<'s> {
const fn as_str(&self) -> &str {
match self {
// In a const-context, I really only expect to see this variant, but I can't switch the implementation
// in some mode like #[cfg(const)] -- there has to be a single body
Self::Str(s) => s,
// so this is a problem, since it's not `const`
Self::String(s) => s.as_str(),
}
}
}
```
Currently `String` and `Vec` don't support this, but can without functional changes. Similar logic applies for `len`, `capacity`, `is_empty`.
## Changes
The essential thing enabling this change is that `Unique::as_ptr` is `const`. This lets us convert `RawVec::ptr` -> `Vec::as_ptr` -> `Vec::as_slice` -> `String::as_str`.
I had to move the `Deref` implementations into `as_{str,slice}` because `Deref` isn't `#[const_trait]`, but I would expect this change to be invisible up to inlining. I moved the `DerefMut` implementations as well for uniformity.
Diffstat (limited to 'tests')
4 files changed, 88 insertions, 106 deletions
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 0ad7f5910a0..4d964b0afb7 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -5,66 +5,61 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined <Vec<u8> as Deref>::deref) { debug self => _1; - let mut _6: usize; - scope 2 (inlined Vec::<u8>::as_ptr) { + scope 2 (inlined Vec::<u8>::as_slice) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec<u8>; - scope 3 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; - scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { - debug self => _3; - scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { + let mut _6: usize; + scope 3 (inlined Vec::<u8>::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec<u8>; + scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { + debug self => _2; + let mut _3: &alloc::raw_vec::RawVecInner; + scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { debug self => _3; - let mut _4: std::ptr::NonNull<u8>; - scope 6 (inlined Unique::<u8>::cast::<u8>) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 7 (inlined NonNull::<u8>::cast::<u8>) { - debug self => _4; - scope 8 (inlined NonNull::<u8>::as_ptr) { + scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { + debug self => _3; + let mut _4: std::ptr::NonNull<u8>; + scope 7 (inlined Unique::<u8>::cast::<u8>) { + debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; + debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; + scope 8 (inlined NonNull::<u8>::cast::<u8>) { debug self => _4; - let mut _5: *const u8; + scope 9 (inlined NonNull::<u8>::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } } } - } - scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) { - debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 11 (inlined Unique::<u8>::as_non_null_ptr) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - } + scope 10 (inlined Unique::<u8>::as_non_null_ptr) { + debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; + debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; } } + scope 11 (inlined NonNull::<u8>::as_ptr) { + debug self => _4; + } } - scope 12 (inlined NonNull::<u8>::as_ptr) { - debug self => _4; - } - } - } - } - scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _5; - debug len => _6; - let _7: *const [u8]; - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 16 (inlined std::mem::size_of::<u8>) { - } - scope 17 (inlined align_of::<u8>) { - } - scope 18 (inlined slice_from_raw_parts::<u8>) { + scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; debug len => _6; - scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _5; - debug metadata => _6; + let _7: *const [u8]; + scope 13 (inlined core::ub_checks::check_language_ub) { + scope 14 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 15 (inlined std::mem::size_of::<u8>) { + } + scope 16 (inlined align_of::<u8>) { + } + scope 17 (inlined slice_from_raw_parts::<u8>) { + debug data => _5; + debug len => _6; + scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _6; + } } } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 0ad7f5910a0..4d964b0afb7 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -5,66 +5,61 @@ fn vec_deref_to_slice(_1: &Vec<u8>) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined <Vec<u8> as Deref>::deref) { debug self => _1; - let mut _6: usize; - scope 2 (inlined Vec::<u8>::as_ptr) { + scope 2 (inlined Vec::<u8>::as_slice) { debug self => _1; - let mut _2: &alloc::raw_vec::RawVec<u8>; - scope 3 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { - debug self => _2; - let mut _3: &alloc::raw_vec::RawVecInner; - scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { - debug self => _3; - scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { + let mut _6: usize; + scope 3 (inlined Vec::<u8>::as_ptr) { + debug self => _1; + let mut _2: &alloc::raw_vec::RawVec<u8>; + scope 4 (inlined alloc::raw_vec::RawVec::<u8>::ptr) { + debug self => _2; + let mut _3: &alloc::raw_vec::RawVecInner; + scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) { debug self => _3; - let mut _4: std::ptr::NonNull<u8>; - scope 6 (inlined Unique::<u8>::cast::<u8>) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 7 (inlined NonNull::<u8>::cast::<u8>) { - debug self => _4; - scope 8 (inlined NonNull::<u8>::as_ptr) { + scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) { + debug self => _3; + let mut _4: std::ptr::NonNull<u8>; + scope 7 (inlined Unique::<u8>::cast::<u8>) { + debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; + debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; + scope 8 (inlined NonNull::<u8>::cast::<u8>) { debug self => _4; - let mut _5: *const u8; + scope 9 (inlined NonNull::<u8>::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } } } - } - scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) { - debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - scope 11 (inlined Unique::<u8>::as_non_null_ptr) { - debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; - debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; - } + scope 10 (inlined Unique::<u8>::as_non_null_ptr) { + debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4; + debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>; } } + scope 11 (inlined NonNull::<u8>::as_ptr) { + debug self => _4; + } } - scope 12 (inlined NonNull::<u8>::as_ptr) { - debug self => _4; - } - } - } - } - scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _5; - debug len => _6; - let _7: *const [u8]; - scope 14 (inlined core::ub_checks::check_language_ub) { - scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 16 (inlined std::mem::size_of::<u8>) { - } - scope 17 (inlined align_of::<u8>) { - } - scope 18 (inlined slice_from_raw_parts::<u8>) { + scope 12 (inlined std::slice::from_raw_parts::<'_, u8>) { debug data => _5; debug len => _6; - scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _5; - debug metadata => _6; + let _7: *const [u8]; + scope 13 (inlined core::ub_checks::check_language_ub) { + scope 14 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + scope 15 (inlined std::mem::size_of::<u8>) { + } + scope 16 (inlined align_of::<u8>) { + } + scope 17 (inlined slice_from_raw_parts::<u8>) { + debug data => _5; + debug len => _6; + scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _6; + } } } } diff --git a/tests/ui/consts/issue-94675.rs b/tests/ui/consts/issue-94675.rs index 56c4b6ea36f..2e30eebb07b 100644 --- a/tests/ui/consts/issue-94675.rs +++ b/tests/ui/consts/issue-94675.rs @@ -1,6 +1,6 @@ //@ known-bug: #103507 -#![feature(const_trait_impl)] +#![feature(const_trait_impl, const_vec_string_slice)] struct Foo<'a> { bar: &'a mut Vec<usize>, diff --git a/tests/ui/consts/issue-94675.stderr b/tests/ui/consts/issue-94675.stderr index ebfa09b2e5d..a85c5e10374 100644 --- a/tests/ui/consts/issue-94675.stderr +++ b/tests/ui/consts/issue-94675.stderr @@ -1,11 +1,3 @@ -error[E0015]: cannot call non-const fn `Vec::<u32>::len` in constant functions - --> $DIR/issue-94675.rs:11:27 - | -LL | self.bar[0] = baz.len(); - | ^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - error[E0015]: cannot call non-const operator in constant functions --> $DIR/issue-94675.rs:11:17 | @@ -20,6 +12,6 @@ help: add `#![feature(effects)]` to the crate attributes to enable LL + #![feature(effects)] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0015`. |
