From c7ea022166d2b6d55c3f69bbf69a31b0d7b053e2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 4 Aug 2025 16:24:41 +0000 Subject: [PATCH] Enforce tail call type is related to body return type in borrowck --- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +++++++--- .../ret-ty-borrowck-constraints.rs | 16 ++++++++++++++++ .../ret-ty-borrowck-constraints.stderr | 10 ++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.rs create mode 100644 tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f5fedbf95c1c..91973f33bd32 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -845,9 +845,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } - if let TerminatorKind::Call { destination, target, .. } = term.kind { - self.check_call_dest(term, &sig, destination, target, term_location); - } + let (destination, target) = + if let TerminatorKind::Call { destination, target, .. } = term.kind { + (destination, target) + } else { + (RETURN_PLACE.into(), Some(BasicBlock::ZERO)) + }; + self.check_call_dest(term, &sig, destination, target, term_location); // The ordinary liveness rules will ensure that all // regions in the type of the callee are live here. We diff --git a/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.rs b/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.rs new file mode 100644 index 000000000000..111ae849c0f6 --- /dev/null +++ b/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.rs @@ -0,0 +1,16 @@ +#![feature(explicit_tail_calls)] +#![expect(incomplete_features)] + +fn link(x: &str) -> &'static str { + become passthrough(x); + //~^ ERROR lifetime may not live long enough +} + +fn passthrough(t: T) -> T { t } + +fn main() { + let x = String::from("hello, world"); + let s = link(&x); + drop(x); + println!("{s}"); +} diff --git a/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.stderr b/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.stderr new file mode 100644 index 000000000000..26a8e1f0122a --- /dev/null +++ b/tests/ui/explicit-tail-calls/ret-ty-borrowck-constraints.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/ret-ty-borrowck-constraints.rs:5:5 + | +LL | fn link(x: &str) -> &'static str { + | - let's call the lifetime of this reference `'1` +LL | become passthrough(x); + | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error +