mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
Only count a tail-call if it actually is one
in e.g. case x of 0 -> 0 _ -> f ( x - 1) The old code would look at the first branch. it is not a tail call, so it concluded that the whole expression isn't. But the second branch is.
This commit is contained in:
parent
5063c3ac7f
commit
d171506fc7
1 changed files with 14 additions and 6 deletions
|
@ -841,9 +841,14 @@ fn canonicalize_case_branch<'a>(
|
||||||
|
|
||||||
// If all branches are tail calling the same symbol, then so is the conditional as a whole.
|
// If all branches are tail calling the same symbol, then so is the conditional as a whole.
|
||||||
if !*recorded_tail_call {
|
if !*recorded_tail_call {
|
||||||
// If we haven't recorded output.tail_call yet, record it.
|
match branch_output.tail_call {
|
||||||
output.tail_call = branch_output.tail_call;
|
Some(call) => {
|
||||||
*recorded_tail_call = true;
|
// If we haven't recorded output.tail_call yet, record it.
|
||||||
|
output.tail_call = Some(call);
|
||||||
|
*recorded_tail_call = true;
|
||||||
|
}
|
||||||
|
None => output.tail_call = None,
|
||||||
|
};
|
||||||
} else if branch_output.tail_call != output.tail_call {
|
} else if branch_output.tail_call != output.tail_call {
|
||||||
// If we recorded output.tail_call, but what we recorded differs from what we just saw,
|
// If we recorded output.tail_call, but what we recorded differs from what we just saw,
|
||||||
// then game over. This can't possibly be a self tail call!
|
// then game over. This can't possibly be a self tail call!
|
||||||
|
@ -1506,7 +1511,7 @@ fn can_defs<'a>(
|
||||||
ret_constraint: can_output.constraint.clone(),
|
ret_constraint: can_output.constraint.clone(),
|
||||||
})));
|
})));
|
||||||
|
|
||||||
// see below: a closure needs a fresh References!
|
// see below: a closure needs a fresh References!
|
||||||
let mut is_closure = false;
|
let mut is_closure = false;
|
||||||
|
|
||||||
match (
|
match (
|
||||||
|
@ -1532,7 +1537,11 @@ fn can_defs<'a>(
|
||||||
let references = env.closures.remove(&symbol).unwrap_or_else(||
|
let references = env.closures.remove(&symbol).unwrap_or_else(||
|
||||||
panic!("Tried to remove symbol {:?} from procedures, but it was not found: {:?}", symbol, env.closures));
|
panic!("Tried to remove symbol {:?} from procedures, but it was not found: {:?}", symbol, env.closures));
|
||||||
|
|
||||||
dbg!(loc_can_expr.clone(), can_output.tail_call.clone(), defined_symbol.clone());
|
dbg!(
|
||||||
|
loc_can_expr.clone(),
|
||||||
|
can_output.tail_call.clone(),
|
||||||
|
defined_symbol.clone()
|
||||||
|
);
|
||||||
// The closure is self tail recursive iff it tail calls itself (by defined name).
|
// The closure is self tail recursive iff it tail calls itself (by defined name).
|
||||||
let is_recursive = if let Some(ref symbol) = can_output.tail_call {
|
let is_recursive = if let Some(ref symbol) = can_output.tail_call {
|
||||||
if symbol == defined_symbol {
|
if symbol == defined_symbol {
|
||||||
|
@ -1578,7 +1587,6 @@ fn can_defs<'a>(
|
||||||
// Functions' references don't count in defs.
|
// Functions' references don't count in defs.
|
||||||
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
// See 3d5a2560057d7f25813112dfa5309956c0f9e6a9 and its
|
||||||
// parent commit for the bug this fixed!
|
// parent commit for the bug this fixed!
|
||||||
|
|
||||||
if is_closure {
|
if is_closure {
|
||||||
References::new()
|
References::new()
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue