2

For a project I'm using a library in Rust which has the following structs & traits:

struct Server<C> { c: C, } impl<C: Customization> Server<C> { type R<'s> = ResultImpl<'s, C> where Self: 's; fn query<'s>(&mut self) -> Self::R<'_> { ResultImpl(self) } } trait Customization {} struct CustomizationImpl<'c> { reference: &'c Foo, } struct Foo {} impl Customization for CustomizationImpl<'_> {} trait Result {} struct ResultImpl<'s, C: Customization>(&'s mut Server<C>); impl<'s, C: Customization> Result for ResultImpl<'s, C> {} 

I know, it seems a bit odd that a Result holds a reference to a Server, but let's assume we can't change the code.

Now I want a wrapper around the Server struct. What I tried was the following:

struct Wrapper<'w> { server: Server<CustomizationImpl<'w>>, } impl<'w> Wrapper<'w> { fn query(&'w mut self) -> ResultImpl<'_, CustomizationImpl> { self.server.query() } } 

But then, I can't call query() more than once on Wrapper.

//compiles let mut server = Server { c: CustomizationImpl { reference: &Foo {} } }; server.query(); server.query(); //does not compile let mut wrapper = Wrapper { server: Server { c: CustomizationImpl { reference: &Foo {} } }, }; wrapper.query(); wrapper.query(); 

With error error[E0499]: cannot borrow wrapper as mutable more than once at a time. You can also find my code at https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=eebfd28e33f5354ffe9b46ff121f5f89

Is there any way to wrap the Server struct?

2
  • Just remove the 'w from &'w mut self in query(). Commented Dec 15, 2022 at 22:18
  • If I do so, I'll get another error: error: lifetime may not live long enough Commented Dec 15, 2022 at 23:15

1 Answer 1

1

Your Wrapper lifetime declarations are wrong. Your code is actually equivalent to this one:

impl<'w> Wrapper<'w> { fn query(&'w mut self) -> ResultImpl<'w, CustomizationImpl<'w>> { self.server.query() } } 

But the two lifetimes in the output type should be unrelated. And creating a value of a type such as &'x Type<'x> is known to cause issues such as yours.

The solution is something like this, having the lifetime of self and that of the generic separated:

impl<'w> Wrapper<'w> { fn query<'s>(&'s mut self) -> ResultImpl<'s, CustomizationImpl<'w>> { self.server.query() } } 
Sign up to request clarification or add additional context in comments.

1 Comment

A nitpick: &'x Type<'x> is usually fine (it is not very different from using the same lifetime for two different & references); it is only the mutable version &'x mut Type<'x> that causes trouble (because &mut T is invariant in T).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.