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 /compiler/rustc_monomorphize | |
| 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 'compiler/rustc_monomorphize')
| -rw-r--r-- | compiler/rustc_monomorphize/src/collector.rs | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index af2c3177067..6a836442c32 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -789,7 +789,35 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // *Before* monomorphizing, record that we already handled this mention. self.used_mentioned_items.insert(MentionedItem::Fn(callee_ty)); let callee_ty = self.monomorphize(callee_ty); - visit_fn_use(self.tcx, callee_ty, true, source, &mut self.used_items) + + // HACK(explicit_tail_calls): collect tail calls to `#[track_caller]` functions as indirect, + // because we later call them as such, to prevent issues with ABI incompatibility. + // Ideally we'd replace such tail calls with normal call + return, but this requires + // post-mono MIR optimizations, which we don't yet have. + let force_indirect_call = + if matches!(terminator.kind, mir::TerminatorKind::TailCall { .. }) + && let &ty::FnDef(def_id, args) = callee_ty.kind() + && let instance = ty::Instance::expect_resolve( + self.tcx, + ty::TypingEnv::fully_monomorphized(), + def_id, + args, + source, + ) + && instance.def.requires_caller_location(self.tcx) + { + true + } else { + false + }; + + visit_fn_use( + self.tcx, + callee_ty, + !force_indirect_call, + source, + &mut self.used_items, + ) } mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; |
