Can you specify the lifetime of a moved self parameter? - rust

I have a newtype struct:
pub struct Branch<'repo>(Git2Branch<'repo>);
And I am trying to wrap a method call:
impl <'repo> Branch<'_> {
pub fn into_reference(self) -> Git2Reference<'repo> {
self.0.into_reference()
}
}
(Git2Branch and Git2Reference here are aliases for types of the same name from the git2 crate.)
This fails to compile with
error: lifetime may not live long enough
--> git_wrapper/src/branch.rs:38:9
|
6 | impl <'repo> Branch<'_> {
| ----- lifetime `'repo` defined here
...
37 | pub fn into_reference(self) -> Git2Reference<'repo> {
| ---- has type `branch::Branch<'1>`
38 | self.0.into_reference()
| ^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'repo` but it is returning data with lifetime `'1`
Lifetimes '1 and 'repo should be the same, but I can't figure out how (or if it's even possible) to specify the lifetime of self in this case.

impl <'repo> Branch<'_> {
Is the same as:
impl <'repo, 'anonymous> Branch<'anonymous> {
So the lifetimes 'repo and the anonymous lifetime of the field are unrelated - which causes an issue when you try to return the Git2Reference<'anonymous>.
You only need to talk about one lifetime here, so say that:
impl <'repo> Branch<'repo> {

Related

access reference in struct causes cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

I'm implementing a web service using tonic grpc crate.
Here is the my code:
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;
fn main() {
let my_struct = MyStruct {data_ref: RefCell::new(None), data: vec![MyData(28)]};
my_struct.my_fun();
// my_struct.my_fun_is_gone(); This is not working.
println!("{}", my_struct.data_ref.borrow().deref().unwrap().0);
}
/// AUTO GENERATED CODE OR THIRD PARTY TRAITS
///for example tonic generated Grpc services
trait TonicGeneratedGrpcService {
fn my_fun_is_gone(&self); //so I Can't change the &self lifetime parameter
}
struct MyData(u8);
struct MyStruct<'a> {
data: Vec<MyData>, //this struct is owns this property, there is no any problem
data_ref: RefCell<Option<&'a MyData>>, //And sometimes I want to save the data
}
impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits, change the lifetime parameters also requires change the super trait's method's lifetime.
//***********COMPILER ERROR is occurred HERE, how can I make this working?*************
let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
*self.data_ref.borrow_mut() = Some(some_of_data);
}
}
impl<'a> MyStruct<'a> {
//Below code is works fine if this is myself defined method, but I can't change the lifetime of "self" in super traits if this is a implementation of tonic generated service or other third party traits
fn my_fun(&'a self) {
let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
*self.data_ref.borrow_mut() = Some(some_of_data);
}
}
My final purpose is save the reference that one of the Vec<MyData> into data_ref field at runtime by some conditions.
Here is the compiler error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:28:29
|
28 | let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/main.rs:26:23
|
26 | fn my_fun_is_gone(&self) { //I can't change the &self lifetime parameter because this is just an implementation of some super traits,...
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:28:29
|
28 | let some_of_data = &self.data[0]; //Maybe &self.data[1], &self.data[2]...
| ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
--> src/main.rs:25:6
|
25 | impl<'a> TonicGeneratedGrpcService for MyStruct<'a> {
| ^^
note: ...so that the expression is assignable
--> src/main.rs:29:39
|
29 | *self.data_ref.borrow_mut() = Some(some_of_data);
| ^^^^^^^^^^^^^^^^^^
= note: expected `Option<&'a MyData>`
found `Option<&MyData>`
I can't change the source code of TonicGeneratedGrpcService trait because it may be in the third party crate or auto generated code,
and now I cannot find any way to make work the my_fun_is_gone method implementation.
Should I avoid the lifetime and use reference counted pointers (Rc, Arc) rather then save reference (&MyData) directly in struct MyStruct?
Or there any way to make work this?
As others said, Rust's lifetime system doesn't allow self-referential struct.
To solve this, you may directly store the index integer in the data_ref if data vec is only appended. Depending on your use case, you can also consider other options here Why can't I store a value and a reference to that value in the same struct?

Why rust told me that a reference still borrowed at the end of main function?

As you can see in the following code, I have two traits, one is called Hittable, and the other is called Material (I have been studying the book "ray-tracing-in-one-weekend", but use Rust).
The Hittable trait implements hit function for some objects (just like Sphere in this code), and every kind of objects includes its material (just like Glass, Wood...).
In my real project, the Sphere struct and another struct (called HitRecord in this book, used as mut reference to pass result in hit function), they both include &dyn Material, so that I need add lifetime parameter for both of them. However, to accomplish that, I should add lifetime parameter in the trait declaration, so I can assign the same lifetime parameter for Sphere and hit.
But the compiler indicates that the reference still under borrowed when the main function ends, I have no idea for that...
trait Hittable<'a> {
fn hit(&self);
}
trait Material {
fn result(&self);
}
struct Glass;
impl Material for Glass {
fn result(&self) {
println!("Glass is broken!");
}
}
struct Sphere<'a> {
name: String,
mat_ptr: &'a dyn Material,
}
impl<'a> Hittable<'a> for Sphere<'a> {
fn hit(&self) {
println!("Name is {}", self.name);
self.mat_ptr.result();
}
}
struct HT<'a> {
pub objects: Vec<Box<dyn Hittable<'a>>>,
}
fn main() {
let mut list = HT { objects: vec![] };
let surface_material = Glass;
let s = Sphere {
name: String::from("球"),
mat_ptr: &surface_material,
};
list.objects.push(Box::new(s));
}
the message shows
Compiling rust_test v0.1.0 (/home/hnyls2002/rust_test)
error[E0597]: `surface_material` does not live long enough
--> src/main.rs:38:18
|
38 | mat_ptr: &surface_material,
| ^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| cast requires that `surface_material` is borrowed for `'static`
...
41 | }
| - `surface_material` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
This is because dyn Hittable<'a> is actually dyn Hittable<'a> + 'static, and thus s is required to live for 'static. The fix is to change HT to:
struct HT<'a> {
pub objects: Vec<Box<dyn Hittable<'a> + 'a>>,
}
Then you'll get a long but pretty self-explanatory error:
error[E0597]: `surface_material` does not live long enough
--> src/main.rs:38:18
|
38 | mat_ptr: &surface_material,
| ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
41 | }
| -
| |
| `surface_material` dropped here while still borrowed
| borrow might be used here, when `list` is dropped and runs the destructor for type `HT<'_>`
|
= note: values in a scope are dropped in the opposite order they are defined
Because surface_material is defined after list, it'll be dropped before and when the potential destructor for dyn Hittable will run it may access the freed surface_material. The fix is just to swap the declaration order of list and surface_material:
fn main() {
// always define before the container you are pushing into
let surface_material = Glass;
let mut list = HT { objects: vec![] };
// ...
}

Lifetime issues when refactoring into function with closure back-call

I am writing a Rust application that uses the wgpu library to render stuff. How the library works is largely unimportant, since the errors I'm facing are lifetime-related.
In the function that actually performs the rendering looks like this: (You don't need to understand it, I listed it largely for completeness' sake.)
pub fn render(&self) -> anyhow::Result<()> {
let output = self.surface.get_current_texture()?;
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor { label: Some("render encoder") }
);
let render_pass_descriptor = wgpu::RenderPassDescriptor {
label: Some("render pass"),
color_attachments: &[
wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(
wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 }),
store: false,
}
},
],
depth_stencil_attachment: None,
};
let mut render_pass = encoder.begin_render_pass(&render_pass_descriptor);
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.draw(0..self.num_vertecies, 0..1);
// Explicitly drop, bc. it borrows the encoder.
drop(render_pass);
self.queue.submit(iter::once(encoder.finish()));
output.present();
Ok(())
}
I wanted to refactor this piece of code into a utility function, but keep the three calls on the render_pass object.
The utility function has this signature and does the same stuff the original function did, but instead of the three calls on render_pipeline, it just calls the render_pass_configurator closure:
pub fn submit_render_pass<F: FnOnce(wgpu::RenderPass)>(
surface: &wgpu::Surface,
device: &wgpu::Device,
queue: &wgpu::Queue,
clear_color: wgpu::Color,
render_pass_configurator: F,
) -> anyhow::Result<()> { ... }
And the body of the original render() function is replaced with the call to this utility function:
util::submit_render_pass(&self.surface, &self.device, &self.queue,
wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 },
| mut render_pass | {
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
render_pass.draw(0..self.num_vertecies, 0..1);
},
)
Seems straightforward to me, but of course Rust's borrow checker disagrees:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/gpu.rs:89:38
|
89 | render_pass.set_pipeline(&self.render_pipeline);
| ^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined here...
--> src/gpu.rs:85:19
|
85 | pub fn render(&self) -> anyhow::Result<()> {
| ^^^^^
note: ...so that reference does not outlive borrowed content
--> src/gpu.rs:89:38
|
89 | render_pass.set_pipeline(&self.render_pipeline);
| ^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined here...
--> src/gpu.rs:88:9
|
88 | / | mut render_pass: wgpu::RenderPass | {
89 | | render_pass.set_pipeline(&self.render_pipeline);
90 | | render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
91 | | render_pass.draw(0..self.num_vertecies, 0..1);
92 | | },
| |_________^
note: ...so that the types are compatible
--> src/gpu.rs:89:25
|
89 | render_pass.set_pipeline(&self.render_pipeline);
| ^^^^^^^^^^^^
= note: expected `&mut RenderPass<'_>`
found `&mut RenderPass<'_>`
(... and a similar error for the .slice(..) call.)
I understand that because of the render_pass.set_pipeline(&self.render_pipeline) call, render_pass may not ever live longer than &self. But it doesn't. render_pipeline gets dropped at the end of the closure, and &self lives on.
I tried adding lifetimes to the best of my ability, and I got the error to change only once when I added an explicit lifetime to the type of the utility function, changing the closure definition to F: FnOnce(wgpu::RenderPass<'a>): (But this error didn't make much sense to me either.)
error[E0597]: `view` does not live long enough
--> src/gpu_util.rs:130:23
|
112 | pub fn submit_render_pass<'a, F: FnOnce(wgpu::RenderPass<'a>)>(
| -- lifetime `'a` defined here
...
130 | view: &view,
| ^^^^^ borrowed value does not live long enough
...
143 | render_pass_configurator(render_pass);
| ------------------------------------- argument requires that `view` is borrowed for `'a`
...
149 | }
| - `view` dropped here while still borrowed
Update
I got it to work by writing the render() function like this: (Self == GpuState)
pub fn render(&self) -> anyhow::Result<()> {
fn configure_render_pass<'a>(s: &'a GpuState, mut render_pass: wgpu::RenderPass<'a>) {
render_pass.set_pipeline(&s.render_pipeline);
render_pass.set_vertex_buffer(0, s.vertex_buffer.slice(..));
render_pass.draw(0..s.num_vertecies, 0..1);
}
util::submit_render_pass(&self.surface, &self.device, &self.queue,
wgpu::Color { r: 0.1, g: 0.2, b: 0.3, a: 1.0 },
| render_pass: wgpu::RenderPass<'_> | {
configure_render_pass(self, render_pass);
},
)
}
I think what makes it work here is that I get a chance to explicitly tell the compiler that the captured self lives as long as the render_pass. But that's only my guess...
I'll leave the question open, if anyone comes up with a solution to make it work without the extra function declaration.
pub fn submit_render_pass<F: FnOnce(wgpu::RenderPass)>(
surface: &wgpu::Surface,
device: &wgpu::Device,
queue: &wgpu::Queue,
clear_color: wgpu::Color,
render_pass_configurator: F,
) -> anyhow::Result<()> { ... }
First of, all, you have a hidden lifetime parameter, which can give rise to very confusing errors. Add the #![deny(elided_lifetimes_in_paths)] lint setting to your code to force these to be explicit. (It's unfortunate that that lint isn't on by default.) You'll be required to change the code to…
pub fn submit_render_pass<F: FnOnce(wgpu::RenderPass<'???>)>(
And now we see part of the problem: what goes in the spot I've marked '???? The RenderPass borrows from the CommandEncoder (the signature of CommandEncoder::begin_render_pass() tells us that), but the CommandEncoder is a local variable inside submit_render_pass(), so borrows of it cannot have a lifetime that is nameable from outside the function.
To solve this problem, you need to use a HRTB to specify that the callback function must be able to accept any lifetime:
pub fn submit_render_pass<F>(
surface: &wgpu::Surface,
device: &wgpu::Device,
queue: &wgpu::Queue,
clear_color: wgpu::Color,
render_pass_configurator: F,
) -> anyhow::Result<()>
where
F: for<'encoder> FnOnce(wgpu::RenderPass<'encoder>)
{ ... }

Constraint associated type of a generic associated type

I have a type Builder with a Generic Associated Type (GAT) InstanceForBuilder<'a>.
I'd like to write a function (build_with_42_for_bool<Builder>) that constraints the Builder to only those cases where Builder::InstanceForBuilder<'a>::InstanceProperty == bool (for all 'a).
I've been playing around for a while to get the syntax around this for <'a> right, but haven't been able to make this work.
The lifetime can't be a template argument of the function itself, because the reference only lives inside it.
Is this possible at all yet, given that GAT is an unstable feature?
playground
#![feature(generic_associated_types)]
// Trait definitions.
trait Builder {
type InstanceForBuilder<'a>: Instance<'a>;
fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a>;
}
trait Instance<'a> {
// Some functions will only work when the instance has some concrete associated type.
type InstanceProperty;
}
fn build_with_42_for_bool<B: Builder>(builder: B)
where
// TODO: What do I put here to make this work?
for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
{
builder.build(&42);
// Do some testing here. The Instance won't be returned.
}
// Now try it out.
struct MyBuilder;
struct MyInstance<'a> {
val: &'a usize,
}
impl Builder for MyBuilder {
type InstanceForBuilder<'a> = MyInstance<'a>;
fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a> {
MyInstance { val }
}
}
impl<'a> Instance<'a> for MyInstance<'a> {
type InstanceProperty = bool;
}
fn main() {
let builder = MyBuilder;
build_with_42_for_bool(builder); // TODO: Doesn't work
}
In my actual code, build_with_42_for_bool is a helper for testing that constructs the arguments passed to build in a specific way. For now I'll probably just inline that function everywhere, since the only problem is how to specify the lifetime of this one function. The code itself works fine.
Here's the full error:
Compiling pairwise-aligner v0.1.0 (/home/philae/git/eth/git/astar-pairwise-aligner)
error[E0271]: type mismatch resolving `for<'a> <<_ as Builder>::InstanceForBuilder<'a> as Instance<'a>>::InstanceProperty == bool`
--> examples/test.rs:45:5
|
45 | build_with_42(builder); // TODO: Doesn't work
| ^^^^^^^^^^^^^ expected `bool`, found associated type
|
= note: expected type `bool`
found associated type `<<_ as Builder>::InstanceForBuilder<'_> as Instance<'_>>::InstanceProperty`
= help: consider constraining the associated type `<<_ as Builder>::InstanceForBuilder<'_> as Instance<'_>>::InstanceProperty` to `bool`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: required by a bound in `build_with_42`
--> examples/test.rs:19:53
|
16 | fn build_with_42<B: Builder>(builder: B)
| ------------- required by a bound in this
...
19 | for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `build_with_42`
error[E0271]: type mismatch resolving `for<'a> <MyBuilder as Builder>::InstanceForBuilder<'a> == <MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:45:5
|
45 | build_with_42(builder); // TODO: Doesn't work
| ^^^^^^^^^^^^^ type mismatch resolving `for<'a> <MyBuilder as Builder>::InstanceForBuilder<'a> == <MyBuilder as Builder>::InstanceForBuilder<'a>`
|
note: expected this to be `<MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:32:35
|
32 | type InstanceForBuilder<'a> = MyInstance<'a>;
| ^^^^^^^^^^^^^^
= note: expected associated type `<MyBuilder as Builder>::InstanceForBuilder<'a>`
found struct `MyInstance<'a>`
help: a method is available that returns `<MyBuilder as Builder>::InstanceForBuilder<'a>`
--> examples/test.rs:8:5
|
8 | fn build<'a>(&self, val: &'a usize) -> Self::InstanceForBuilder<'a>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider calling `Builder::build`
note: required by a bound in `build_with_42`
--> examples/test.rs:19:40
|
16 | fn build_with_42<B: Builder>(builder: B)
| ------------- required by a bound in this
...
19 | for<'a> B::InstanceForBuilder<'a>: Instance<'a, InstanceProperty = bool>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `build_with_42`
For more information about this error, try `rustc --explain E0271`.
error: could not compile `pairwise-aligner` due to 2 previous errors
The correct syntax to do what you want is:
where B::InstanceForBuilder::InstanceProperty = bool
there's no need to introduce the for<'a> lifetime because the value of the associated type is not allowed to depend on the lifetime parameter. If you compile this code, you'll find that you get another error:
error: equality constraints are not yet supported in `where` clauses
--> src/main.rs:19:5
|
19 | B::InstanceForBuilder::InstanceProperty = bool,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
There's no immediate workaround for this. If you badly need this, you may be able to write a new trait, implement it only for bool, and then constrain things to that trait. That will get messy quickly though.
The answer from DreamConspiracy is a little outdated. I'd like to reuse the example codes from him to show a compiled solution
Instead of
where B::InstanceForBuilder::InstanceProperty = bool
You should write
fn build_with_42_for_bool_instance<'a, B, I>(builder: B)
where
B : Builder<InstanceForBuilder<'a>=I>,
I : Instance<'a, InstanceProperty=bool>,
{
builder.build(&42);
}

Is it possible to call a member closure from another member closure? [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Borrowing references to attributes in a struct
(2 answers)
Passing mutable self reference to method of owned object
(2 answers)
How to call method with &mut self from inside another method of the same type?
(2 answers)
Closed 4 years ago.
I'm working with callbacks on my struct, using boxed closures. However, I haven't been able to figure out how to call one closure from another:
struct MyStruct {
first: Box<Fn()>,
second: Box<Fn()>,
}
impl MyStruct {
fn method(&mut self) {
self.second = Box::new(|| {
// How can I make this work?
(self.first)();
});
}
}
fn main() {
let _ = MyStruct {
first: Box::new(|| {}),
second: Box::new(|| {}),
};
}
This gives:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:8:32
|
8 | self.second = Box::new(|| {
| ________________________________^
9 | | // How can I make this work?
10 | | (self.first)();
11 | | });
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 7:5...
--> src/main.rs:7:5
|
7 | / fn method(&mut self) {
8 | | self.second = Box::new(|| {
9 | | // How can I make this work?
10 | | (self.first)();
11 | | });
12 | | }
| |_____^
= note: ...so that the types are compatible:
expected &&mut MyStruct
found &&mut MyStruct
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::ops::Fn() + 'static)>
found std::boxed::Box<dyn std::ops::Fn()>
I'm not quite sure what that means in this context.
I understand that the borrowing rules are the cause of the error, but is there any legal way in Rust to get the same effect of what I'm going for?
I'm not sure if it makes sense just from this why I would want to do this. It's a minimal reproduction. I can provide a bigger example, but it's much more involved.
Here is a partial solution to your problem: Do not take Box<Fn()>, but use Box<Fn(&MyStruct)> instead, i.e. pass the "self" explicitly to the closures.
However, as far as I can see, this only allows the closures to take &MyStruct (as opposed to &mut MyStruct), i.e. the closures cannot modify the given MyStruct (which may or may not be enough for your use case).
struct MyStruct {
first: Box<Fn(&MyStruct)>,
second: Box<Fn(&MyStruct)>,
}
impl MyStruct {
fn method(&mut self) {
self.second = Box::new(|self2: &MyStruct| {
(self2.first)(self2)
});
}
}
fn main() {
let _ = MyStruct {
first: Box::new(|_self_ignored| {}),
second: Box::new(|_self_ignored| {}),
};
}
If the closures should modify MyStruct, you run into problems with (self2.first)(self2), since this would then borrow self2 twice, once of them mutably. You could possibly get around this by swapping out first/second temporarily, but this way, you would need to be terribly careful whenever you call first/second, since it could at any time be impossible to call first/second.
There may be unsafe ways around this. That said, I suppose (or at least, I hope) there is a better way to implement what you are trying to achieve.

Resources