Open
Description
This came up here. @WaffleLapkin provided an example:
#![feature(explicit_tail_calls)]
use std::num::NonZeroU8;
use std::mem::transmute;
fn a() -> u8 { 0 }
fn b() -> NonZeroU8 { unsafe {
become transmute::<fn() -> u8, fn() -> NonZeroU8>(a)();
} }
fn c() {
let _x: u8 = unsafe { transmute::<fn() -> NonZeroU8, fn() -> u8>(b)() };
}
As a normal call, there would be UB when b
returns, since the return place at that moment contains something that is invalid for b
's return type (despite being valid for c
's return type).
However, with tail calls, b
is long gone by the time a
returns. a
returns directly to c
, and both caller and callee see a return type of u8
. So arguably this program should be allowed? More fundamentally, not allowing this program means that Miri / the spec would have to keep around the return type of all the stack frames that were "popped early" due to tail calls, and ensure that the eventual return type is valid according to all of them -- which seems to go against the very idea of a tail call.
Metadata
Metadata
Assignees
Labels
No labels