Skip to content

Allow exceptions on wasm platforms#1714

Merged
NobodyXu merged 1 commit into
rust-lang:mainfrom
kolayne:patch-1
May 2, 2026
Merged

Allow exceptions on wasm platforms#1714
NobodyXu merged 1 commit into
rust-lang:mainfrom
kolayne:patch-1

Conversation

@kolayne
Copy link
Copy Markdown
Contributor

@kolayne kolayne commented Apr 30, 2026

Content

WASM now supports exceptions.
Remove the hardcoded -fno-exceptions option.

Resolves #1680

Discussion

Should we remain compatible with programs that rely on the old behavior of the library? Should we keep the old behavior as default, and add a function that will allow the user to select between, e.g., -fno-exceptions, -fwasm-exceptions, and -fexceptions?

WASM now supports exceptions.
Remove the hardcoded `-fno-exceptions` option.

Resolves rust-lang#1680
@NobodyXu
Copy link
Copy Markdown
Contributor

Is it universal? I was under the impression that only some wasm targets and some toolchain supports it

@kolayne
Copy link
Copy Markdown
Contributor Author

kolayne commented Apr 30, 2026

It is supported by emscripten (target wasm32-unknown-emscripten) by default; it is supported by wasi (all the wasm32-wasip* targets) since WebAssembly/wasi-sdk#606 (merged 3 weeks ago, to become available in the upcoming release); I have no experience with wasm32-unknown-unknown and wasm32v1-none.

But, in any case, it should probably be up to the developer, rather than hardcoded in the library.

@NobodyXu
Copy link
Copy Markdown
Contributor

In that case, can you please only allow exception on these specific target?

Blank removal would break compilation of existing projects.

@kolayne
Copy link
Copy Markdown
Contributor Author

kolayne commented May 1, 2026

Yes, we could do that, but that would not be much better:

  1. If more wasm* targets are added, this piece of code would need to be edited again to maintain the up-to-date list of targets that allow exceptions.
  2. Exceptions support is not only about the target. E.g., on wasi the user still needs to provide a wasm sysroot that was compiled with extensions support and includes libunwind, otherwise the project will fail to link. So, just enabling exceptions on all targets that support it might still break existing projects.

As an alternative, we could keep the old behavior by default (i.e., if wasm, add -fno-exceptions, otherwise do nothing) but give the library the choice, e.g., via a method of cc::Build and an environment variable. What do you think?

@kolayne
Copy link
Copy Markdown
Contributor Author

kolayne commented May 1, 2026

In the latter case, though, I'm not sure what kind of interface we want to export. We could just have an option (env var + cc::Builder method) that controls this exact thing: whether to automatically force-disable exceptions when compiling for wasm. That's viable, but feels a bit to specific.

Alternatively, we could generalize this a bit and have an option to control exception support in general (which defaults to -fno-exceptions on wasm and to nothing on other architectures). But then I'm not sure which variants this setting should support: the set of -f*exceptions options depends on the compiler and the compiler version, the clang on my machine has eleven such options. And if we just let the user specify this option is a string, then it just becomes an extra function with the functionality of cc::Build::flag.

So, should we just introduce an option to control the disabling of exceptions? Should we make it only effective on wasm?

@NobodyXu
Copy link
Copy Markdown
Contributor

NobodyXu commented May 1, 2026

I'm not sure about this as I'm not that familiar with current status of exception in wasm, cc @alexcrichton can you please give us some advice on this?

@alexcrichton
Copy link
Copy Markdown
Member

Reading over this and some history here, I think that the best way forward is this PR as-is, which is to delete the unconditional -fno-exceptions. My hunch is that @NobodyXu you're right in that something will break somewhere, but I also feel the same way about pretty much any change to the cc crate.

This'll definitely fix the use case for Emscripten targets where exceptions should work just fine. The reason I don't think this will cause widespread breakage for WASI targets is that -fno-exceptions should already be the default there. Given that I don't think that it should be necessary to doubly pass -fno-exceptions. I don't understand the origin of this flag being passed, #1083, and maybe wasi-sdk was configured slightly differently back then or something like that. That's the main reason I'd hesitate, but I can say that at least nowaday's wasi-sdk should have exceptions off-by-default.

Actually supporting exceptions on WASI is more involved than just updating wasi-sdk even with WebAssembly/wasi-sdk#606, and that doesn't mean that WASI all-of-a-sudden supports exceptions. In theory the buckets folks could be in (for WASI targets) are:

  • -Cpanic=unwind in Rust, exceptions in C++ - this requires target-level changes in Rust or, in lieu of that, recompiling the standard library. This is known to be pretty broken and not fully baked.
  • -Cpanic=abort in Rust, exceptions in C++ - for example the extern "C-unwind" ABI could be used to say C++ can throw, but Rust should catch the exceptions and abort. This also basically isn't supported and requires the exception-handling LLVM feature to be enabled in Rust, which isn't by default.
  • -Cpanic=abort in Rust, no exceptions in C++ - if no one configures anything out of their way, this should be the default behavior today.

If the cc crate does anything, in theory it should detect the enabled features in Rust. When the exception-handling target feature is disabled then -fno-exceptions in theory should unconditionally be passed since Rust can't work correctly with C++ code that throws exceptions across the boundary. Even then though it's possible to compile C++ code with exceptions so long as it doesn't cross any boundaries.

Overall, in my opinion, the cc crate isn't in a position to render judgement or guidance on how to sort out exceptions on wasm. It's all a bit of a mess anyway, and I think the best thing for cc to do is to provide an unopinionated stance. That way problems can be configured around (in theory) and all the possible use cases should work (in theory). It does mean that error messages won't be great, but that's sort of par for the course with FFI

Copy link
Copy Markdown
Contributor

@NobodyXu NobodyXu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @kolayne @alexcrichton in that case I'd merge this PR, and it'd be scheduled to release next Friday (as it misses today's release), if you need a new release now I can do it

@NobodyXu
Copy link
Copy Markdown
Contributor

NobodyXu commented May 1, 2026

If the cc crate does anything, in theory it should detect the enabled features in Rust. When the exception-handling target feature is disabled then -fno-exceptions in theory should unconditionally be passed since Rust can't work correctly with C++ code that throws exceptions across the boundary. Even then though it's possible to compile C++ code with exceptions so long as it doesn't cross any boundaries.

cc @alexcrichton this sounds like we should add a generic conversion, if CARGO_FEATURES says exception is disabled then we pass -fno-exception to c/cxx compiler?

@alexcrichton
Copy link
Copy Markdown
Member

I was initially thinking that'd be a possibility, yeah, but then I realized as I was typing that even if Rust has exceptions disabled it's possible to safely enable exceptions in C++ so long as exceptions never cross the boundary (which would be up to the user at that point). So even force-disabling when Rust has exceptions disables I think can technically run afoul of otherwise-valid situations. Given that I think it's best for cc to just not have a stance on C++ exceptions usage and leave that to the C++ toolchain and users to configure correctly.

Something more "obviously correct" might emerge in the future, though, but for now I think it's best to just delete this code.

@NobodyXu NobodyXu merged commit a9d8632 into rust-lang:main May 2, 2026
79 checks passed
@NobodyXu
Copy link
Copy Markdown
Contributor

NobodyXu commented May 2, 2026

Thank you @alexcrichton !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wasm32-unknown-emscripten target shouldn't use -fno-exceptions

4 participants