mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
parent
fd4b20de58
commit
92b754f292
2 changed files with 51 additions and 8 deletions
|
@ -1516,8 +1516,10 @@ pub(crate) fn sort_can_defs_new(
|
|||
let def = defs.pop().unwrap();
|
||||
let index = group.first_one().unwrap();
|
||||
|
||||
if def_ordering.direct_references.get_row_col(index, index) {
|
||||
// a definition like `x = x + 1`, which is invalid in roc
|
||||
let bad_recursion_body = if def_ordering.direct_references.get_row_col(index, index)
|
||||
{
|
||||
// a definition like `x = x + 1`, which is invalid in roc.
|
||||
// We need to convert the body of the def to a runtime error.
|
||||
let symbol = def_ordering.get_symbol(index).unwrap();
|
||||
|
||||
let entries = vec![make_cycle_entry(symbol, &def)];
|
||||
|
@ -1525,9 +1527,19 @@ pub(crate) fn sort_can_defs_new(
|
|||
let problem = Problem::RuntimeError(RuntimeError::CircularDef(entries.clone()));
|
||||
env.problem(problem);
|
||||
|
||||
// Declaration::InvalidCycle(entries)
|
||||
todo!("InvalidCycle: {:?}", entries)
|
||||
} else if def_ordering.references.get_row_col(index, index) {
|
||||
Some(Expr::RuntimeError(RuntimeError::CircularDef(entries)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let is_illegally_self_recursive = bad_recursion_body.is_some();
|
||||
let set_opt_invalid_recursion_body = |e: &mut Expr| match bad_recursion_body {
|
||||
Some(err) => *e = err,
|
||||
None => {}
|
||||
};
|
||||
|
||||
if def_ordering.references.get_row_col(index, index) && !is_illegally_self_recursive
|
||||
{
|
||||
// this function calls itself, and must be typechecked as a recursive def
|
||||
match def.loc_pattern.value {
|
||||
Pattern::Identifier(symbol) => match def.loc_expr.value {
|
||||
|
@ -1540,7 +1552,7 @@ pub(crate) fn sort_can_defs_new(
|
|||
None,
|
||||
);
|
||||
}
|
||||
_ => todo!(),
|
||||
e => todo!("{:?}", e),
|
||||
},
|
||||
Pattern::AbilityMemberSpecialization {
|
||||
ident: symbol,
|
||||
|
@ -1562,7 +1574,9 @@ pub(crate) fn sort_can_defs_new(
|
|||
} else {
|
||||
match def.loc_pattern.value {
|
||||
Pattern::Identifier(symbol) => match def.loc_expr.value {
|
||||
Closure(closure_data) => {
|
||||
Closure(mut closure_data) => {
|
||||
set_opt_invalid_recursion_body(&mut closure_data.loc_body.value);
|
||||
|
||||
declarations.push_function_def(
|
||||
Loc::at(def.loc_pattern.region, symbol),
|
||||
Loc::at(def.loc_expr.region, closure_data),
|
||||
|
@ -1572,6 +1586,9 @@ pub(crate) fn sort_can_defs_new(
|
|||
);
|
||||
}
|
||||
_ => {
|
||||
let mut def = def;
|
||||
set_opt_invalid_recursion_body(&mut def.loc_expr.value);
|
||||
|
||||
declarations.push_value_def(
|
||||
Loc::at(def.loc_pattern.region, symbol),
|
||||
def.loc_expr,
|
||||
|
@ -1585,7 +1602,9 @@ pub(crate) fn sort_can_defs_new(
|
|||
ident: symbol,
|
||||
specializes,
|
||||
} => match def.loc_expr.value {
|
||||
Closure(closure_data) => {
|
||||
Closure(mut closure_data) => {
|
||||
set_opt_invalid_recursion_body(&mut closure_data.loc_body.value);
|
||||
|
||||
declarations.push_function_def(
|
||||
Loc::at(def.loc_pattern.region, symbol),
|
||||
Loc::at(def.loc_expr.region, closure_data),
|
||||
|
@ -1595,6 +1614,9 @@ pub(crate) fn sort_can_defs_new(
|
|||
);
|
||||
}
|
||||
_ => {
|
||||
let mut def = def;
|
||||
set_opt_invalid_recursion_body(&mut def.loc_expr.value);
|
||||
|
||||
declarations.push_value_def(
|
||||
Loc::at(def.loc_pattern.region, symbol),
|
||||
def.loc_expr,
|
||||
|
@ -1605,6 +1627,9 @@ pub(crate) fn sort_can_defs_new(
|
|||
}
|
||||
},
|
||||
_ => {
|
||||
let mut def = def;
|
||||
set_opt_invalid_recursion_body(&mut def.loc_expr.value);
|
||||
|
||||
declarations.push_destructure_def(
|
||||
def.loc_pattern,
|
||||
def.loc_expr,
|
||||
|
|
|
@ -10767,4 +10767,22 @@ All branches in an `if` must have the same type!
|
|||
@r###"
|
||||
"###
|
||||
);
|
||||
|
||||
test_report!(
|
||||
invalid_toplevel_cycle,
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" imports [] provides [main] to "./platform"
|
||||
|
||||
main =
|
||||
if Bool.true then \{} -> {} else main
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
── CIRCULAR DEFINITION ─────────────────────────────────── /code/proj/Main.roc ─
|
||||
|
||||
The `main` value is defined directly in terms of itself, causing an
|
||||
infinite loop.
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue