Use a generic type only for method invocations, not struct data

How can I ensure that all invocations of a method fn foo<T>(&self, x: T) where T: SomeTrait have the same concrete type for a specific instance of a struct?

I tried struct Thing<T> { field: u32 }, but that complains about an unused generic parameter, forcing me to place the <T> on the function. But placing it on the function allows multiple invocations with different concrete types over the life of Thing.

Is PhantomData the only option? I’d rather not use it to make struct construction easier.

Yes, you must use PhantomData to do this.

What are you trying to do? There may be a better way than what you can think of.

My struct contains a few “graphical” items, that need to be laid out on a page. I want to make sure that each call to layout and item is called with an instance of the same kind of page, otherwise their final co-ordinates will be jumbled.

Now that I think about it, I might be able to just make the Layout struct have a reference to a page. I had been avoiding that because of lifetime issues, since I could not mutate the page as long as any layouts existed if the layouts had a reference to the page, but maybe I can use a second type (e.g. FinalisedLayout) that doesn’t hold a reference to work around that.

edited to add:
My flow currently is something like this:

let mut p = Page::new();

let mut front = Layout::new();
front.add(x, y, z);
front.measure(x, &p);
front.measure(y, &p);
front.measure(z, &p);

let mut back = Layout::new();
//...

let mut r = Renderer::new(&mut p);
r.render(front);
r.render(back);

The problem I ran into was that front and back are needed after the call to Renderer::new(...), which needs a &mut Page, so I was avoiding having Layout keep a reference to Page.

I’ve solved this by moving some functions from Layout to Page, which solved the lifetime issues I was having earlier.

1 Like