-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
I've ran into an issue with one of my libraries that was preventing it from compiling with wasm-pack
. It would otherwise compile just fine with rustc
to other targets (no compiler errors) but when I would attempt to compile with wasm-pack
I would get this cryptic error:
LLVM ERROR: Function addresses with offsets not supported
error: could not compile `hello-wasm`.
No line numbers, no error trace, just that.
After spending quite a while to find the offending block of code, I've discovered that the issue was caused by misusing the type system a bit.
Here's the offending code:
use wasm_bindgen::prelude::*;
use std::vec::Vec;
#[wasm_bindgen]
pub fn err() -> i32 {
let vector: Vec<u8> = Vec::new();
// In my library, I meant to use `core::u16::MAX` and did this instead
let my_size = (u16::max as usize) - 1; // <- casting function as usize
// `u16::max` is actually a function to compare two numbers and get the maximum between them
if my_size > vector.len() {
20
} else {
50
}
}
I expected to see this happen: I think this is actually a type error. u16::max
is a function and I'm casting it to a usize
. I would hope the Rust compiler would yell at me for that or at least require me to write unsafe
before I can cast a function to a usize
.
Instead, this happened: The program compiles and runs just fine unless you attempt to compile it to wasm with wasm-pack build
. If you run the function in a test, it spits out 20
.
rustc --version --verbose
:
rustc 1.47.0 (18bf6b4f0 2020-10-07)
binary: rustc
commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
commit-date: 2020-10-07
host: x86_64-apple-darwin
release: 1.47.0
LLVM version: 11.0
wasm-pack -V
:
wasm-pack 0.9.1
Hoping to save someone else a few days of hair pulling!
Edit: A little bit more testing, it looks like the program compiles just fine if you change the line to this:
// let my_size = (u16::max as usize) - 1;
let my_size = (u16::max as usize)
So it seems like combining the cast with an operation causes the issue. Interestingly, not all operations cause the error.
// Doesn't compile with `wasm-pack`
let my_size = (u16::max as usize) + 1;
let my_size = (u16::max as usize) - 1;
let my_size = (u16::max as usize) + 2;
let my_size = (u16::max as usize) - 2;
// Compiles Fine with `wasm-pack`:
let my_size = (u16::max as usize) * 1;
let my_size = (u16::max as usize) / 1;
let my_size = (u16::max as usize) * 2;
let my_size = (u16::max as usize) / 2;
Activity
camelid commentedon Dec 23, 2020
I and other people would like to reduce the use of
as
(cc #79477 and RFC 2484), but that's a big undertaking and unlikely to happen soon. You should probably be usingtry_into().unwrap()
instead ofas
so that your code panics if the value doesn't fit. In this case what you're doing is probably fine, but in general usingas
will cause the number to be truncated/wrapped if it doesn't fit in the type you're casting to.Using
try_into()
will also give an error if you try to call it on a function.By the way, why are you importing
std::vec::Vec
? It's in the prelude.only-cliches commentedon Dec 23, 2020
I've been working in
no_std
so long it's become a habit!Thanks for the reply, at the very least hopefully the next person to run into this has a head start on troubleshooting.
Mark-Simulacrum commentedon Dec 23, 2020
This isn't a type error, I think, because u16::max is getting coerced into a function pointer which can then be cast into usize without any truncation. I'm a little surprised that the coercion occurred in that context but in any case that's not really the underlying cause of the bug here, I suspect.
only-cliches commentedon Dec 23, 2020
Agreed, after further investigation It has something to do with casting a function into a usize, then adding or subtracting some value from that usize.