Skip to content

Commit 6a088fd

Browse files
Defer tail call ret ty equality to check_tail_calls
1 parent 16ad385 commit 6a088fd

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,7 +1895,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18951895
if !output_ty
18961896
.is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
18971897
{
1898-
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
1898+
span_mirbug!(self, term, "call to non-diverging function {:?} w/o dest", sig);
18991899
}
19001900
} else {
19011901
let dest_ty = destination.ty(self.body, tcx).ty;

compiler/rustc_mir_build/src/check_tail_calls.rs

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -135,30 +135,23 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
135135
self.report_abi_mismatch(expr.span, caller_sig.abi, callee_sig.abi);
136136
}
137137

138+
// FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
139+
// e.g.
140+
// ```
141+
// fn a() -> impl Sized { become b() } // ICE
142+
// fn b() -> u8 { 0 }
143+
// ```
144+
// we should think what is the expected behavior here.
145+
// (we should probably just accept this by revealing opaques?)
138146
if caller_sig.inputs_and_output != callee_sig.inputs_and_output {
139-
if caller_sig.inputs() != callee_sig.inputs() {
140-
self.report_arguments_mismatch(
141-
expr.span,
142-
self.tcx.liberate_late_bound_regions(
143-
CRATE_DEF_ID.to_def_id(),
144-
self.caller_ty.fn_sig(self.tcx),
145-
),
146-
self.tcx
147-
.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
148-
);
149-
}
150-
151-
// FIXME(explicit_tail_calls): this currently fails for cases where opaques are used.
152-
// e.g.
153-
// ```
154-
// fn a() -> impl Sized { become b() } // ICE
155-
// fn b() -> u8 { 0 }
156-
// ```
157-
// we should think what is the expected behavior here.
158-
// (we should probably just accept this by revealing opaques?)
159-
if caller_sig.output() != callee_sig.output() {
160-
span_bug!(expr.span, "hir typeck should have checked the return type already");
161-
}
147+
self.report_signature_mismatch(
148+
expr.span,
149+
self.tcx.liberate_late_bound_regions(
150+
CRATE_DEF_ID.to_def_id(),
151+
self.caller_ty.fn_sig(self.tcx),
152+
),
153+
self.tcx.liberate_late_bound_regions(CRATE_DEF_ID.to_def_id(), ty.fn_sig(self.tcx)),
154+
);
162155
}
163156

164157
{
@@ -365,7 +358,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
365358
self.found_errors = Err(err);
366359
}
367360

368-
fn report_arguments_mismatch(
361+
fn report_signature_mismatch(
369362
&mut self,
370363
sp: Span,
371364
caller_sig: ty::FnSig<'_>,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(explicit_tail_calls)]
2+
#![expect(incomplete_features)]
3+
4+
fn foo() -> for<'a> fn(&'a i32) {
5+
become bar();
6+
//~^ ERROR mismatched signatures
7+
}
8+
9+
fn bar() -> fn(&'static i32) {
10+
dummy
11+
}
12+
13+
fn dummy(_: &i32) {}
14+
15+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error: mismatched signatures
2+
--> $DIR/ret-ty-hr-mismatch.rs:5:5
3+
|
4+
LL | become bar();
5+
| ^^^^^^^^^^^^
6+
|
7+
= note: `become` requires caller and callee to have matching signatures
8+
= note: caller signature: `fn() -> for<'a> fn(&'a i32)`
9+
= note: callee signature: `fn() -> fn(&'static i32)`
10+
11+
error: aborting due to 1 previous error
12+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Ensure that we anonymize the output of a function for tail call signature compatibility.
2+
3+
//@ check-pass
4+
5+
#![feature(explicit_tail_calls)]
6+
#![expect(incomplete_features)]
7+
8+
fn foo() -> for<'a> fn(&'a ()) {
9+
become bar();
10+
}
11+
12+
fn bar() -> for<'b> fn(&'b ()) {
13+
todo!()
14+
}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)