From 3f1e11f920f065da8eb8da55b5b87e04415b33ef Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Tue, 9 Aug 2022 16:07:59 -0700 Subject: [PATCH] Recursive vars in occurs check can happen anywhere in the chain --- crates/compiler/solve/src/solve.rs | 42 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/crates/compiler/solve/src/solve.rs b/crates/compiler/solve/src/solve.rs index 6fb947d778..72b09e50e6 100644 --- a/crates/compiler/solve/src/solve.rs +++ b/crates/compiler/solve/src/solve.rs @@ -2876,28 +2876,34 @@ fn check_for_infinite_type( ) { let var = loc_var.value; - while let Err((recursive, _chain)) = subs.occurs(var) { - // try to make a union recursive, see if that helps - match subs.get_content_without_compacting(recursive) { - &Content::Structure(FlatType::TagUnion(tags, ext_var)) => { - subs.mark_tag_union_recursive(recursive, tags, ext_var); - } - &Content::LambdaSet(subs::LambdaSet { - solved, - recursion_var: _, - unspecialized, - ambient_function: ambient_function_var, - }) => { - subs.mark_lambda_set_recursive( - recursive, + 'next_occurs_check: while let Err((_, chain)) = subs.occurs(var) { + // walk the chain till we find a tag union or lambda set, starting from the variable that + // occurred recursively, which is always at the end of the chain. + for &var in chain.iter().rev() { + match subs.get_content_without_compacting(var) { + &Content::Structure(FlatType::TagUnion(tags, ext_var)) => { + subs.mark_tag_union_recursive(var, tags, ext_var); + continue 'next_occurs_check; + } + &Content::LambdaSet(subs::LambdaSet { solved, + recursion_var: _, unspecialized, - ambient_function_var, - ); + ambient_function: ambient_function_var, + }) => { + subs.mark_lambda_set_recursive( + var, + solved, + unspecialized, + ambient_function_var, + ); + continue 'next_occurs_check; + } + _ => { /* fall through */ } } - - _other => circular_error(subs, problems, symbol, &loc_var), } + + circular_error(subs, problems, symbol, &loc_var); } }