diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-08-15 16:16:31 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-15 16:16:31 +1000 |
| commit | 44eb7a167c9df395c803bf113a933f668b4c278a (patch) | |
| tree | 0b352a5e4f981570afdb0135b40f873df7a56441 /tests | |
| parent | 603b61df5768c95c994a4cde42898edf394c5f6f (diff) | |
| parent | fa18b3ebe29154440f6e8d9ad83021802b3aaa29 (diff) | |
| download | rust-44eb7a167c9df395c803bf113a933f668b4c278a.tar.gz rust-44eb7a167c9df395c803bf113a933f668b4c278a.zip | |
Rollup merge of #144865 - WaffleLapkin:track-tail, r=lqd
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 closes rust-lang/rust#144762) Fixes https://github.com/rust-lang/rust/issues/144755
Diffstat (limited to 'tests')
4 files changed, 43 insertions, 2 deletions
diff --git a/tests/ui/explicit-tail-calls/callee_is_track_caller.rs b/tests/ui/explicit-tail-calls/callee_is_track_caller.rs index bcb93fda8c8..b85b335844b 100644 --- a/tests/ui/explicit-tail-calls/callee_is_track_caller.rs +++ b/tests/ui/explicit-tail-calls/callee_is_track_caller.rs @@ -1,10 +1,11 @@ -//@ check-pass -// FIXME(explicit_tail_calls): make this run-pass, once tail calls are properly implemented +//@ run-pass +//@ ignore-pass #![expect(incomplete_features)] #![feature(explicit_tail_calls)] fn a(x: u32) -> u32 { become b(x); + //~^ warning: tail calling a function marked with `#[track_caller]` has no special effect } #[track_caller] diff --git a/tests/ui/explicit-tail-calls/callee_is_track_caller.stderr b/tests/ui/explicit-tail-calls/callee_is_track_caller.stderr new file mode 100644 index 00000000000..e1a251d156f --- /dev/null +++ b/tests/ui/explicit-tail-calls/callee_is_track_caller.stderr @@ -0,0 +1,10 @@ +warning: tail calling a function marked with `#[track_caller]` has no special effect + --> $DIR/callee_is_track_caller.rs:7:12 + | +LL | become b(x); + | ^^^^ + | + = note: `#[warn(tail_call_track_caller)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.rs b/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.rs new file mode 100644 index 00000000000..33384de83eb --- /dev/null +++ b/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.rs @@ -0,0 +1,20 @@ +//@ run-pass +//@ ignore-pass +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +fn c<T: Trait>() { + become T::f(); + //~^ warning: tail calling a function marked with `#[track_caller]` has no special effect +} + +trait Trait { + #[track_caller] + fn f() {} +} + +impl Trait for () {} + +fn main() { + c::<()>(); +} diff --git a/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.stderr b/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.stderr new file mode 100644 index 00000000000..5a1c40509ad --- /dev/null +++ b/tests/ui/explicit-tail-calls/callee_is_track_caller_polymorphic.stderr @@ -0,0 +1,10 @@ +warning: tail calling a function marked with `#[track_caller]` has no special effect + --> $DIR/callee_is_track_caller_polymorphic.rs:7:12 + | +LL | become T::f(); + | ^^^^^^ + | + = note: `#[warn(tail_call_track_caller)]` on by default + +warning: 1 warning emitted + |
