-
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
Question: Can omit the <A: Allocator> generic param for the immutable references? #110
Comments
You can define a struct CollectionData<'a> {
some_data: &'a i32,
another_data: &'a [u32],
} This is similar to passing |
Thanks for the suggestion! 🙏 Yes that's one of the very possible solutions, which has some positive properties compared to the solution defining a new
though it has some downsides:
If there's any other solutions, please let me know, thanks! |
To avoid writing duplicate code, you could create a sealed trait with functions that return references to the field values and default functions that implement the rest of the behavior. |
You could only define
|
I'm not sure what the safety implications of transmuting between references of types are; wrapping the original allocator should at least make the layouts the same:
|
I had to deal with this too. The way I usually write these is have a plain, module-private function that receives all the params from either the collection or the view, and does the stuff. The associated functions on the collection and view types then call into this plain function. It doesn't look very pretty inside the module with your collection, but the outside looks rather clean. |
The original question deals with shared references to a collection, but I tend to run into this with unique references a lot, too. I wish there was a way to write underscore as a type parameter in the function parameters, when I still want the function to be generic over the allocator, but don't want to interact with it directly: fn do_stuff(data: &mut MyCollection<u32, _>) {} (Yes, I know this would be a huge language change, and is mostly a pipedream) How are other people dealing with the additional type parameters? |
Yeah, we've no idea if rustc places
An |
What's stopping you from defining a type that borrows from your collection type and doesn't use an allocator? |
@burdges Yeah, I used Otherwise, I agree Your other suggestion with |
Yes I'd think It's maybe best if proc macro crates explore some view types tooling. Also https://internals.rust-lang.org/t/blog-post-view-types-for-rust/15556 |
thanks everyone for the active responses!
True 👍, but I'm still not satisfying with this solution because I cannot stop comparing this solution with the simple
|
Assuming you're asking to me about why I'm not using the @Amanieu 's solution: For my case, in the example I described has only 2 fields, but in my real case the number of the fields can vary from 1 to possibly over 100. So if I use that method, then the overhead coming from the ref struct size and the ref struct construct time may be unignorable. |
One idea I'm testing now is introducing a collection type using the allocator but not storing the allocator. For example, for the replacement for the // Note `Vec::into_raw_parts_with_alloc()` returns `(*mut T, usize, usize, Alloc)`
pub struct NoAllocVec<T>(*mut T, usize, usize);
impl<T> NoAllocVec<T> {
// This method is needed to impl `Deref<Target=[T]>`
pub fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.0, self.1) }
}
// Generate something like `std::cell::RefMut<'_, Vec<T, A>>`.
// This method is unsafe because a different allocator with the one used when constructing
// this struct might be passed here, and we cannot tell that because we erased the allocator type
// information intentionally.
pub unsafe fn in_allocator<A>(&self, alloc: A) -> RefMutVec<T> {
//...
}
}
impl<T> Deref for NoAllocVec<T> {
type Target = [T];
// ...
} Then, I can write my larger pub struct MyCollection<A: ?Sized + Allocator> {
another_data1: NoAllocVec<u32>,
another_data2: NoAllocVec<u32>,
another_data3: NoAllocVec<u32>,
another_data4: NoAllocVec<u32>,
alloc: A,
} One of a benefits of writing like this is that I can remove the allocator instances from the field types. This can reduce the |
Instead of If your doing crates for general purpose data structures, then you should maybe emulate
|
Hello, 🙇♂
I was creating my own data structure using the <A: Allocator> generic param, say it's something like this:
and want to pass around this data type ref in my code:
Apparently, in this function the
<A: Allocator>
param is essentially redundant because we can assume the immutable methods does not use the allocator.This problem is nicely avoided in the basic std data types like
Box<T, A>
,Vec<T, A>
andString<A>
because those types have corresponding immutable types which omits<A>
param:&T
,&[T]
andstr
.But for the other types planned in issue #7 , like
BTreeMap<K, V, A>
, we have the same problem. The all users of theBTreeMap
need to know about the allocator even if it's just using theBTreeMap
instance in immutable way.Of course, one of the solution for this is to define a custom trait. But then I need to re-define the all immutable methods in that trait.
It's great if I can have something "official" or de facto standard crate for that, or maybe can use an implementation technique to extract out the immutable-reference type like
str
from the owned type.WDYT?
thanks,
The text was updated successfully, but these errors were encountered: