about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_build/src/check_tail_calls.rs11
-rw-r--r--tests/ui/explicit-tail-calls/caller-lifetime-presence.rs51
-rw-r--r--tests/ui/explicit-tail-calls/caller-lifetime-presence.stderr32
3 files changed, 93 insertions, 1 deletions
diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs
index b4c8b20e50f..2b2c2cbc372 100644
--- a/compiler/rustc_mir_build/src/check_tail_calls.rs
+++ b/compiler/rustc_mir_build/src/check_tail_calls.rs
@@ -3,6 +3,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem;
 use rustc_hir::def::DefKind;
+use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::span_bug;
 use rustc_middle::thir::visit::{self, Visitor};
 use rustc_middle::thir::{BodyTy, Expr, ExprId, ExprKind, Thir};
@@ -132,7 +133,15 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
 
         if caller_sig.inputs_and_output != callee_sig.inputs_and_output {
             if caller_sig.inputs() != callee_sig.inputs() {
-                self.report_arguments_mismatch(expr.span, caller_sig, callee_sig);
+                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.
diff --git a/tests/ui/explicit-tail-calls/caller-lifetime-presence.rs b/tests/ui/explicit-tail-calls/caller-lifetime-presence.rs
new file mode 100644
index 00000000000..2382bc9dd1e
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/caller-lifetime-presence.rs
@@ -0,0 +1,51 @@
+//! Regression test for: https://github.com/rust-lang/rust/issues/144957
+//!
+//! This test ensures that lifetime information is included in diagnostics.
+//!
+//! Specifically, it checks that the `become` call produces an error with lifetimes shown
+//! in both caller and callee signatures.
+//!
+//! If the test fails:
+//! - Lifetimes may be missing (fix the diagnostic), or
+//! - The message format changed (update the test).
+
+#![feature(explicit_tail_calls)]
+#![allow(incomplete_features)]
+
+fn foo<'a>(_: fn(&'a ())) {
+    become bar(dummy);
+    //~^ ERROR mismatched signatures
+    //~| NOTE `become` requires caller and callee to have matching signatures
+    //~| NOTE caller signature: `fn(fn(&'a ()))`
+    //~| NOTE callee signature: `fn(for<'a> fn(&'a ()))`
+}
+
+fn bar(_: fn(&())) {}
+
+fn dummy(_: &()) {}
+
+fn foo_(_: fn(&())) {
+    become bar1(dummy2);
+    //~^ ERROR mismatched signatures
+    //~| NOTE `become` requires caller and callee to have matching signatures
+    //~| NOTE caller signature: `fn(for<'a> fn(&'a ()))`
+    //~| NOTE callee signature: `fn(fn(&'a ()))`
+}
+
+fn bar1<'a>(_: fn(&'a ())) {}
+
+fn dummy2(_: &()) {}
+
+fn foo__(_: fn(&'static ())) {
+    become bar(dummy3);
+    //~^ ERROR mismatched signatures
+    //~| NOTE `become` requires caller and callee to have matching signatures
+    //~| NOTE caller signature: `fn(fn(&'static ()))`
+    //~| NOTE callee signature: `fn(for<'a> fn(&'a ()))`
+}
+
+fn bar2(_: fn(&())) {}
+
+fn dummy3(_: &()) {}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/caller-lifetime-presence.stderr b/tests/ui/explicit-tail-calls/caller-lifetime-presence.stderr
new file mode 100644
index 00000000000..2fb981d9682
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/caller-lifetime-presence.stderr
@@ -0,0 +1,32 @@
+error: mismatched signatures
+  --> $DIR/caller-lifetime-presence.rs:16:5
+   |
+LL |     become bar(dummy);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn(fn(&'a ()))`
+   = note: callee signature: `fn(for<'a> fn(&'a ()))`
+
+error: mismatched signatures
+  --> $DIR/caller-lifetime-presence.rs:28:5
+   |
+LL |     become bar1(dummy2);
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn(for<'a> fn(&'a ()))`
+   = note: callee signature: `fn(fn(&'a ()))`
+
+error: mismatched signatures
+  --> $DIR/caller-lifetime-presence.rs:40:5
+   |
+LL |     become bar(dummy3);
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: `become` requires caller and callee to have matching signatures
+   = note: caller signature: `fn(fn(&'static ()))`
+   = note: callee signature: `fn(for<'a> fn(&'a ()))`
+
+error: aborting due to 3 previous errors
+