-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
component-model: bindgen macro generates traits whose lifetimes are too loose for state with explicit lifetime #7088
Comments
Could you share some more code as a reproducible example? This for example compiles ok for me locally: mod with_lifetimes {
wasmtime::component::bindgen!({
inline: "
package my:project
interface host {
gen-random-integer: func() -> u32
sha256: func(bytes: list<u8>) -> string
}
world hello-world {
import host
export demo: interface {
run: func()
}
}
",
async: true,
});
struct MyState<'a> {
_x: Option<wgpu::RenderPass<'a>>,
}
#[async_trait::async_trait]
impl my::project::host::Host for MyState<'_> {
async fn gen_random_integer(&mut self) -> wasmtime::Result<u32> {
loop {}
}
async fn sha256(&mut self, _bytes: Vec<u8>) -> wasmtime::Result<String> {
loop {}
}
}
} |
@alexcrichton apologies for the increase in complexity of the example, but this more accurately reflects the problem I'm having and demonstrates the correct lifetimes issue. Uses mod with_lifetimes {
wasmtime::component::bindgen!({
inline: "
package my:project
interface host {
gen-random-integer: func() -> u32
sha256: func(bytes: list<u8>) -> string
}
world hello-world {
import host
export demo: interface {
run: func()
}
}
",
async: true,
});
struct MyState<'a> {
render_state: Option<RenderState<'a>>,
}
pub struct RenderState<'a> {
pub command_encoders: slab::Slab::<GpuCommandEncoderState<'a>>,
}
impl<'a> RenderState<'a> {
pub fn new() -> RenderState<'a> {
RenderState {
command_encoders: slab::Slab::new()
}
}
}
pub struct GpuCommandEncoderState<'a> {
pub encoder: wgpu::CommandEncoder,
pub render_passes: slab::Slab::<wgpu::RenderPass<'a>>
}
impl<'a> GpuCommandEncoderState<'a> {
pub fn new(encoder: wgpu::CommandEncoder) -> GpuCommandEncoderState<'a> {
GpuCommandEncoderState {
encoder,
render_passes: slab::Slab::new()
}
}
}
#[async_trait::async_trait]
impl my::project::host::Host for MyState<'_> {
async fn gen_random_integer(&mut self) -> wasmtime::Result<u32> {
let render_state = self.render_state.as_mut().expect("Render state");
let command_encoder_state = render_state.command_encoders.get_mut(0 as usize).unwrap();
let render_pass_encoder = command_encoder_state.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[],
depth_stencil_attachment: None
});
let pass_id = command_encoder_state.render_passes.insert(render_pass_encoder);
wasmtime::Result::Ok(1)
}
async fn sha256(&mut self, _bytes: Vec<u8>) -> wasmtime::Result<String> {
loop {}
}
}
} |
Thanks! I unfortunately think though that this isn't related to Wasmtime or struct MyState<'a> {
render_state: Option<RenderState<'a>>,
}
pub struct RenderState<'a> {
pub command_encoders: slab::Slab<GpuCommandEncoderState<'a>>,
}
impl<'a> RenderState<'a> {
pub fn new() -> RenderState<'a> {
RenderState {
command_encoders: slab::Slab::new(),
}
}
}
pub struct GpuCommandEncoderState<'a> {
pub encoder: wgpu::CommandEncoder,
pub render_passes: slab::Slab<wgpu::RenderPass<'a>>,
}
impl<'a> GpuCommandEncoderState<'a> {
pub fn new(encoder: wgpu::CommandEncoder) -> GpuCommandEncoderState<'a> {
GpuCommandEncoderState {
encoder,
render_passes: slab::Slab::new(),
}
}
}
impl MyState<'_> {
fn gen_random_integer(&mut self) {
let render_state = self.render_state.as_mut().expect("Render state");
let command_encoder_state = render_state.command_encoders.get_mut(0 as usize).unwrap();
let render_pass_encoder =
command_encoder_state
.encoder
.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[],
depth_stencil_attachment: None,
});
command_encoder_state
.render_passes
.insert(render_pass_encoder);
loop {}
}
} I believe the root cause of this is that That's at least the problem, but I don't know enough about wgpu to know how best to restructure to fix this. Regardless though I think that this is unrelated to Wasmtime? |
Ok, that's a good assessment. I'll have to do some more digging on my end to figure out how to manage that. I'm happy to close the issue in that case. Thanks for your help! |
I guess I do have one follow up @alexcrichton -- specifying that the lifetime of self ( impl<'life0: 'render, 'render> MyState<'render> {
async fn gen_random_integer(&'life0 mut self) -> wasmtime::Result<u32> {
let render_state = self.render_state.as_mut().expect("Render state");
let command_encoder_state = render_state.command_encoders.get_mut(0 as usize).unwrap();
let render_pass_encoder = command_encoder_state.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
color_attachments: &[],
depth_stencil_attachment: None
});
let pass_id = command_encoder_state.render_passes.insert(render_pass_encoder);
wasmtime::Result::Ok(1)
}
async fn sha256(&mut self, _bytes: Vec<u8>) -> wasmtime::Result<String> {
loop {}
}
} |
Unfortunately while that works and passes the compiler it is not possible to actually call that function. |
😕 I think I'd rather deal with use after free bugs... Thank you for the explanation and I understand that this out of scope for wasmtime so I appreciate you taking the time to make that clear to me. |
If you're up for it I suspect the wgpu authors would be happy to hear from you and might be able to assist. You may not be the first that wanted to store those two structures next to each other so they may have pointers about how to approach this already. |
I'll give it a try, thanks again for your help. Edit: yeah... gfx-rs/wgpu#1453 |
Consider the example from the bindgen docs:
If
MyState
here is insteadMyState<'render>
(in my case, MyState owns anOption<wgpu::RenderPass<'render>>
), the bindgen macro generates a trait which is implemented like this:but here, Rust is unable to assume that
'life0
outlives'render
and I cannot specify it as'life0: 'render
because that's a stricter requirement than the trait.The text was updated successfully, but these errors were encountered: