fix/update teach_note from 'escaping mutable ref/ptr' const-check
The old note was quite confusing since it talked about statics, but the message is also shown for consts. So let's reword to something that is true for both of them.
LLVM 20 split out what used to be called b16b16 and correspond to aarch64
FEAT_SVE_B16B16 into sve-b16b16 and sme-b16b16.
Add sme-b16b16 as an explicit feature and update the codegen accordingly.
Reserve guarded string literals (RFC 3593)
Implementation for RFC 3593, including:
- lexer / parser changes
- diagnostics
- migration lint
- tests
We reserve `#"`, `##"`, `###"`, `####`, and any other string of four or more repeated `#`. This avoids infinite lookahead in the lexer, though we still use infinite lookahead in the parser to provide better forward compatibility diagnostics.
This PR does not implement any special lexing of the string internals:
- strings preceded by one or more `#` are denied
- regardless of the number of trailing `#`
- string contents are lexed as if it was just a bare `"string"`
Tracking issue: #123735
RFC: rust-lang/rfcs#3593
Ignore broken-pipe-no-ice on apple (specifically macOS) for now
This test fails for me locally (initially reported by Zalathar) because apparently on macOS it doesn't say "internal compiler error" but it does report the std I/O panic, and it doesn't exit with a code of 101 but instead terminates with a wait signal of SIGPIPE.
Ignore this test on apple for now, until we try to actually address the underlying issue.
See https://github.com/rust-lang/rust/pull/131155 and https://github.com/rust-lang/rust/issues/131436 for more context.
Dont ICE when encountering post-mono layout cycle error
It's possible to encounter post-mono layout cycle errors in `fn_abi_of_instance`. Don't ICE in those cases.
This was originally discovered in an async fn, but that's not the only way to encounter such an error (which the other test I added should demonstrate).
Error messsages suck, but this fix is purely about suppressing the ICE.
Fixes#131409
Prevent building cargo from invalidating build cache of other tools due to conditionally applied `-Zon-broken-pipe=kill` via tracked `RUSTFLAGS`
This PR fixes#130980 where building cargo invalidated the tool build caches of other tools (such as rustdoc) because `-Zon-broken-pipe=kill` was conditionally passed via `RUSTFLAGS` for other tools *except* for cargo. The differing `RUSTFLAGS` triggered tool build cache invalidation as `RUSTFLAGS` is a tracked env var -- any changes in `RUSTFLAGS` requires a rebuild.
`-Zon-broken-pipe=kill` is load-bearing for rustc and rustdoc to not ICE on broken pipes due to usages of raw std `println!` that panics without the flag being set, which manifests in ICEs.
I can't say I like the changes here, but it is what it is...
See detailed discussions and history of `-Zon-broken-pipe=kill` usage in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F/near/474593815.
## Approach
This PR fixes the tool build cache invalidation by informing the `rustc` binary shim when to apply `-Zon-broken-pipe=kill` (i.e. when the rustc binary shim is not used to build cargo). This information is not communicated by `RUSTFLAGS`, which is an env var tracked by cargo, and instead uses an untracked env var `UNTRACKED_BROKEN_PIPE_FLAG` so we won't trigger tool build cache invalidation. We preserve bootstrap's behavior of not setting that flag for cargo by conditionally omitting setting `UNTRACKED_BROKEN_PIPE_FLAG` when building cargo.
Notably, the `-Zon-broken-pipe=kill` instance in 1e5719bdc4/src/bootstrap/src/core/build_steps/compile.rs (L1058) is not modified because that is used to build rustc only and not cargo itself.
Thanks to `@cuviper` for the idea!
## Testing
### Integration testing
This PR introduces a run-make test for rustc and rustdoc that checks that when they do not ICE/panic when they encounter a broken pipe of the stdout stream.
I checked this test will catch the broken pipe ICE regression for rustc on Linux (at least) by commenting out 1e5719bdc4/src/bootstrap/src/core/build_steps/compile.rs (L1058), and the test failed because rustc ICE'd.
### Manual testing
I have manually tried:
1. `./x clean && `./x test build --stage 1` -> `rustc +stage1 --print=sysroot | false`: no ICE.
2. `./x clean` -> `./x test run-make` twice: no stage 1 cargo rebuilds.
3. `./x clean` -> `./x build rustdoc` -> `rustdoc +stage1 --version | false`: no panics.
4. `./x test src/tools/cargo`: tests pass, notably `build::close_output` and `cargo_command::closed_output_ok` do not fail which would fail if cargo was built with `-Zon-broken-pipe=kill`.
## Related discussions
Thanks to everyone who helped!
- https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Applying.20.60-Zon-broken-pipe.3Dkill.60.20flags.20in.20bootstrap.3F
- https://rust-lang.zulipchat.com/#narrow/stream/326414-t-infra.2Fbootstrap/topic/Modifying.20run-make.20tests.20unnecessarily.20rebuild.20stage.201.20.2E.2E.2E
- https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Internal.20lint.20for.20raw.20.60print!.60.20and.20.60println!.60.3F
Fixes https://github.com/rust-lang/rust/issues/130980
Closes https://github.com/rust-lang/rust/issues/131059
---
try-job: aarch64-apple
try-job: x86_64-msvc
try-job: x86_64-mingw
[Coverage][MCDC] Adapt mcdc to llvm 19
Related issue: #126672
Also finish task 4 at #124144
[llvm #82448](https://github.com/llvm/llvm-project/pull/82448) has introduced some break changes into mcdc, causing incompatibility between llvm 18 and 19. This draft adapts to that change and gives up supporting for llvm-18.
Fix utf8-bom test
The BOM was accidentally removed in https://github.com/rust-lang/rust/pull/57108
I had to move the run-pass line down, because compiletest doesn't seem to know about BOMs, so it does not parse the header if it is the first line.
Add tests for some old fixed issues
Closes#30867Closes#30472Closes#28994Closes#26719 (and migrates the relevant test to the new run-make)
Closes#23600
cc `@jieyouxu` for the run-make-support changes
try-job: x86_64-msvc
Add missing module flags for `-Zfunction-return=thunk-extern`
This fixes a bug in the `-Zfunction-return=thunk-extern` flag. The flag needs to be passed onto LLVM to ensure that functions such as `asan.module_ctor` and `asan.module_dtor` that are created internally in LLVM have the mitigation applied to them.
This was originally discovered [in the Linux kernel](https://lore.kernel.org/all/CANiq72myZL4_poCMuNFevtpYYc0V0embjSuKb7y=C+m3vVA_8g@mail.gmail.com/).
Original flag PR: #116892
PR for similar issue: #129373
Tracking issue: #116853
cc ``@ojeda``
r? ``@wesleywiser``
Add precondition checks to ptr::offset, ptr::add, ptr::sub
All of `offset`, `add`, and `sub` (currently) have the trivial preconditions that the offset in bytes must be <= isize::MAX, and the computation of the new address must not wrap. This adds precondition checks for these, and like in slice indexing, we use intrinsics directly to implement unsafe APIs that have explicit checks, because we get a clearer error message that mentions the misused API not an implementation detail.
Experimentation indicates these checks have 1-2% compile time overhead, due primarily to adding the checks for `add`.
A crater run (https://github.com/rust-lang/rust/pull/130251#issuecomment-2395824565) indicates some people currently have buggy calls to `ptr::offset` that apply a negative offset to a null pointer, but the crater run does not hit the `ptr::add` or `ptr::sub` checks, which seems like an argument for cfg'ing out those checks on account of their overhead.
Don't allow the `#[pointee]` attribute where it doesn't belong
Error if the `#[pointee]` attribute is applied to anything but generic type parameters.
Closes#128485
Related to #123430
liballoc: introduce String, Vec const-slicing
This change `const`-qualifies many methods on `Vec` and `String`, notably `as_slice`, `as_str`, `len`. These changes are made behind the unstable feature flag `const_vec_string_slice`.
## Motivation
This is to support simultaneous variance over ownership and constness. I have an enum type that may contain either `String` or `&str`, and I want to produce a `&str` from it in a possibly-`const` context.
```rust
enum StrOrString<'s> {
Str(&'s str),
String(String),
}
impl<'s> StrOrString<'s> {
const fn as_str(&self) -> &str {
match self {
// In a const-context, I really only expect to see this variant, but I can't switch the implementation
// in some mode like #[cfg(const)] -- there has to be a single body
Self::Str(s) => s,
// so this is a problem, since it's not `const`
Self::String(s) => s.as_str(),
}
}
}
```
Currently `String` and `Vec` don't support this, but can without functional changes. Similar logic applies for `len`, `capacity`, `is_empty`.
## Changes
The essential thing enabling this change is that `Unique::as_ptr` is `const`. This lets us convert `RawVec::ptr` -> `Vec::as_ptr` -> `Vec::as_slice` -> `String::as_str`.
I had to move the `Deref` implementations into `as_{str,slice}` because `Deref` isn't `#[const_trait]`, but I would expect this change to be invisible up to inlining. I moved the `DerefMut` implementations as well for uniformity.
Don't use Immediate::offset to transmute pointers to integers
This applies the relatively new `assert_matches_abi` check in the `offset` operation on immediates, which makes sure that if offsets are used to alter the layout (which is possible because the field layout is arbitrarily picked by the caller), this is not done in a way that breaks the invariant of the `Immediate` type.
This leads to ICEs in a GVN mir-opt test, so the second commit fixes GVN.
Fixes https://github.com/rust-lang/rust/issues/131064.
This change `const`-qualifies many methods on Vec and String, notably
`as_slice`, `as_str`, `len`. These changes are made behind the unstable
feature flag `const_vec_string_slice` with the following tracking issue:
https://github.com/rust-lang/rust/issues/129041
add `naked_asm!` macro for use in `#[naked]` functions
tracking issue: https://github.com/rust-lang/rust/issues/90957
Adds the `core::arch::naked_asm` macro, to be used in `#[naked]` functions, but providing better error messages and a place to explain the restrictions on assembly in naked functions.
This PR does not yet require that the `naked_asm!` macro is used inside of `#[naked]` functions:
- the `asm!` macro can still be used in `#[naked]` functions currently, with the same restrictions and error messages as before.
- the `naked_asm!` macro can be used outside of `#[naked]` functions. It has not yet been decided whether that should be allowed long-term.
In this PR, the parsing code of `naked_asm!` now enforces the restrictions on assembly in naked functions, with the exception of checking that the `noreturn` option is specified. It also has not currently been decided if `noreturn` should be implicit or not.
This PR looks large because it touches a bunch of tests. The code changes are mostly straightforward I think: we now have 3 flavors of assembly macro, and that information must be propagated through the parsing code and error messages.
cc `@Lokathor`
r? `@Amanieu`
- fix for divergence
- fix error message
- fix another cranelift test
- fix some cranelift things
- don't set the NORETURN option for naked asm
- fix use of naked_asm! in doc comment
- fix use of naked_asm! in run-make test
- use `span_bug` in unreachable branch
Make deprecated_cfg_attr_crate_type_name a hard error
Turns the forward compatibility lint added by #83744 into a hard error, so now, while the `#![crate_name]` and `#![crate_type]` attributes are still allowed in raw form, they are now forbidden to be nested inside a `#![cfg_attr()]` attribute.
The following will now be an error:
```Rust
#![cfg_attr(foo, crate_name = "foobar")]
#![cfg_attr(foo, crate_type = "bin")]
```
This code will continue working and is not deprecated:
```Rust
#![crate_name = "foobar"]
#![crate_type = "lib"]
```
The reasoning for this is explained in #83744: it allows us to not have to cfg-expand in order to determine the crate's type and name.
As of filing the PR, exactly two years have passed since #99784 has been merged, which has turned the lint's default warning level into an error, so there has been ample time to move off the now-forbidden syntax.
cc #91632 - tracking issue for the lint
On function and method calls in patterns, link to the book
```
error: expected a pattern, found an expression
--> f889.rs:3:13
|
3 | let (x, y.drop()) = (1, 2);
| ^^^^^^^^ not a pattern
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
error[E0532]: expected a pattern, found a function call
--> f889.rs:2:13
|
2 | let (x, drop(y)) = (1, 2);
| ^^^^ not a tuple struct or tuple variant
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
```
Fix#97200.
Do not consider match/let/ref of place that evaluates to `!` to diverge, disallow coercions from them too
Fixes#117288.
This PR implements a heuristic which disables two things that are currently being performed on the HIR when we have **expressions that involve place-like expressions that point to `!`**. Specifically, it will (in certain cases explained below):
### (1.) Disable the `NeverToAny` coercion we implicitly insert for `!`.
Which fixes this inadvertent, sneaky unsoundness:
```
unsafe {
let x: *const ! = &0 as *const u8 as *const !;
let _: () = *x;
}
```
which is UB because currently rust emits an *implicit* NeverToAny coercion even though we really shouldn't be, since there's no read of the value pointed by `x`.
### (2.) Disable the logic which considers expression which evaluate to `!` to diverge, which affects the type returned by the containing block.
Which fixes this unsoundness:
```
fn make_up_a_value<T>() -> T {
unsafe {
let x: *const ! = &0 as *const u8 as *const !;
let _ = *x;
}
}
```
We disable these two operations **if** the expression is a place-like expression (locals, statics, field projections, index operations, and deref operations), and if the parent expression is either:
(1.) the LHS of an assignment
(2.) AddrOf
(3.) A match or let **unless** all of the *patterns consitute a read*, which is explained below:
And finally, a pattern currently is considered to constitute a read **unless** it is a wildcard, or an OR pattern. An OR pattern is considered to constitute a read if all of its subpatterns constitute a read, to remain as conservative as possible in cases like `_ | subpat` or `subpat | _`.
All other patterns are considered currently to constitute a read. Specifically, because `NeverToAny` is a coercion performed on a *value* and not a *place*, `Struct { .. }` on a `!` type must be a coercion currently, and we currently rely on this behavior to allow us to perform coercions like `let _: i32 = x;` where `x: !`.
This is already considered UB by [miri](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=daf3a2246433fe43fdc07d1389c276c9), but also means it does not affect the preexisting UB in this case:
```
let Struct { .. } = *never_ptr;
```
Even though it's likely up for debate since we're not actually reading any data out of the struct, it almost certainly causes inference changes which I do *NOT* want to fix in this PR.
```
error: expected a pattern, found an expression
--> f889.rs:3:13
|
3 | let (x, y.drop()) = (1, 2); //~ ERROR
| ^^^^^^^^ not a pattern
|
= note: arbitrary expressions are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
error[E0532]: expected a pattern, found a function call
--> f889.rs:2:13
|
2 | let (x, drop(y)) = (1, 2); //~ ERROR
| ^^^^ not a tuple struct or tuple variant
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch18-00-patterns.html>
```
Fix#97200.
Initial support for riscv32{e|em|emc}_unknown_none_elf
We have a research prototype of an RV32EMC target and have been successfully running the e, em, emc programs on it. I'm hoping upstreaming this configuration would make the target maintenance slightly easier.
Configuration is based on the respective {i, im, imc} variants. As defined in RISC-V Unprivileged Spec. 20191213, the only change in RVE wrt. RVI is to reduce the number of integer registers to 16 (x0-x15), which also implies
- 2 callee saved registers instead of 12
- 32-bit / 4-byte stack alignment instead of 128 bits / 16 bytes
My initial presumption is that this will not impact how the target is defined for the compiler but only becomes relevant at the runtime level. I am willing to investigate, though.
EDIT: LLVM is now told about the presumed 32-bit stack alignment.
`@Disasm` `@romancardenas`
Make opaque types regular HIR nodes
Having opaque types as HIR owner introduces all sorts of complications. This PR proposes to make them regular HIR nodes instead.
I haven't gone through all the test changes yet, so there may be a few surprises.
Many thanks to `@camelid` for the first draft.
Fixes https://github.com/rust-lang/rust/issues/129023Fixes#129099Fixes#125843Fixes#119716Fixes#121422
Account for `impl Trait {` when `impl Trait for Type {` was intended
On editions where bare traits are never allowed, detect if the user has written `impl Trait` with no type, silence any dyn-compatibility errors, and provide a structured suggestion for the potentially missing type:
```
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^
|
help: add `dyn` keyword before this trait
|
LL | impl dyn Foo<i64> {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Foo<i64> for /* Type */ {
| ++++++++++++++
```
CC #131051.
Add support for reborrowing pinned method receivers
This builds on #130526 to add pinned reborrowing for method receivers. This enables the folllowing examples to work:
```rust
#![feature(pin_ergonomics)]
#![allow(incomplete_features)]
use std::pin::Pin;
pub struct Foo;
impl Foo {
fn foo(self: Pin<&mut Self>) {
}
fn baz(self: Pin<&Self>) {
}
}
pub fn bar(x: Pin<&mut Foo>) {
x.foo();
x.foo();
x.baz(); // Pin<&mut Foo> is downgraded to Pin<&Foo>
}
pub fn baaz(x: Pin<&Foo>) {
x.baz();
x.baz();
}
```
This PR includes the original one, which is currently in the commit queue, but the only code changes are in the latest commit (d3c53aaa5c6fcb1018c58d229bc5d92202fa6880).
#130494
r? `@compiler-errors`
Check elaborated projections from dyn don't mention unconstrained late bound lifetimes
Check that the projections that are *not* explicitly written but which we deduce from elaborating the principal of a `dyn` *also* do not reference unconstrained late-bound lifetimes, just like the ones that the user writes by hand.
That is to say, given:
```
trait Foo<T>: Bar<Assoc = T> {}
trait Bar {
type Assoc;
}
```
The type `dyn for<'a> Foo<&'a T>` (basically) elaborates to `dyn for<'a> Foo<&'a T> + for<'a> Bar<Assoc = &'a T>`[^1]. However, the `Bar` projection predicate is not well-formed, since `'a` must show up in the trait's arguments to be referenced in the term of a projection. We must error in this situation[^well], or else `dyn for<'a> Foo<&'a T>` is unsound.
We already detect this for user-written projections during HIR->rustc_middle conversion, so this largely replicates that logic using the helper functions that were already conveniently defined.
---
I'm cratering this first to see the fallout; if it's minimal or zero, then let's land it as-is. If not, the way that this is implemented is very conducive to an FCW.
---
Fixes#130347
[^1]: We don't actually elaborate it like that in rustc; we only keep the principal trait ref `Foo<&'a T>` and the projection part of `Bar<Assoc = ...>`, but it's useful to be a bit verbose here for the purpose of explaining the issue.
[^well]: Well, we could also make `dyn for<'a> Foo<&'a T>` *not* implement `for<'a> Bar<Assoc = &'a T>`, but this is inconsistent with the case where the user writes `Assoc = ...` in the type itself, and it overly complicates the implementation of trait objects' built-in impls.
On editions where bare traits are never allowed, detect if the user has
written `impl Trait` with no type, silence any dyn-compatibility errors,
and provide a structured suggestion for the potentially missing type:
```
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/missing-for-type-in-impl.rs:8:6
|
LL | impl Foo<i64> {
| ^^^^^^^^
|
help: add `dyn` keyword before this trait
|
LL | impl dyn Foo<i64> {
| +++
help: you might have intended to implement this trait for a given type
|
LL | impl Foo<i64> for /* Type */ {
| ++++++++++++++
```
Fix `target_abi` in `sparc-unknown-none-elf`
This was previously set to `target_abi = "elf"`, but `elf` is not used elsewhere as a target ABI (even though there's many targets that have it in their name), so I've removed it.
CC target maintainer ``@jonathanpallant,`` what do you think about this?
``@rustbot`` label O-SPARC
Stabilize the `map`/`value` methods on `ControlFlow`
And fix the stability attribute on the `pub use` in `core::ops`.
libs-api in https://github.com/rust-lang/rust/issues/75744#issuecomment-2231214910 seemed reasonably happy with naming for these, so let's try for an FCP.
Summary:
```rust
impl<B, C> ControlFlow<B, C> {
pub fn break_value(self) -> Option<B>;
pub fn map_break<T>(self, f: impl FnOnce(B) -> T) -> ControlFlow<T, C>;
pub fn continue_value(self) -> Option<C>;
pub fn map_continue<T>(self, f: impl FnOnce(C) -> T) -> ControlFlow<B, T>;
}
```
Resolves#75744
``@rustbot`` label +needs-fcp +t-libs-api -t-libs
---
Aside, in case it keeps someone else from going down the same dead end: I looked at the `{break,continue}_value` methods and tried to make them `const` as part of this, but that's disallowed because of not having `const Drop`, so put it back to not even unstably-const.
Add x86_64-unknown-trusty as tier 3 target
This PR adds a third target for the Trusty platform, `x86_64-unknown-trusty`.
Please let me know if an MCP is required. https://github.com/rust-lang/compiler-team/issues/582 was made when adding the first two targets, I can make another one for the new target as well if needed.
# Target Tier Policy Acknowledgements
> A tier 3 target must have a designated developer or developers (the "target maintainers") on record to be CCed when issues arise regarding the target. (The mechanism to track and CC such developers may evolve over time.)
- Nicole LeGare (```@randomPoison)```
- Andrei Homescu (```@ahomescu)```
- Chris Wailes (chriswailes@google.com)
- As a fallback trusty-dev-team@google.com can be contacted
Note that this does not reflect the maintainers currently listed in [`trusty.md`](c52c23b6f4/src/doc/rustc/src/platform-support/trusty.md). #130452 is currently open to update the list of maintainers in the documentation.
> Targets must use naming consistent with any existing targets; for instance, a target for the same CPU or OS as an existing Rust target should use the same name for that CPU or OS. Targets should normally use the same names and naming conventions as used elsewhere in the broader ecosystem beyond Rust (such as in other toolchains), unless they have a very good reason to diverge. Changing the name of a target can be highly disruptive, especially once the target reaches a higher tier, so getting the name right is important even for a tier 3 target.
The new target `x86_64-unknown-trusty` follows the existing naming convention for similar targets.
> Target names should not introduce undue confusion or ambiguity unless absolutely necessary to maintain ecosystem compatibility. For example, if the name of the target makes people extremely likely to form incorrect beliefs about what it targets, the name should be changed or augmented to disambiguate it.
👍
> Tier 3 targets may have unusual requirements to build or use, but must not create legal issues or impose onerous legal terms for the Rust project or for Rust developers or users.
There are no known legal issues or license incompatibilities.
> Neither this policy nor any decisions made regarding targets shall create any binding agreement or estoppel by any party. If any member of an approving Rust team serves as one of the maintainers of a target, or has any legal or employment requirement (explicit or implicit) that might affect their decisions regarding a target, they must recuse themselves from any approval decisions regarding the target's tier status, though they may otherwise participate in discussions.
👍
> Tier 3 targets should attempt to implement as much of the standard libraries as possible and appropriate (core for most targets, alloc for targets that can support dynamic memory allocation, std for targets with an operating system or equivalent layer of system-provided functionality), but may leave some code unimplemented (either unavailable or stubbed out as appropriate), whether because the target makes it impossible to implement or challenging to implement. The authors of pull requests are not obligated to avoid calling any portions of the standard library on the basis of a tier 3 target not implementing those portions.
This PR only adds the target. `std` support is being worked on and will be added in a future PR.
> The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target supports running binaries, or running tests (even if they do not pass), the documentation must explain how to run such binaries or tests for the target, using emulation if possible or dedicated hardware if necessary.
👍
> Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a block on the PR based on a tier 3 target. Do not send automated messages or notifications (via any medium, including via ```@)``` to a PR author or others involved with a PR regarding a tier 3 target, unless they have opted into such messages.
👍
> Patches adding or updating tier 3 targets must not break any existing tier 2 or tier 1 target, and must not knowingly break another tier 3 target without approval of either the compiler team or the maintainers of the other tier 3 target.
👍
> Tier 3 targets must be able to produce assembly using at least one of rustc's supported backends from any host target. (Having support in a fork of the backend is not sufficient, it must be upstream.)
👍
This was previously set to `target_abi = "elf"`, but `elf` is not used
elsewhere as a target ABI (even though there's many targets that have it
in their name).