about summary refs log tree commit diff
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2024-02-15 19:54:37 +0000
committerMaybe Lapkin <waffle.lapkin@gmail.com>2024-07-07 17:11:04 +0200
commit484152d562f6babaacb3fae08cc5f70ee550e9ee (patch)
tree300d1010e369b3960213e11a75713fa64e0a0525 /compiler/rustc_borrowck
parente2cf31a6148725bde4ea48acf1e4fe72675257a2 (diff)
downloadrust-484152d562f6babaacb3fae08cc5f70ee550e9ee.tar.gz
rust-484152d562f6babaacb3fae08cc5f70ee550e9ee.zip
Support tail calls in mir via `TerminatorKind::TailCall`
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/src/lib.rs9
-rw-r--r--compiler/rustc_borrowck/src/polonius/loan_invalidations.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs20
3 files changed, 30 insertions, 5 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index e6f8ffd428d..df532c73950 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -728,6 +728,12 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
                 }
                 self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
+            TerminatorKind::TailCall { func, args, fn_span: _ } => {
+                self.consume_operand(loc, (func, span), flow_state);
+                for arg in args {
+                    self.consume_operand(loc, (&arg.node, arg.span), flow_state);
+                }
+            }
             TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
                 if let AssertKind::BoundsCheck { len, index } = &**msg {
@@ -814,9 +820,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R>
 
             TerminatorKind::UnwindResume
             | TerminatorKind::Return
+            | TerminatorKind::TailCall { .. }
             | TerminatorKind::CoroutineDrop => {
-                // Returning from the function implicitly kills storage for all locals and statics.
-                // Often, the storage will already have been killed by an explicit
                 // StorageDead, but we don't always emit those (notably on unwind paths),
                 // so this "extra check" serves as a kind of backup.
                 let borrow_set = self.borrow_set.clone();
diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
index 6979910a02d..30dfc4c21b0 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
@@ -125,6 +125,12 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
                 }
                 self.mutate_place(location, *destination, Deep);
             }
+            TerminatorKind::TailCall { func, args, .. } => {
+                self.consume_operand(location, func);
+                for arg in args {
+                    self.consume_operand(location, &arg.node);
+                }
+            }
             TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(location, cond);
                 use rustc_middle::mir::AssertKind;
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index aa25e3adf28..8bba7ef4255 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1352,7 +1352,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
                 // FIXME: check the values
             }
-            TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
+            TerminatorKind::Call { func, args, .. }
+            | TerminatorKind::TailCall { func, args, .. } => {
+                let call_source = match term.kind {
+                    TerminatorKind::Call { call_source, .. } => call_source,
+                    TerminatorKind::TailCall { .. } => CallSource::Normal,
+                    _ => unreachable!(),
+                };
+
                 self.check_operand(func, term_location);
                 for arg in args {
                     self.check_operand(&arg.node, term_location);
@@ -1425,7 +1432,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
 
-                self.check_call_dest(body, term, &sig, *destination, *target, term_location);
+                if let TerminatorKind::Call { destination, target, .. } = term.kind {
+                    self.check_call_dest(body, 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
@@ -1443,7 +1452,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         .add_location(region_vid, term_location);
                 }
 
-                self.check_call_inputs(body, term, func, &sig, args, term_location, *call_source);
+                self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
             }
             TerminatorKind::Assert { cond, msg, .. } => {
                 self.check_operand(cond, term_location);
@@ -1675,6 +1684,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, block_data, "return on cleanup block")
                 }
             }
+            TerminatorKind::TailCall { .. } => {
+                if is_cleanup {
+                    span_mirbug!(self, block_data, "tailcall on cleanup block")
+                }
+            }
             TerminatorKind::CoroutineDrop { .. } => {
                 if is_cleanup {
                     span_mirbug!(self, block_data, "coroutine_drop in cleanup block")