Skip to content

Commit 20c26dc

Browse files
committed
Implement necessary checks for tail calls
1 parent ced6c93 commit 20c26dc

22 files changed

+874
-24
lines changed

compiler/rustc_middle/src/query/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,12 @@ rustc_queries! {
864864
cache_on_disk_if { true }
865865
}
866866

867+
/// Checks well-formedness of tail calls (`become f()`).
868+
query thir_check_tail_calls(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> {
869+
desc { |tcx| "tail-call-checking `{}`", tcx.def_path_str(key) }
870+
cache_on_disk_if { true }
871+
}
872+
867873
/// Returns the types assumed to be well formed while "inside" of the given item.
868874
///
869875
/// Note that we've liberated the late bound regions of function signatures, so

compiler/rustc_mir_build/src/build/expr/stmt.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
101101
),
102102
ExprKind::Become { value } => {
103103
let v = &this.thir[value];
104-
let ExprKind::Scope { region_scope, lint_level, value, .. } = v.kind else { span_bug!(v.span, "what {v:?}") };
104+
let ExprKind::Scope { region_scope, lint_level, value, .. } = v.kind
105+
else { span_bug!(v.span, "`thir_check_tail_calls` should have disallowed this {v:?}") };
105106
let v = &this.thir[value];
106-
let ExprKind::Call { ref args, fun, fn_span, .. } = v.kind else { span_bug!(v.span, "what {v:?}") };
107+
let ExprKind::Call { ref args, fun, fn_span, .. } = v.kind
108+
else { span_bug!(v.span, "`thir_check_tail_calls` should have disallowed this {v:?}") };
107109

108110
this.in_scope((region_scope, source_info), lint_level, |this| {
109111
let fun = unpack!(block = this.as_local_operand(block, &this.thir[fun]));

compiler/rustc_mir_build/src/build/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
4545
return construct_error(tcx, def, e);
4646
}
4747

48+
if let Err(err) = tcx.thir_check_tail_calls(def) {
49+
return construct_error(tcx, def, err);
50+
}
51+
4852
let body = match tcx.thir_body(def) {
4953
Err(error_reported) => construct_error(tcx, def, error_reported),
5054
Ok((thir, expr)) => {

0 commit comments

Comments
 (0)