From 2c97c840fc454d8272083aaac8ac852dbd5b630a Mon Sep 17 00:00:00 2001 From: Folkert Date: Fri, 31 Dec 2021 14:26:23 +0100 Subject: [PATCH] walk the chain till we find a tag union to make recursive --- compiler/test_gen/src/gen_primitives.rs | 46 +++++++++++++++++++++++++ compiler/unify/src/unify.rs | 13 ++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/compiler/test_gen/src/gen_primitives.rs b/compiler/test_gen/src/gen_primitives.rs index d339961dc5..0381b0dd70 100644 --- a/compiler/test_gen/src/gen_primitives.rs +++ b/compiler/test_gen/src/gen_primitives.rs @@ -3138,3 +3138,49 @@ fn alias_defined_out_of_order() { RocStr ); } + +#[test] +#[cfg(any(feature = "gen-llvm"))] +fn recursively_build_effect() { + assert_evals_to!( + indoc!( + r#" + app "test" provides [ main ] to "./platform" + + greeting = + hi = "Hello" + name = "World" + + "\(hi), \(name)!" + + main = + when nestHelp 4 is + _ -> greeting + + nestHelp : I64 -> XEffect {} + nestHelp = \m -> + when m is + 0 -> + always {} + + _ -> + always {} |> after \_ -> nestHelp (m - 1) + + + XEffect a : [ @XEffect ({} -> a) ] + + always : a -> XEffect a + always = \x -> @XEffect (\{} -> x) + + after : XEffect a, (a -> XEffect b) -> XEffect b + after = \(@XEffect e), toB -> + @XEffect \{} -> + when toB (e {}) is + @XEffect e2 -> + e2 {} + "# + ), + RocStr::from_slice(b"Hello, World!"), + RocStr + ); +} diff --git a/compiler/unify/src/unify.rs b/compiler/unify/src/unify.rs index e9ee4d42db..0a426b4a56 100644 --- a/compiler/unify/src/unify.rs +++ b/compiler/unify/src/unify.rs @@ -833,10 +833,21 @@ enum OtherTags2 { } fn maybe_mark_tag_union_recursive(subs: &mut Subs, tag_union_var: Variable) { - while let Err((recursive, _chain)) = subs.occurs(tag_union_var) { + 'outer: while let Err((recursive, chain)) = subs.occurs(tag_union_var) { let description = subs.get(recursive); if let Content::Structure(FlatType::TagUnion(tags, ext_var)) = description.content { subs.mark_tag_union_recursive(recursive, tags, ext_var); + } else { + // walk the chain till we find a tag union + for v in &chain[..chain.len() - 1] { + let description = subs.get(*v); + if let Content::Structure(FlatType::TagUnion(tags, ext_var)) = description.content { + subs.mark_tag_union_recursive(*v, tags, ext_var); + continue 'outer; + } + } + + panic!("recursive loop does not contain a tag union") } } }