Skip to content
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

Not sound to use lifetimes in function signatures #1187

Open
attente opened this issue Jan 16, 2019 · 12 comments · Fixed by #3856
Open

Not sound to use lifetimes in function signatures #1187

attente opened this issue Jan 16, 2019 · 12 comments · Fixed by #3856
Labels
more-types Adding support for more Rust types to cross the boundary

Comments

@attente
Copy link

attente commented Jan 16, 2019

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?

@alexcrichton
Copy link
Contributor

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?

@attente
Copy link
Author

attente commented Jan 17, 2019

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.

@alexcrichton alexcrichton added the more-types Adding support for more Rust types to cross the boundary label Jan 22, 2019
@takkuumi
Copy link

@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? 😭

@anymost
Copy link

anymost commented Jun 29, 2019

The same issue I encountered. I suspect that wasm-bindgen do not support static lifetime yet either.

@anymost
Copy link

anymost commented Jul 7, 2019

So, I want to know When this bug will be fixed. Thanks a lot.

KronicDeth added a commit to GetFirefly/firefly that referenced this issue Jul 29, 2019
wasm-bindgen does not allow `&'static` or any other lifetimes for
exported bindings
(rustwasm/wasm-bindgen#1187), so needed to
switch tags to owned Strings.
@oHaiyang
Copy link

oHaiyang commented Aug 6, 2019

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.

KronicDeth added a commit to GetFirefly/firefly that referenced this issue Aug 6, 2019
wasm-bindgen does not allow `&'static` or any other lifetimes for
exported bindings
(rustwasm/wasm-bindgen#1187), so needed to
switch tags to owned Strings.
KronicDeth added a commit to GetFirefly/firefly that referenced this issue Aug 6, 2019
wasm-bindgen does not allow `&'static` or any other lifetimes for
exported bindings
(rustwasm/wasm-bindgen#1187), so needed to
switch tags to owned Strings.
bokuweb added a commit to bokuweb/docx-rs that referenced this issue Dec 8, 2019
This is because wasm-bindgen does not support 'static for function
Pleaase see rustwasm/wasm-bindgen#1187
bokuweb added a commit to bokuweb/docx-rs that referenced this issue Dec 8, 2019
This is because wasm-bindgen does not support 'static for function
Pleaase see rustwasm/wasm-bindgen#1187
bokuweb added a commit to bokuweb/docx-rs that referenced this issue Dec 8, 2019
* feat: Add numberings

* feat: Use String for wasm

This is because wasm-bindgen does not support 'static for function
Pleaase see rustwasm/wasm-bindgen#1187
@chriamue
Copy link

chriamue commented May 9, 2021

@oHaiyang did you find any solution or workaround for the closure problem?

@chipsenkbeil
Copy link

chipsenkbeil commented May 18, 2021

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()
    }
}

celeryclub added a commit to celeryclub/life-like that referenced this issue Jul 6, 2023
I wanted to avoid passing around instances of core structs so much, and just initialize one with an instance of another, but wasm-bindgen doesn’t fully support Rust lifetimes yet so this wasn’t possible.
rustwasm/wasm-bindgen#1187
@daxpedda daxpedda reopened this Feb 27, 2024
@andreamancuso
Copy link

+1 for this feature, thanks!

@andreamancuso
Copy link

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:

image

image

image

image

image

andreamancuso added a commit to xframes-project/xframes that referenced this issue May 23, 2024
Came across rustwasm/wasm-bindgen#1187 and eventually found a way around it. Things are still looking quite ugly but at least I'm moving forward.
@woile
Copy link

woile commented May 25, 2024

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!

@andreamancuso
Copy link

andreamancuso commented May 25, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
more-types Adding support for more Rust types to cross the boundary
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants