wasm-bindgen
wasm-bindgen copied to clipboard
Not sound to use lifetimes in function signatures
Seems like wasm-bindgen prohibits the use of lifetime specifiers in certain places where the compiler requires them. I have a test repo here: https://github.com/attente/wasm-bindgen-lifetime-issue
Building it, the error is:
[nix-shell:~/wasm-bindgen-lifetime-issue]$ cargo build --release --target=wasm32-unknown-unknown
Compiling wasm-bindgen-lifetime-issue v0.1.0 (/home/william/wasm-bindgen-lifetime-issue)
error: it is currently not sound to use lifetimes in function signatures
--> src/lib.rs:10:31
|
10 | pub fn f() -> Result<(), &'static str> {
| ^^^^^^^
error: aborting due to previous error
error: Could not compile `wasm-bindgen-lifetime-issue`.
To learn more, run the command again with --verbose.
Unfortunately if I remove the 'static lifetime specifier, then the compiler will complain:
[nix-shell:~/wasm-bindgen-lifetime-issue]$ cargo build --release --target=wasm32-unknown-unknown
Compiling wasm-bindgen-lifetime-issue v0.1.0 (/home/william/wasm-bindgen-lifetime-issue)
error[E0106]: missing lifetime specifier
--> src/lib.rs:10:30
|
10 | pub fn f() -> Result<(), &str> {
| ^ help: consider giving it a 'static lifetime: `&'static`
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
error: aborting due to previous error
For more information about this error, try `rustc --explain E0106`.
error: Could not compile `wasm-bindgen-lifetime-issue`.
To learn more, run the command again with --verbose.
Is there any workaround for this issue?
Thanks for the report! This is one I don't think we've given a ton of thought to just yet, but I suspect that with some work we could get 'static working as it doesn't run into the same issues as an arbitrary 'a. Would a String work for you use case for now though?
Thanks for the feedback! What I ended up doing instead is changing my Error type from &'static str to i32, with numeric error codes. I'm sure it must be non-trivial to add lifetime support to wasm-bindgen.
@attente i am agree this. when i learn rust, the rust-book tell me how important about the lifetime. so i learned the lifetime . but when i use rust to write a WebAssembly program, wasm-bindgen tell me i cant do this. Am i wrong? 😭
The same issue I encountered. I suspect that wasm-bindgen do not support static lifetime yet either.
So, I want to know When this bug will be fixed. Thanks a lot.
same probleme here, I'm passing a js cloure to wasm, the complier tells me to add 'static lifetime parameter to the rust function signature, but wasm-bindgen forbids it.
@oHaiyang did you find any solution or workaround for the closure problem?
I'm also bit by this as I have data structures that have a lifetime on them. Even though I can support a static lifetime, I can't actually return them. An example (untested) of the issue I'm encountering:
#[wasm_bindgen]
#[derive(Serialize, Deserialize)]
pub struct SomeStruct<'a> { ... }
#[wasm_bindgen]
pub fn get_some_struct() -> SomeStruct<'static> {
// Make a static instance
SomeStruct { ... }
}
I can get around this by providing a wrapper type that contains the static instance, although I still have to convert to a JsValue to export.
#[wasm_bindgen]
pub struct Output(Page<'static>);
#[derive(Serialize, Deserialize)]
pub struct SomeStruct<'a> { ... }
#[wasm_bindgen]
impl Output {
pub fn to_js(&self) -> JsValue {
JsValue::from_serde(&self.0).unwrap()
}
}
+1 for this feature, thanks!
Not ideal but this, after several hours of googling, trial/error, etc. (sadly not everyone is a Rust expert) is what I came up with:
I'm also struggling with this. I have a parser that outputs a Token<'a> were the lifetime 'a is binded to the input &'a str
kind of like:
pub fn parse<'a>(input: &'a str) -> Result<Vec<Token<'a>>, ParseError> {}
any idea how can I create a wasbindgen for this case?
thanks!
I got the following to compile:
use js_sys::{Array, Function};
struct Token<'a> {
value: &'a str
}
#[derive(Debug)]
struct ParseError {}
pub fn parse<'a>(input: &'a str) -> Result<Vec<Token<'a>>, ParseError> {
return Ok(Vec::<Token<'a>>::new());
}
#[wasm_bindgen]
pub fn parse_bindgen(input: JsValue) -> Array {
let input_as_string = input.as_string().unwrap();
let result = parse(input_as_string.as_str());
let token_vector = result.unwrap();
let array_length = token_vector.len() as u32;
let arr = Array::new_with_length(array_length);
for (i, token) in token_vector.iter().enumerate() {
let s = JsValue::from("token?"); // replace with `Token`, though I don't know what it looks like
arr.set(i as u32, s);
}
return arr;
}
You should take the above with several pinches of salt:
- I am new to Rust
- I made assumptions about
Token - Based on the point above, I am not sure whether you would be able to run
JsValue::from(), you might need to perform an intermediate conversion into a type of value that is actually supported
I hope this helps you. Feel free to let me know the outcome.