-
Notifications
You must be signed in to change notification settings - Fork 9
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
Associated Err type for the Alloc trait #23
Comments
Disagree. All methods of |
I think the borrow-as-other-allocator type is much better, because it make it much easier for code vigilantly handling all allocation failures to make sure it doesn't accidentally panic by mistake. If I'm writing a kernel module, I want to still use libraries and be confident after some quick grepping that none of them use |
I've rebased my old PR rust-lang/rust#60703 |
@SimonSapin I disagree, |
… and add a separately-unstable field to force non-exhaustive matching (`#[non_exhaustive]` is no implemented yet on enum variants) so that we have the option to later expose the allocator’s error value. CC rust-lang/wg-allocators#23
Finalize the error type for `try_reserve` See tracking issue comments from rust-lang#48043 (comment). It is now: ```rust /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] pub enum TryReserveError { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). CapacityOverflow, /// The memory allocator returned an error AllocError { /// The layout of allocation request that failed layout: Layout, #[doc(hidden)] #[unstable(feature = "container_error_extra", issue = "0", reason = "\ Enable exposing the allocator’s custom error value \ if an associated type is added in the future: \ rust-lang/wg-allocators#23")] non_exhaustive: (), }, } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] impl From<LayoutErr> for TryReserveError { #[inline] fn from(_: LayoutErr) -> Self { TryReserveError::CapacityOverflow } } ``` Changes: * A `Layout` is included. Firefox wants to log the size of failed allocations. If this were not part of the return value of e.g. `HashMap::try_reserve`, users would only be able to estimate based on `HashMap::capacity` and assumptions about the allocation strategy of `HashMap`. * There’s a dummy field that can stay unstable when `try_reserve` and the rest of this enum are stabilized. This forces non-exhaustive matching ~(rust-lang#44109 is not implemented yet for variants)~ and allows adding another field in the future if we want to expose custom error values from the allocator. See rust-lang/wg-allocators#23. - If the `Alloc` trait is stabilized without an associated error type and with a zero-size `AllocErr` type, we can simply remove this dummy field. - If an associated type is added, we can add a default type parameter to `ContainerError` and a generic field to the `AllocError` variant. * ~Moved from the `collections` module to the `alloc` module, and replaced `Collection` in the enum name with `Container`. The wold collection implies a multiplicity of items which is not relevant to this type. For example we may want to use this error type in a future `Box::try_new` method.~ - Renamed to `TryReserveError`, after the methods that involve this type: rust-lang#61780 (comment) * Replaced `Err` with `Error` in the enum and variant names. There is more precedent for this in https://doc.rust-lang.org/std/error/trait.Error.html#implementors, `AllocErr` and `LayoutErr` are the odd ones. * ~Dropped `Alloc` in the enum name. `ContainerAllocError` with a mouthful, and being in the `alloc` module already provides the same indication.~
I don't think a new type has to be introduced for this: pub trait InfallibleAllocErr: fmt::Display {}
impl InfallibleAllocErr for ! {}
impl InfallibleAllocErr for std::convert::Infallible {}
impl<T, A: Alloc> Box<T, A>
where
A::Error: InfallibleAllocErr,
{
pub fn new_in(x: T, mut a: A) -> Self {
match Self::try_new_in(x, a) {
Ok(b) => b,
Err(e) => panic!("Infallible allocation failed: {}", e),
}
}
} Edit: Once the |
To get back to the OP, we should decide, if we want to experiment with an associated error type at all. trait AllocRef {
type Error;
...
}
Please vote with
|
I feel like the pro's and con's of each approach have not been discussed, at least on this issue, and it's too soon to make a decision. Is there another issue with discussion comparing Associated Type vs separate Trait? If so, could someone link a summary? I'm unclear on if any allocators are actually infallible. I know, most Linux OS's are configured to kill processes rather than fail malloc, but do the allocators themselves make any guarantee's about being infallible? If not, then there's no need to even handle that case. |
I'd like to remind, that voting this into nightly is by no mean a final decision. It's just for publishing the change to the rest of the rust community to try this out 🙂 |
I guess I had pushed "postpone" by mistake! |
I'm happy to push this into nightly as an experiment, but I would like this decision to be revisited before stabilizing the |
@Amanieu I would agree with all that; butdo also note that after rounds of discussion with @TimDiekmann and @gnzlbg, they've improved the |
There's a lot of discussion to go through, a summary with the latest ideas on using |
Based on the latest discussions, I think an allocator should never return |
I'll push the associated error upstream, but we have to listen carefully to the community, if this is useful or not. |
I agree. But that seems to be the only use case for an associated error type that people are seriously discussing. In theory an inhabited non-zero-size error type could be used by an allocator to return more details about what when wrong exactly, but I haven’t heard of anyone actually wanting to do this. So I’m a bit confused that you seem to both be in favor of having the associated type and think that its only use case is not a good idea. |
I wonder if no one has ever wanted something like this because they didn't know that it was theoretically possible, or if no one has ever seen a use-case. Especially because most people only use the collection API which never returns a One use case could be a tracing allocator, which prints every action (success + failures) with all possible information. #[cfg(debug_assertions)]
type Allocator = MyAllocWithCustomError;
#[cfg(not(debug_assertions))]
type Allocator = MyAlloc; I don't have an example currently, but I can also imagine an allocator, which uses FFI and the binding has a dedicating error logging API similar to |
It’s a fair point that no-one has done this with the current
These are all theoretical, so until someone comes with something more concrete (such as prior art in another language) I feel this is not a good way to spend complexity budget. |
I am pretty sure @TimDiekmann means that he does want |
I don’t understand what that means. Associated types are always associated to some trait. What trait would be relevant to allocation in containers if not |
I think like, to use a bit of Rust pseudo-code:
|
… which implies the existence of
|
Without an associated error type, it would just return |
If the consensus is that |
So what is the consensus here? Close this proposal? |
I would say close it for now. If a good use case for custom errors comes up while |
I opened #39 for the I would really like this to do this as soon as the unstable type params are ready, so I'd appreciate if we can vote on this issue too. |
FWIW, Besides |
@Ericson2314 I'm afraid I don't follow. If you substituted a different |
@scottjmaddox the idea is whenever one writes code which doesn't fix the |
First off, apologies if dropping into a closed issue of a working group's issue tracker out of nowhere is not appropriate. I'd like to make a case for an error type I didn't see in this issue yet: It allows to express that an implementation of an allocation-error-aware trait is infallible because it never allocates in the first place. Consider a trait like the following: trait AllocatorAwareClone<A: Alloc> {
fn clone(&self, alloc: A) -> Result<Self, A::Error>;
} Now suppose there is a struct |
#10 got a little too confusing, so I think it's good to separate this sub-issue into its own issue.
Currently, the
Alloc
trait looks like this:I propose that we add an associated type called
Err
. All methods that currently returnResult<_, AllocErr>
would returnResult<_, Self::Err>
.Then, the
std::alloc
module would contain anAbortAlloc
(or something named similarly).Then, types like
Vec
could have their normal methods that interact with the allocator only be implemented when theAlloc::Err
type is!
. Otherwise, thetry_*
methods would be available which would propagate the error upwards.Additionally, the
new_in
/etc methods would take anInto<A>
parameter so that the user experience of creating an infallible collection wouldn't require the user to explicitly wrap their allocator in anAbortAlloc
.The text was updated successfully, but these errors were encountered: