Defer tail call ret ty equality to check_tail_calls

This commit is contained in:
Michael Goulet 2025-08-19 20:15:43 +00:00
parent 16ad385579
commit 6a088fd584
5 changed files with 61 additions and 25 deletions

View file

@ -1895,7 +1895,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if !output_ty
.is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
{
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
span_mirbug!(self, term, "call to non-diverging function {:?} w/o dest", sig);
}
} else {
let dest_ty = destination.ty(self.body, tcx).ty;

View file

@ -135,30 +135,23 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
}
// FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
// e.g.
// ```
// fn a() -> impl Sized { become b() } // ICE
// fn b() -> u8 { 0 }
// ```
// we should think what is the expected behavior here.
// (we should probably just accept this by revealing opaques?)
if caller_sig.inputs_and_output != callee_sig.inputs_and_output {
if caller_sig.inputs() != callee_sig.inputs() {
self.report_arguments_mismatch(
expr.span,
self.tcx.liberate_late_bound_regions(
CRATE_DEF_ID.to_def_id(),
self.caller_ty.fn_sig(self.tcx),
),
self.tcx
.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
);
}
// FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
// e.g.
// ```
// fn a() -> impl Sized { become b() } // ICE
// fn b() -> u8 { 0 }
// ```
// we should think what is the expected behavior here.
// (we should probably just accept this by revealing opaques?)
if caller_sig.output() != callee_sig.output() {
span_bug!(expr.span, "hir typeck should have checked the return type already");
}
self.report_signature_mismatch(
expr.span,
self.tcx.liberate_late_bound_regions(
CRATE_DEF_ID.to_def_id(),
self.caller_ty.fn_sig(self.tcx),
),
self.tcx.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
);
}
{
@ -365,7 +358,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
self.found_errors = Err(err);
}
fn report_arguments_mismatch(
fn report_signature_mismatch(
&mut self,
sp: Span,
caller_sig: ty::FnSig<'_>,

View file

@ -0,0 +1,15 @@
#![feature(explicit_tail_calls)]
#![expect(incomplete_features)]
fn foo() -> for<'a> fn(&'a i32) {
become bar();
//~^ ERROR mismatched signatures
}
fn bar() -> fn(&'static i32) {
dummy
}
fn dummy(_: &i32) {}
fn main() {}

View file

@ -0,0 +1,12 @@
error: mismatched signatures
--> $DIR/ret-ty-hr-mismatch.rs:5:5
|
LL | become bar();
| ^^^^^^^^^^^^
|
= note: `become` requires caller and callee to have matching signatures
= note: caller signature: `fn() -> for<'a> fn(&'a i32)`
= note: callee signature: `fn() -> fn(&'static i32)`
error: aborting due to 1 previous error

View file

@ -0,0 +1,16 @@
// Ensure that we anonymize the output of a function for tail call signature compatibility.
//@ check-pass
#![feature(explicit_tail_calls)]
#![expect(incomplete_features)]
fn foo() -> for<'a> fn(&'a ()) {
become bar();
}
fn bar() -> for<'b> fn(&'b ()) {
todo!()
}
fn main() {}