Is there a way to prevent Weak :: new () from being allocated?

Next Steps Why doesn't Weak :: new () work when Rc :: downgrade () does?

When I try to implement Weak::new() in such a way that it would NOT be required that it allocate memory for the base type, even if it will never be used, I ended up in a checkpoint.

The definition of RcBox<T> quite simple:

 struct RcBox<T: ?Sized> { strong: Cell<usize>, weak: Cell<usize>, value: T, } 

And the goal here is to create an RcBox<T> that does NOT actually contain value . Essentially RcBox<()> .

However, there is a clue. *mut RcBox<()> is a thin pointer, but *mut RcBox<T> is a potentially thick pointer. We have some data from this fat pointer, but there are many different cases of fat pointers, so trying to synthesize the rest is tough .

As you can see from the related question, I can make it work only for objects with objects:

 impl<T: ?Sized> Weak<T> { pub fn new() -> Weak<T> { unsafe { let boxed = Box::into_raw(box RcBox { strong: Cell::new(0), weak: Cell::new(1), value: (), }); let ptr = if size_of::<*mut ()>() == size_of::<*mut T>() { let ptr: *mut RcBox<T> = transmute_copy(&boxed); ptr } else { let ptr: *mut RcBox<T> = transmute_copy(&TraitObject { data: boxed as *mut (), vtable: null_mut(), }); ptr }; Weak { ptr: Shared::new(ptr) } } } } 

However, this will not work with str (for example).

I tried to isolate the fixed-size RcBox part, allowing the compiler to output the bold part of the pointer:

 struct RcBox<T: ?Sized> { counters: RcBoxCounters<T>, value: T, } struct RcBoxCounters<T: ?Sized> { strong: Cell<usize>, weak: Cell<usize>, _phantom: PhantomData<T>, } impl<T: ?Sized> Weak<T> { pub fn new() -> Weak<T> { unsafe { let boxed = Box::into_raw(box RcBox::Counters::new(0, 1)); Weak { ptr: Shared::new(boxed as *mut RcBox<T>) } } } } 

which sounds very smart until the compiler suppresses your enthusiasm:

 error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions --> <anon>:58:40 | 58 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RcBox<U>> for RcBox<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions | = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: counters (RcBoxCounters<T> to RcBoxCounters<U>), value (T to U) 

I.e:

  • I think that in order for the compiler to synthesize the bold part, I need PhantomData in RcBoxCounters ,
  • however, this requires 2 transformations for coercion, which is not allowed.

So, is there a way to fix Weak::new() so that it does not allocate extraneous (unnecessary) memory?

Note. I mean allocating only space for two counters, after which allocating large and trimming DOES NOT help.

Note. It was noted that to indicate the absence of a value, you can use Option or a special value. This requires branching for each method, which may be undesirable. I prefer to learn to play with bold pointers.

+8
rust
source share

No one has answered this question yet.

See similar questions:

2
Why does Weak :: new () not work when Rc :: downgrade () is executed?

or similar:

23
Call Rust with Java
6
Is it possible to map a function over Vec without allocating a new Vec?
5
How to return a dynamic-length vector to an extern "C" fn pub?
4
Is it possible to implement "PartialEq" to reference a property that returns "true" for instances of implementations that have the same internal content?
4
Is it possible to select a feature object at runtime without using Box <Trait>?
3
Time limits for garbage collection simulations
one
Return non-trivial gstreamer "callbacks" as closed boxes
one
Borrowing from Weak <t>
one
Factory method: the instance does not live long enough
0
Encoding stronger WinApi security through Rust RFI

All Articles