mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Recursive functions must be shared
This commit is contained in:
parent
dbe615b4c5
commit
50f8bf1856
3 changed files with 58 additions and 13 deletions
|
@ -459,7 +459,9 @@ pub fn constrain_expr(
|
||||||
expected,
|
expected,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Closure(fn_var, _symbol, _recursion, args, boxed) => {
|
Closure(fn_var, _symbol, recursion, args, boxed) => {
|
||||||
|
use crate::can::expr::Recursive;
|
||||||
|
|
||||||
let (loc_body_expr, ret_var) = &**boxed;
|
let (loc_body_expr, ret_var) = &**boxed;
|
||||||
let mut state = PatternState {
|
let mut state = PatternState {
|
||||||
headers: SendMap::default(),
|
headers: SendMap::default(),
|
||||||
|
@ -485,11 +487,18 @@ pub fn constrain_expr(
|
||||||
vars.push(*pattern_var);
|
vars.push(*pattern_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_uniq_var = var_store.fresh();
|
let fn_uniq_type;
|
||||||
vars.push(fn_uniq_var);
|
if let Recursive::NotRecursive = recursion {
|
||||||
|
let fn_uniq_var = var_store.fresh();
|
||||||
|
vars.push(fn_uniq_var);
|
||||||
|
fn_uniq_type = Bool::Variable(fn_uniq_var);
|
||||||
|
} else {
|
||||||
|
// recursive definitions MUST be Shared
|
||||||
|
fn_uniq_type = Bool::Zero
|
||||||
|
}
|
||||||
|
|
||||||
let fn_type = constrain::attr_type(
|
let fn_type = constrain::attr_type(
|
||||||
Bool::Variable(fn_uniq_var),
|
fn_uniq_type,
|
||||||
Type::Function(pattern_types, Box::new(ret_type.clone())),
|
Type::Function(pattern_types, Box::new(ret_type.clone())),
|
||||||
);
|
);
|
||||||
let body_type = Expected::NoExpectation(ret_type);
|
let body_type = Expected::NoExpectation(ret_type);
|
||||||
|
|
|
@ -1246,12 +1246,12 @@ mod test_infer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO add more realistic function when able
|
||||||
#[test]
|
#[test]
|
||||||
fn integer_sum() {
|
fn integer_sum() {
|
||||||
with_larger_debug_stack(|| {
|
infer_eq_without_problem(
|
||||||
infer_eq_without_problem(
|
indoc!(
|
||||||
indoc!(
|
r#"
|
||||||
r#"
|
|
||||||
f = \n ->
|
f = \n ->
|
||||||
when n is
|
when n is
|
||||||
0 -> 0
|
0 -> 0
|
||||||
|
@ -1259,10 +1259,9 @@ mod test_infer {
|
||||||
|
|
||||||
f
|
f
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Int -> Int",
|
"Int -> Int",
|
||||||
);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// currently fails, the rank of Cons's ext_var is 3, where 2 is the highest pool
|
// currently fails, the rank of Cons's ext_var is 3, where 2 is the highest pool
|
||||||
|
|
|
@ -1231,4 +1231,41 @@ mod test_infer_uniq {
|
||||||
"Attr.Attr * Int",
|
"Attr.Attr * Int",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO add more realistic recursive example when able
|
||||||
|
#[test]
|
||||||
|
fn factorial_is_shared() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
factorial = \n ->
|
||||||
|
when n is
|
||||||
|
0 -> 1
|
||||||
|
1 -> 1
|
||||||
|
m -> factorial m
|
||||||
|
|
||||||
|
factorial
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Attr.Attr Attr.Shared (Attr.Attr * Int -> Attr.Attr * Int)",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO add more realistic recursive example when able
|
||||||
|
#[test]
|
||||||
|
fn factorial_without_recursive_case_can_be_unique() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
factorial = \n ->
|
||||||
|
when n is
|
||||||
|
0 -> 1
|
||||||
|
_ -> 1
|
||||||
|
|
||||||
|
factorial
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Attr.Attr * (Attr.Attr * Int -> Attr.Attr * Int)",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue