Idiomatic way of implementing From trait for more than one arguments

Hi. I have a Gc<T> struct (garbage collected smart pointer) that needs a value and a garbage collector that it will belong to for being constructed. Something like this:

struct GarbageCollector { ... }
struct Gc<T> { ... }

impl<T> Gc<T> {
    pub fn new(value: T, collector: &GarbageCollector) -> Self {}
}

I thought that converting a Box<T> into a Gc<T> would be reasonable, so I tried implementing the From<Box<T>> for Gc<T>. But I can't construct a Gc without having the garbage collector. So the only way of solving this that I can think of is something like this:

impl<T: Trace> From<(Box<T>, &GarbageCollector)> for Gc<T> {
	fn from(value: (Box<T>, &GarbageCollector)) -> Self {
		...
	}
}

Do you think that this solution is idiomatic? Would you suggest me to use a method like from_box(box: Box<T>, collector: GarbageCollector) -> Self instead or is the above solution fine?

I don't think I would implement From in this case.

4 Likes

The only nice option I can see would be to implement a global garbage collector. Otherwise I'd do as @alice said, and not implement From. From by definition takes one input, and kludging this with a tuple does not improve clarity. Instead you'd probably implement a method on your GarbageCollector like from_box.

2 Likes

Oh, but the whole point of my library is being able to use garbage collectors without being tied to one global, thread local garbage collector :slight_smile:

I will probably make it an ordinary method.

Yeah, that would make a big difference. But in that case, surely your Gc<T> should also have all lifetime parameter?

It currently has two lifetime parameters. I didn't write them in the above examples.

I read the source code of rust-gc. The main difference between rust-gc and my code is that my lifetime parameters are generic, while rust-gc uses 'static since the garbage collector is also a thread local static.

Yeah I would probably make this an ordinary method.

Is there some way to benefit from auto-dereferencing the Box?

Like if we do

let my_thing = Box::new("thing");
let gc_thing = Gc::new(my_thing, gc);

Would rust know that it can Deref my_thing if needed? I guess not since new() doesn't take a reference... Hmm. It might even compile fine and put the entire Box inside Gc.

Yes, it does this. But you can dereference the box yourself. Now I don't think I even need a method like from_box, making this method more performant than passing the box to the Gc::new seems imposible because of the memory layout of garbage collected objects.