Allow foreign exceptions to unwind through Rust code and Rust panics to unwind through FFI
This PR fixes interactions between Rust panics and foreign (mainly C++) exceptions.
C++ exceptions (and other FFI exceptions) can now safely unwind through Rust code:
- The FFI function causing the unwind must be marked with `#[unwind(allowed)]`. If this is not the case then LLVM may optimize landing pads away with the assumption that they are unreachable.
- Drop code will be executed as the exception unwinds through the stack, as with a Rust panic.
- `catch_unwind` will *not* catch the exception, instead the exception will silently continue unwinding past it.
Rust panics can now safely unwind through C++ code:
- C++ destructors will be called as the stack unwinds.
- The Rust panic can only be caught with `catch (...)`, after which it can be either rethrown or discarded.
- C++ cannot name the type of the Rust exception object used for unwinding, which means that it can't be caught explicitly or have its contents inspected.
Tests have been added to ensure all of the above works correctly.
Some notes about non-C++ exceptions:
- `pthread_cancel` and `pthread_exit` use unwinding on glibc. This has the same behavior as a C++ exception: destructors are run but it cannot be caught by `catch_unwind`.
- `longjmp` on Windows is implemented using unwinding. Destructors are run on MSVC, but not on MinGW. In both cases the unwind cannot be caught by `catch_unwind`.
- As with C++ exceptions, you need to mark the relevant FFI functions with `#[unwind(allowed)]`, otherwise LLVM will optimize out the destructors since they seem unreachable.
I haven't updated any of the documentation, so officially unwinding through FFI is still UB. However this is a step towards making it well-defined.
Fixes#65441
cc @gnzlbg
r? @alexcrichton
As of LLVM 9, this is required for 32-bit PowerPC to properly generate
PLT references. Previously, only BigPIC was supported; now LLVM supports
both BigPIC and SmallPIC, and there is no default value provided.
Validate error patterns and error annotation in ui tests when present
Previously, when compilation succeeded, neither error patterns nor error
annotation would be validated. Additionally, when compilation failed,
only error patterns would be validated if both error patterns and error
annotation were present.
Now both error patterns and error annotation are validated when present,
regardless of compilation status. Furthermore, for test that should run,
the error patterns are matched against executable output, which is what
some of tests already expect to happen, and when #65506 is merged even
more ui tests will.
Fixes#56277
Remove a loop which runs exactly once
Though the code seems to work properly, it is worth removing the loop entirely in order to not confuse the reader.
r? @estebank
The concrete type that will be too big is target dependent. Avoid
matching it in error annotation to make test work correctly across
different targets.
Previously, when compilation succeeded, neither error patterns nor error
annotation would be validated. Additionally, when compilation failed,
only error patterns would be validated if both error patterns and error
annotation were present.
Now both error patterns and error annotation are validated when present,
regardless of compilation status. Furthermore, for test that should run,
the error patterns are matched against executable output, which is what
some of tests already expect to happen, and when #65506 is merged even
more ui tests will.
When both error patterns and error annotations are present in an ui
test, only error patterns are validated against the output.
Replace the error pattern with an error annotation to avoid silently
ignoring the other error annotation.
The proper attribute was added to `simd_shuffle*` in
rust-lang/stdarch#825. This caused `promote_consts` to double-count its
second argument when recording promotion candidates, which caused
the promotion candidate compatibility check to fail.
Just to make it useable for profiling and such inside
rustc itself. It was vaguely useful in
https://wiki.alopex.li/WhereRustcSpendsItsTime and I figured
I might as well upstream it; I may or may not ever get around
to doing more with it (hopefully I will), but it may be useful
for others.
Partially revert the early feature-gatings added in #65742.
The intent here is to address #65860 ASAP (in time for beta, ideally), while leaving as much of #65742 around as possible, to make it easier to re-enable later.
Therefore, I've only kept the parts of the revert that re-add the old (i.e. non-early) feature-gating checks that were removed in #65742, and the test reverts.
I've disabled the new early feature-gating checks from #65742 entirely for now, but it would be easy to put them behind a `-Z` flag, or turn them into warnings, which would allow us to keep tests for both the early and late versions of the checks - assuming that's desirable.
cc @nikomatsakis @Mark-Simulacrum @Centril
Those annotation are silently ignored rather than begin validated
against compiler output. Update them before validation is enabled,
to avoid test failures.
Type parameters are referenced in the error message after the previous
few commits (using span label). But when the main error message already
references the very same type parameter it becomes clumsy. Do not show
the additional label in this case as per code review comment by
@estebank.
Also this contains a small style fix.
Fixes#47319.
Shows the type parameter definition(s) on type mismatch errors so the
context is clearer. Pretty much changes the following:
```
LL | bar1(t);
| ^
| |
| expected enum `std::option::Option`, found type parameter `T`
```
into:
```
LL | fn foo1<T>(t: T) {
| - this type parameter
LL | bar1(t);
| ^
| |
| expected enum `std::option::Option`, found type parameter `T`
```
Part of #47319.
This just adds type parameter name to type mismatch error message, so
e.g. the following:
```
expected enum `std::option::Option`, found type parameter
```
becomes
```
expected enum `std::option::Option`, found type parameter `T`
```
the docs are great at explaining that .len() isn't like in other
languages but stops short of explaining how to get the character length.
r? @steveklabnik