Skip to content
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

fallible allocation experiment 2 #117738

Closed
wants to merge 2 commits into from
Closed

Conversation

pitaj
Copy link
Contributor

@pitaj pitaj commented Nov 9, 2023

supercedes #111970

The idea is to implement fallible allocation APIs using an extra generic parameter on the container type. Here that has been done for Vec. The docs turned out much better but there is still some room for improvement.

In order to limit the impact on the std docs, I used a type alias for std::vec::Vec as @matthieu-m suggested. This actually produced quite nice docs complete with all of the relevant impls, and excluding the duplicate functions for the irrelevant Fallible case.

There are a few things we'll need to handle on the rustdoc side before moving forward with this, some of which can be seen in the following image. I think we can address all of them by making #[doc(inline)] work on trait aliases. It would need to do the following:

  1. Copy the item-level docs (in this case the alloc::vec::Vec docs)
  2. Display a Struct / Enum documentation page, rather than a Type Alias page (in this case "Struct std::vec::Vec")
  3. Hide any explicitly defined generic parameters from showing up in the impl headers (in this case, FH should be hidden)
  4. And, I think it should generate a static html page rather than depending on the JS-based type alias inlining

Unrelated to doc(inline), it would be really nice if there was a way to copy the docs of one module to another. As it is, I think the only way to make sure that std::vec stays up-to-date with the alloc::vec docs will be to extract the docs to a separate text file and use include_str!.

image

Documentation archive
(Hopefully that still mostly works, I had to delete a couple things)

@rustbot
Copy link
Collaborator

rustbot commented Nov 9, 2023

r? @cuviper

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Nov 9, 2023
@rust-log-analyzer
Copy link
Collaborator

The job mingw-check-tidy failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
Prepare all required actions
Getting action download info
Download action repository 'actions/checkout@v4' (SHA:b4ffde65f46336ab88eb53be808477a3936bae11)
Download action repository 'actions/upload-artifact@v3' (SHA:a8a3f3ad30e3422c9c7b888a15615d19a852ae32)
Complete job name: PR - mingw-check-tidy
git config --global core.autocrlf false
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
---
Removing intermediate container 874122103ad4
 ---> a02b8c6b2a29
Step 6/10 : COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
 ---> fda40611240a
Step 7/10 : RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-requirements.txt     && pip3 install virtualenv
Collecting binaryornot==0.4.4
  Downloading binaryornot-0.4.4-py2.py3-none-any.whl (9.0 kB)
Collecting boolean-py==4.0
  Downloading boolean.py-4.0-py3-none-any.whl (25 kB)
---
Building wheels for collected packages: reuse
  Building wheel for reuse (pyproject.toml): started
  Building wheel for reuse (pyproject.toml): finished with status 'done'
  Created wheel for reuse: filename=reuse-1.1.0-cp310-cp310-manylinux_2_35_x86_64.whl size=180123 sha256=f323ccf11d14c5b11f6d5e70edb46e391f4b49a5df5c7d922224477ad8ee15c5
  Stored in directory: /tmp/pip-ephem-wheel-cache-7wwp8t__/wheels/c2/3c/b9/1120c2ab4bd82694f7e6f0537dc5b9a085c13e2c69a8d0c76d
Installing collected packages: boolean-py, binaryornot, setuptools, reuse, python-debian, markupsafe, license-expression, jinja2, chardet
  Attempting uninstall: setuptools
    Found existing installation: setuptools 59.6.0
    Not uninstalling setuptools at /usr/lib/python3/dist-packages, outside environment /usr
---
  Downloading virtualenv-20.24.6-py3-none-any.whl (3.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.8/3.8 MB 60.7 MB/s eta 0:00:00
Collecting filelock<4,>=3.12.2
  Downloading filelock-3.13.1-py3-none-any.whl (11 kB)
Collecting platformdirs<4,>=3.9.1
  Downloading platformdirs-3.11.0-py3-none-any.whl (17 kB)
Collecting distlib<1,>=0.3.7
  Downloading distlib-0.3.7-py2.py3-none-any.whl (468 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 468.9/468.9 KB 121.0 MB/s eta 0:00:00
Installing collected packages: distlib, platformdirs, filelock, virtualenv
Successfully installed distlib-0.3.7 filelock-3.13.1 platformdirs-3.11.0 virtualenv-20.24.6
Removing intermediate container 6c15745f7917
 ---> e1d5bfb28b8e
Step 8/10 : COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 ---> a3c052d51b42
 ---> a3c052d51b42
Step 9/10 : COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 ---> 16d0d72b8c77
Step 10/10 : ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint
Removing intermediate container b2729c3cc0bf
 ---> 5e68976d6976
Successfully built 5e68976d6976
Successfully tagged rust-ci:latest
Successfully tagged rust-ci:latest
##[endgroup]
Built container sha256:5e68976d69769e702873820bfbded859850c048fa797986d57188e0665c93f94
Uploading finished image sha256:5e68976d69769e702873820bfbded859850c048fa797986d57188e0665c93f94 to https://ci-caches.rust-lang.org/docker/139141a603ff222e98d20ef66f0e4eaedfc4b373e41d302ecff577f90ee0c6cf0cab092d18a8f6a073c88b362b9a680d3b2b6e5c828faaf25d1b853eabb78b1a
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
5e68976d6976   1 second ago         /bin/sh -c #(nop)  ENV SCRIPT=TIDY_PRINT_DIF…   0B        
a3c052d51b42   2 seconds ago        /bin/sh -c #(nop) COPY file:078ea1d11e7b7cda…   367B      
e1d5bfb28b8e   3 seconds ago        |1 DEBIAN_FRONTEND=noninteractive /bin/sh -c…   23.8MB    
fda40611240a   10 seconds ago       /bin/sh -c #(nop) COPY file:ac591dd6bc5afa66…   5.33kB    
a02b8c6b2a29   11 seconds ago       |1 DEBIAN_FRONTEND=noninteractive /bin/sh -c…   23.1MB    
---
<missing>      4 weeks ago          /bin/sh -c #(nop)  LABEL org.opencontainers.…   0B        
<missing>      4 weeks ago          /bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH     0B        
<missing>      4 weeks ago          /bin/sh -c #(nop)  ARG RELEASE                  0B        

<botocore.awsrequest.AWSRequest object at 0x7f35036ab990>
gzip: stdout: Broken pipe
xargs: docker: terminated by signal 13
https://ci-caches.rust-lang.org/docker/139141a603ff222e98d20ef66f0e4eaedfc4b373e41d302ecff577f90ee0c6cf0cab092d18a8f6a073c88b362b9a680d3b2b6e5c828faaf25d1b853eabb78b1a
sha256:5e68976d69769e702873820bfbded859850c048fa797986d57188e0665c93f94
---
DirectMap4k:      188352 kB
DirectMap2M:     7151616 kB
DirectMap1G:    11534336 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint
    Finished dev [unoptimized] target(s) in 0.03s
##[endgroup]
downloading https://ci-artifacts.rust-lang.org/rustc-builds-alt/d8dbf7ca0ee9c6da0fd039b1eb8cf7c7cb840f43/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz
extracting /checkout/obj/build/cache/llvm-d8dbf7ca0ee9c6da0fd039b1eb8cf7c7cb840f43-true/rust-dev-nightly-x86_64-unknown-linux-gnu.tar.xz to /checkout/obj/build/x86_64-unknown-linux-gnu/ci-llvm
---
   Compiling tidy v0.1.0 (/checkout/src/tools/tidy)
    Finished release [optimized] target(s) in 25.81s
##[endgroup]
fmt check
##[error]Diff in /checkout/library/alloc/src/vec/spec_extend.rs at line 1:
 use crate::alloc::failure_handling::Fatal;
+use crate::alloc::Allocator;
 use core::iter::TrustedLen;
 use core::iter::TrustedLen;
 use core::slice::{self};
 
##[error]Diff in /checkout/library/alloc/src/vec/into_iter.rs at line 406:
                     // `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec
                     let alloc = ManuallyDrop::take(&mut self.0.alloc);
                     // RawVec handles deallocation
-                    let _ = RawVec::<_, _, Fallible>::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
+                    let _ = RawVec::<_, _, Fallible>::from_raw_parts_in(
+                        self.0.buf.as_ptr(),
+                        self.0.cap,
+                    );
                 }
             }
         }
         }
##[error]Diff in /checkout/library/alloc/src/boxed.rs at line 694:
             Global.allocate(layout)?.cast()
         };
         };
-        unsafe { Ok(RawVec::<_, _, Fallible>::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
+        unsafe {
+            Ok(RawVec::<_, _, Fallible>::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len))
     }
 
     /// Constructs a new boxed slice with uninitialized contents, with the memory
     /// Constructs a new boxed slice with uninitialized contents, with the memory
##[error]Diff in /checkout/library/alloc/src/boxed.rs at line 728:
             };
             Global.allocate_zeroed(layout)?.cast()
         };
-        unsafe { Ok(RawVec::<_, _, Fallible>::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) }
+        unsafe {
+            Ok(RawVec::<_, _, Fallible>::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len))
     }
 }
 
 
##[error]Diff in /checkout/library/alloc/src/vec/drain.rs at line 1:
-use crate::alloc::failure_handling::{FailureHandling, DefaultFailureHandling};
+use crate::alloc::failure_handling::{DefaultFailureHandling, FailureHandling};
 use crate::alloc::{Allocator, Global};
 use core::fmt;
 use core::iter::{FusedIterator, TrustedLen};
##[error]Diff in /checkout/library/alloc/src/raw_vec.rs at line 16:
##[error]Diff in /checkout/library/alloc/src/lib.rs at line 274:
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use crate::vec::*;
-        
+
+
         // FIXME: include `Vec` docs here
         #[stable(feature = "rust1", since = "1.0.0")]
-        pub type Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A = crate::alloc::Global> = crate::vec::Vec<T, A, crate::alloc::failure_handling::DefaultFailureHandling>;
+        pub type Vec<
+            T,
+            #[unstable(feature = "allocator_api", issue = "32838")] A = crate::alloc::Global,
+        > = crate::vec::Vec<T, A, crate::alloc::failure_handling::DefaultFailureHandling>;
 
     #[stable(feature = "rust1", since = "1.0.0")]
 use crate::collections::TryReserveError;
 use crate::collections::TryReserveErrorKind::*;
 use crate::collections::TryReserveErrorKind::*;
 
-use crate::alloc::failure_handling::{FailureHandling, Fatal, Fallible};
+use crate::alloc::failure_handling::{FailureHandling, Fallible, Fatal};
 #[cfg(test)]
 mod tests;
 mod tests;
##[error]Diff in /checkout/library/alloc/src/raw_vec.rs at line 391:
     //     Self::allocate_in(capacity, AllocInit::Zeroed, alloc)
     // }
 
-    fn try_allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Result<Self, TryReserveError> {
+    fn try_allocate_in(
+        capacity: usize,
+        alloc: A,
+    ) -> Result<Self, TryReserveError> {
+    ) -> Result<Self, TryReserveError> {
         // Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
         use crate::collections::TryReserveErrorKind;
         use crate::collections::TryReserveErrorKind;
##[error]Diff in /checkout/library/alloc/src/raw_vec.rs at line 477:
     /// If `len` exceeds `self.capacity()`, this may fail to actually allocate
     /// the requested space. This is not really unsafe, but the unsafe code
     /// *you* write that relies on the behavior of this function may break.
-        &mut self,
-        len: usize,
-        additional: usize,
-    ) -> Result<(), TryReserveError> {
-    ) -> Result<(), TryReserveError> {
+    pub fn reserve_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
         if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) }
-    
+
+
     /// Shrinks the buffer down to the specified capacity. If the given amount
     /// is 0, actually completely deallocates.
     #[unstable(feature = "allocator_api", issue = "32838")]
##[error]Diff in /checkout/library/alloc/src/vec/spec_from_iter_nested.rs at line 2:
 use core::iter::TrustedLen;
 use core::ptr;
 
-use crate::{raw_vec::RawVec, alloc::{failure_handling::Fatal, Global}};
+use crate::{
+    alloc::{failure_handling::Fatal, Global},
+};
 
 
 use super::{SpecExtend, Vec};
 
Running `"/checkout/obj/build/x86_64-unknown-linux-gnu/rustfmt/bin/rustfmt" "--config-path" "/checkout" "--edition" "2021" "--unstable-features" "--skip-children" "--check" "/checkout/library/alloc/src/task.rs" "/checkout/library/alloc/src/alloc/tests.rs" "/checkout/library/alloc/src/collections/vec_deque/spec_extend.rs" "/checkout/library/alloc/src/collections/btree/merge_iter.rs" "/checkout/library/alloc/src/collections/btree/mod.rs" "/checkout/library/alloc/src/collections/vec_deque/into_iter.rs" "/checkout/library/alloc/src/collections/btree/node.rs" "/checkout/library/alloc/src/vec/spec_from_iter_nested.rs"` failed.
If you're running `tidy`, try again with `--bless`. Or, if you just want to format code, run `./x.py fmt` instead.
  local time: Thu Nov  9 05:43:57 UTC 2023
  network time: Diff in /checkout/library/alloc/src/vec/mod.rs at line 65:
  network time: Diff in /checkout/library/alloc/src/vec/mod.rs at line 65:
 use core::ptr::{self, NonNull};
 use core::slice::{self, SliceIndex};
 
-use crate::alloc::failure_handling::{FailureHandling, DefaultFailureHandling, Fatal, Fallible};
+use crate::alloc::failure_handling::{DefaultFailureHandling, FailureHandling, Fallible, Fatal};
 use crate::alloc::{Allocator, Global};
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
##[error]Diff in /checkout/library/alloc/src/vec/mod.rs at line 681:
 }
 }
 impl<T, A: Allocator> Vec<T, A, Fallible> {
-    /// Like the other `with_capacity_in`, but returns `Err` instead of 
-    /// panicking when allocation size exceeds `isize::MAX` or 
+    /// Like the other `with_capacity_in`, but returns `Err` instead of
+    /// panicking when allocation size exceeds `isize::MAX` or
     /// aborting on allocation failure.
     #[inline]
     #[unstable(feature = "allocator_api", issue = "32838")]
##[error]Diff in /checkout/library/alloc/src/vec/mod.rs at line 3244:
 impl<T, A: Allocator> Vec<T, A, Fallible> {
     // leaf method to which various SpecFrom/SpecExtend implementations delegate when
     // they have no further optimizations to apply
-    fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) -> Result<(), TryReserveError> {
+    fn extend_desugared<I: Iterator<Item = T>>(
+        mut iterator: I,
+    ) -> Result<(), TryReserveError> {
         // This is the case for a general iterator.
         //
         //
         // This function should be the moral equivalent of:
##[error]Diff in /checkout/library/alloc/src/vec/mod.rs at line 3272:
 
     // specific extend for `TrustedLen` iterators, called both by the specializations
     // and internal places where resolving specialization makes compilation slower
-    fn extend_trusted(&mut self, iterator: impl iter::TrustedLen<Item = T>) -> Result<(), TryReserveError> {
+        &mut self,
+        &mut self,
+        iterator: impl iter::TrustedLen<Item = T>,
+    ) -> Result<(), TryReserveError> {
         let (low, high) = iterator.size_hint();
         if let Some(additional) = high {
             debug_assert_eq!(
##[error]Diff in /checkout/library/alloc/src/vec/mod.rs at line 3405:
     A1: Allocator,
     A2: Allocator,
     FH1: FailureHandling,
-    FH2: FailureHandling
+    FH2: FailureHandling,
     #[inline]
     #[inline]
     fn partial_cmp(&self, other: &Vec<T, A2, FH2>) -> Option<Ordering> {
##[error]Diff in /checkout/library/alloc/src/vec/partial_eq.rs at line 1:
-use crate::alloc::{Allocator, failure_handling::FailureHandling};
+use crate::alloc::{failure_handling::FailureHandling, Allocator};
 #[cfg(not(no_global_oom_handling))]
 use crate::borrow::Cow;
 
##[error]Diff in /checkout/library/alloc/src/vec/extract_if.rs at line 1:
-use crate::alloc::failure_handling::{FailureHandling, DefaultFailureHandling};
+use crate::alloc::failure_handling::{DefaultFailureHandling, FailureHandling};
 use crate::alloc::{Allocator, Global};
 use core::ptr;
 use core::slice;
##[error]Diff in /checkout/library/alloc/src/vec/try_spec_extend.rs at line 1:
 use crate::alloc::failure_handling::Fallible;
+use crate::alloc::Allocator;
 use crate::collections::TryReserveError;
 use core::iter::TrustedLen;
 use core::iter::TrustedLen;
 use core::slice::{self};
##[error]Process completed with exit code 1.
Post job cleanup.

type Result<T, E> = T;
}

/// Handle allocation failure falliblyby returning a `Result`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Handle allocation failure falliblyby returning a `Result`.
/// Handle allocation failure fallibly by returning a `Result`.


/// Handle allocation failure globally by panicking / aborting.
#[derive(Debug)]
pub struct Fatal;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub struct Fatal;
#[non_exhaustive]
pub enum Fatal {}

Maybe?

@fmease
Copy link
Member

fmease commented Nov 9, 2023

In order to limit the impact on the std docs, I used a trait alias for std::vec::Vec

You mistyped “type alias” as “trait alias” in the PR description.

@fmease
Copy link
Member

fmease commented Nov 9, 2023

And, I think it should generate a static html page rather than depending on the JS-based type alias inlining

This was a very intentional decision to fix page size explosions (issue #115718, Zulip discussion, PR #116471).

@pitaj
Copy link
Contributor Author

pitaj commented Nov 9, 2023

Oh I know why that was chosen. To be clear, I'm saying that doc(inline) would opt into full html inlining instead. That should have a pretty limited effect on html size.

@pitaj
Copy link
Contributor Author

pitaj commented Nov 28, 2023

I'm considering moving the generic parameter into Allocator:

trait Allocator<FH: FailureHanding = Fatal>

The benefit of this is that for the normal case, nobody needs to worry about what that third generic parameter does.

One question is whether the FH parameter should affect the output of the allocation functions. But Allocator<Fatal> has to be able to provide Vec::try_reserve so that's not an option.

@matthieu-m
Copy link
Contributor

I'm considering moving the generic parameter into Allocator:

trait Allocator<FH: FailureHanding = Fatal>

The benefit of this is that for the normal case, nobody needs to worry about what that third generic parameter does.

Wasn't this the approach you already experimented with in PR #111970, which this PR supercedes?

One question is whether the FH parameter should affect the output of the allocation functions. But Allocator<Fatal> has to be able to provide Vec::try_reserve so that's not an option.

I am afraid that try_reserve is not really an isolated case, either. And bundling it "just because it hides it" seems like a poor justification.


I think there are two distinct usecases, which may be at odds.

On the one hand, moving the allocation failure strategy to the allocator may possibly provide a performance benefit, both internally and to consumers, by eliminating the need to check for a potential failure at every step of the way and by (possibly) improving return argument passing (Result may be inflating the size, causing a demotion from register to stack passing).

I would argue that this is a case for making the error on an associated type on the Allocator. Not only could a specific implementation opt to fail internally, and thus use ! for its associated error type, but other implementations could possibly provide more in-depth errors causes than AllocError.

It also seems orthogonal to support for fallible allocations in containers, to be honest.

On the other hand, a single container or algorithm may have different strategies for handling allocation failure depending on the context. This is seen here by Vec::reserve and Vec::try_reserve, but may also apply to implementing transaction semantics where failure during the transaction itself is fine (rollback is possible) but failing during the commit isn't (part of the changes cannot be rolled back any longer), etc...

In such case, the allocator is NOT in position to take the decision, which leaves us with two choices:

  1. Duplicate all allocation methods for both faillible and infallible options: allocate vs try_allocate, +grow +zeroed variants.
  2. Don't handle fallibility in the allocator at all, it's none of its concern.

And if the allocator doesn't handle fallibility, then it's not clear why it should be concerned about FailureHandling. It clearly isn't its responsibility.

So if the only argument is "one less argument on containers", I must admit I find it fairly shallow:

  • Either people care about it, and thus should be okay having the extra argument -- or they should make an alias with their selected policy.
  • Or people don't care about it, and they should be using an alias of the container which hides all the gory details.

@pitaj
Copy link
Contributor Author

pitaj commented Nov 28, 2023

Wasn't this the approach you already experimented with in PR #111970, which this PR supercedes?

No, that had an associated type on Allocator.

I am afraid that try_reserve is not really an isolated case, either.

I know, it was just an example.

And bundling it "just because it hides it" seems like a poor justification.

I really don't understand what you mean by this. Can you expand on this?

Thinking about this again, I think we could just implement try_reserve etc only when we have a Fatal allocator that also implements Allocator<Fallible>:

impl<T, A: Allocator<Fatal>> Vec<T, A> {
    fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
    where A: Allocator<Fallible>
    { ... }
}

Because if someone has an Allocator<Fallible> they can just use reserve directly.

Everything you said below the line makes sense to me.

@matthieu-m
Copy link
Contributor

Because if someone has an Allocator<Fallible> they can just use reserve directly.

I'd be wary of going down that road, as it would be a pain for code generic over the fallibility.

No, that had an associated type on Allocator.

Good point, I read the default argument as being an associated type constraint somehow.

I am not sure if this would play well with specialization. On stable, at least, it's no possible to implement Allocator<FH: FailureHandler> and Allocator<Fatal> for the same type see playground, so it seems that an allocator either works with all FailureHandler or works only for a few specific ones. And that's not great:

  1. An allocator working for a few specific FailureHandler cannot be used in a generic context.
  2. An allocator working for all FailureHandler cannot have a fast-path for some (absent specialization).

Then again, arguably, an allocator that is unaware of any FailureHandler cannot specialize for it either, so (2) may not be an issue?

(It does seem to make the question about try_reserve void, though)

@pitaj
Copy link
Contributor Author

pitaj commented Nov 29, 2023

An allocator working for a few specific FailureHandler cannot be used in a generic context.

Well the plan is that only two will ever exist: Fatal and Fallible.

So my idea would be that if you only support one or the other, you only implement one or the other. Otherwise you'd implement both Allocator<Fatal> and Allocator<Fallible>

@matthieu-m
Copy link
Contributor

Well the plan is that only two will ever exist: Fatal and Fallible.

So my idea would be that if you only support one or the other, you only implement one or the other. Otherwise you'd implement both Allocator<Fatal> and Allocator<Fallible>

This makes me wonder whether this would be better modeled with a const generic parameter, specifically a const generic enum, rather than a (sealed, I presume?) trait.

Though I am not sure where the support's at...

@pitaj
Copy link
Contributor Author

pitaj commented Nov 30, 2023

I'm not sure about the status of adt_const_generics either. But AFAIK a const generic wouldn't allow the different Allocator modes to have different function return types, you have to have a trait with an associated type for that.

@Noratrieb
Copy link
Member

Im going to mark this as S-experimental, this doesn't look like it's waiting for a review.

@Noratrieb Noratrieb added S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state. F-non_exhaustive_omitted_patterns_lint `#![feature(non_exhaustive_omitted_patterns_lint)]` and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. F-non_exhaustive_omitted_patterns_lint `#![feature(non_exhaustive_omitted_patterns_lint)]` labels Jan 22, 2024
@Dylan-DPC
Copy link
Member

Closing this as it was an experiment

@Dylan-DPC Dylan-DPC closed this Apr 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-experimental Status: Ongoing experiment that does not require reviewing and won't be merged in its current state. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants