Creating Weak<T> from &T?

I presume I am missing something obvious. In some methods on a struct, I want to create a weak reference to the structure. As far as I can tell, for good reasons, I need to get to an Rc, and then I can call Rc::downgrade(...) to get to a Weak. But when I try to figure out how to create an Rc, I end up seeing various Clone methods. I don't want a reference to a clone of the object. And &Self is not an Rc. What am I missing?
Thanks,
Joel

For an Rc type the data is on the heap, so you can get a weak reference from it. But if you have a struct value on the stack, that should not work. Well, at least that is what I would assume -- I have never used weak references in Rust yet.

In Rust objects are not reference counted, and there's no garbage collection. If something isn't in Rc already, then it won't support Rc's Weak. There's no magic to uncover a hidden Weak. There's no special way of upgrading temporary references. Rc is always in-your-face explicit and if it's not obviously there, then it's not.

3 Likes

Thank you both. Sounds like I can't do what I want wiht a method on &self, but have to define methods that take Rc as a parameter, and probably a build method to build the Rc. I guess I am biased in my patterns because so much of what I work with assumes graphs / bi-directional trees, ...
Yours,
Joel

A reference is internally implemented in Rust as a simple pointer. It is basically only an address. A reference points directly to the referenced value.

But a Rc<T> and Weak<T is not simply a pointer or a reference, but a custom type (struct) containing a raw pointer to some other type containing additional management data, something similarly like this:

struct Rc<T> {
    pointer: *mut InternalRcNode<T>,
}

struct Weak<T> {
    pointer: *mut InternalRcNode<T>,
}

struct InternalRcNode<T> {
    strong_count: usize,
    weak_count: usize,
    value: MaybeUninit<T>,
}

(The real implementation differs)

So, obviously you can't create a Rc<T> or Weak<T> from a reference.

You can make fn method(self: Rc<Self>) when it requires use of reference counting.

&self is not merely a default, but also a type system promise that the method won't be able to keep self by any means.

2 Likes

If I am reading that right, it looks like what I am going to need. If I define a method as you give above, fn method (self: Rc, ...).... as part of the implementation of a struct (say DataStore), then can I in other places where I have an instance I of Rc, can I call I.method(....)? Or do I need to call DataStore::method(I, ...)?
Thank you,
Joel

Thanks for the further elaboration. I should have realized it from what I had read, but simply didn't put it together.
Yours,
Joel

Yes, you can do that whenever there is a self parameter. That is what makes a function callable using method call (dot) syntax.

If a function does not have a self parameter but is in an impl, then it is not a method, but only an associated function, and you can only call it using Type::function() syntax. (All methods are associated functions, but not all associated functions are methods.)

If your object is already in an Rc, then Rc::clone will not create a clone of the internal object; only new refcounted handle.

1 Like

Thanks. Still working through getting all this consistent, just wanted to acknoweldge that this is helping a great deal.
Yours,
Joel