Fix tail calls to `#[track_caller]` functions
We want `#[track_caller]` to be semver independent, i.e. it should not be a breaking change to add or remove it. Since it changes ABI of a function (adding an additional argument) we have to be careful to preserve this property when adding tail calls.
The only way to achieve this that I can see is:
- we forbid tail calls in functions which are marked with `#[track_caller]` (already implemented)
- tail-calling a `#[track_caller]` marked function downgrades the tail-call to a normal call (or equivalently tail-calls the shim made by fn def to fn ptr cast) (this pr)
Ideally the downgrade would be performed by a MIR pass, but that requires post mono MIR opts (cc ```@saethlin,``` rust-lang/rust#131650). For now I've changed code in cg_ssa to accomodate this behaviour (+ added a hack to mono collector so that the shim is actually generated)
Additionally I added a lint, although I don't think it's strictly necessary.
Alternative to rust-lang/rust#144762 (and thus closesrust-lang/rust#144762)
Fixes https://github.com/rust-lang/rust/issues/144755
Additional tce tests
r? `@oli-obk`
Adds known-bug tests for LLVM emissions regarding indirect operands for TCE. Also includes a test, `indexer.rs`, referring to function_table behavior described by the RFC.
Depends on rust-lang/rust#144232Closesrust-lang/rust#144293
Enforce tail call type is related to body return type in borrowck
Like all call terminators, tail call terminators instantiate the binder of the callee signature with region variables and equate the arg operand types with that signature's args to ensure that the call is valid.
However, unlike normal call terminators, we were forgetting to also relate the return type of the call terminator to anything. In the case of tail call terminators, the correct thing is to relate it to the return type of the caller function (or in other words, the return local `_0`).
This meant that if the caller's return type had some lifetime constraint, then that constraint wouldn't flow through the signature and affect the args.
This is what's happening in the example test I committed:
```rust
fn link(x: &str) -> &'static str {
become passthrough(x);
}
fn passthrough<T>(t: T) -> T { t }
fn main() {
let x = String::from("hello, world");
let s = link(&x);
drop(x);
println!("{s}");
}
```
Specifically, the type `x` is `'?0 str`, where `'?0` is some *universal* arg. The type of `passthrough` is `fn(&'?1 str) -> &'?1 str`. Equating the args sets `'?0 = '?1`. However, we need to also equate the return type `&'?1 str` to `&'static str` so that we eventually require that `'?0 = 'static`, which is a borrowck error!
-----
Look at the first commit for the functional change, and the second commit is just a refactor because we don't need to pass `Option<BasicBlock>` to `check_call_dest`, but just whether or not the terminator is expected to be diverging (i.e. if the return type is `!`).
Fixesrust-lang/rust#144916
Previously, we included a redundant prefix on the panic message and a postfix of the location of the panic. The prefix didn't carry any additional information beyond "something failed", and the location of the panic is redundant with the diagnostic's span, which gets printed out even if its code is not shown.
```
error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:11:9
|
LL | MaybeUninit::<!>::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: aborted execution: attempted to instantiate uninhabited type `!`
```
```
error[E0080]: evaluation of `Fail::<i32>::C` failed
--> $DIR/collect-in-dead-closure.rs:9:19
|
LL | const C: () = panic!();
| ^^^^^^^^ evaluation panicked: explicit panic
|
= note: this error originates in the macro
`$crate::panic::panic_2015` which comes from the expansion of the macro
`panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
```
error[E0080]: evaluation of constant value failed
--> $DIR/uninhabited.rs:41:9
|
LL | assert!(false);
| ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
```
---
When the primary span for a const error is the same as the first frame in the const error report, skip it.
```
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| ^^^^^^^^^^^^^^ evaluation panicked: explicit panic
|
note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34}>`
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^ the failure occurred here
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
instead of
```
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^ explicit panic
|
note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34}>`
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^
note: inside `_CONST`
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| ^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
---
Revert order of constant evaluation errors
Point at the code the user wrote first and std functions last.
```
error[E0080]: evaluation of constant value failed
--> $DIR/const-errs-dont-conflict-103369.rs:5:25
|
LL | impl ConstGenericTrait<{my_fn(1)}> for () {}
| ^^^^^^^^ evaluation panicked: Some error occurred
|
note: called from `my_fn`
--> $DIR/const-errs-dont-conflict-103369.rs:10:5
|
LL | panic!("Some error occurred");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
instead of
```
error[E0080]: evaluation of constant value failed
--> $DIR/const-errs-dont-conflict-103369.rs:10:5
|
LL | panic!("Some error occurred");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some error occurred
|
note: called from `<() as ConstGenericTrait<{my_fn(1)}>>::{constant#0}`
--> $DIR/const-errs-dont-conflict-103369.rs:5:25
|
LL | impl ConstGenericTrait<{my_fn(1)}> for () {}
| ^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
```
error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
--> $DIR/attempted-access-non-fatal.rs:7:15
|
LL | let _ = 2.l;
| ^
|
help: if intended to be a floating point literal, consider adding a `0` after the period and a `f64` suffix
|
LL - let _ = 2.l;
LL + let _ = 2.0f64;
|
```
fix tail call checks wrt `#[track_caller]`
Only check the caller + disallow caller having the attribute.
fixes#134336
r? `@compiler-errors`
<sub>apparently there were no tests for `#[track_caller]` before... ooops</sub>
implement checks for tail calls
Quoting the [RFC draft](https://github.com/phi-go/rfcs/blob/guaranteed-tco/text/0000-explicit-tail-calls.md):
> The argument to become is a function (or method) call, that exactly matches the function signature and calling convention of the callee. The intent is to ensure a matching ABI. Note that lifetimes may differ as long as they pass borrow checking, see [below](https://github.com/phi-go/rfcs/blob/guaranteed-tco/text/0000-explicit-tail-calls.md#return-type-coercion) for specifics on the return type.
> Tail calling closures and tail calling from closures is not allowed. This is due to the high implementation effort, see below, this restriction can be lifted by a future RFC.
> Invocations of operators were considered as valid targets but were rejected on grounds of being too error-prone. In any case, these can still be called as methods.
> Tail calling [variadic functions](https://doc.rust-lang.org/beta/unstable-book/language-features/c-variadic.html) and tail calling from variadic functions is not allowed. As support for variadic function is stabilized on a per target level, support for tail-calls regarding variadic functions would need to follow a similar approach. To avoid this complexity and to minimize implementation effort for backends, this interaction is currently not allowed but support can be added with a future RFC.
-----
The checks are implemented as a query, similarly to `check_unsafety`.
The code is cherry-picked straight out of #112657 which was written more than a year ago, so I expect we might need to change some things ^^"
this implements checks necessary to guarantee that we can actually
perform a tail call. while extremely restrictive, this is what is
documented in the RFC, and all these checks are needed for one reason or
another.
This improves parallel rustc parallelism by avoiding the bottleneck after each individual `par_body_owners` (because it needs to wait for queries to finish, so if there is one long running one, a lot of cores will be idle while waiting for the single query).