diff --git a/ast/src/constrain.rs b/ast/src/constrain.rs index bd00bbbda5..547b732c0e 100644 --- a/ast/src/constrain.rs +++ b/ast/src/constrain.rs @@ -683,19 +683,24 @@ pub fn constrain_expr<'a>( // when_branch.patterns.iter(env.pool).map(|v| &v.region), // ); + let patten_expected = |sub_pattern| { + PExpected::ForReason( + PReason::WhenMatch { + index: HumanIndex::zero_based(index), + sub_pattern, + }, + cond_type.shallow_clone(), + pattern_region, + ) + }; + let branch_con = constrain_when_branch( arena, env, // TODO: when_branch.value.region, region, when_branch, - PExpected::ForReason( - PReason::WhenMatch { - index: HumanIndex::zero_based(index), - }, - cond_type.shallow_clone(), - pattern_region, - ), + patten_expected, Expected::FromAnnotation( name.clone(), *arity, @@ -726,18 +731,23 @@ pub fn constrain_expr<'a>( // let pattern_region = // Region::across_all(when_branch.patterns.iter().map(|v| &v.region)); + let patten_expected = |sub_pattern| { + PExpected::ForReason( + PReason::WhenMatch { + index: HumanIndex::zero_based(index), + sub_pattern, + }, + cond_type.shallow_clone(), + pattern_region, + ) + }; + let branch_con = constrain_when_branch( arena, env, region, when_branch, - PExpected::ForReason( - PReason::WhenMatch { - index: HumanIndex::zero_based(index), - }, - cond_type.shallow_clone(), - pattern_region, - ), + patten_expected, Expected::ForReason( Reason::WhenBranch { index: HumanIndex::zero_based(index), @@ -1296,7 +1306,7 @@ fn constrain_when_branch<'a>( env: &mut Env, region: Region, when_branch: &WhenBranch, - pattern_expected: PExpected, + pattern_expected: impl Fn(HumanIndex) -> PExpected, expr_expected: Expected, ) -> Constraint<'a> { let when_expr = env.pool.get(when_branch.body); @@ -1311,16 +1321,18 @@ fn constrain_when_branch<'a>( // TODO investigate for error messages, is it better to unify all branches with a variable, // then unify that variable with the expectation? - for pattern_id in when_branch.patterns.iter_node_ids() { + for (sub_pattern, pattern_id) in when_branch.patterns.iter_node_ids().enumerate() { let pattern = env.pool.get(pattern_id); + let pattern_expected = pattern_expected(HumanIndex::zero_based(sub_pattern)); + constrain_pattern( arena, env, pattern, // loc_pattern.region, region, - pattern_expected.shallow_clone(), + pattern_expected, &mut state, true, ); diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index f78ff9ce59..47addd8f51 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -1188,34 +1188,26 @@ fn solve( use {Content::*, FlatType::*}; let mut desc = subs.get(var); - match desc.content { - Structure(TagUnion(tags, ext)) => { - match subs.get_content_without_compacting(ext) { - Structure(FlatType::EmptyTagUnion) => { - let new_ext = subs.fresh_unnamed_flex_var(); - subs.set_rank(new_ext, desc.rank); - let new_union = Structure(TagUnion(tags, new_ext)); - desc.content = new_union; - subs.set(var, desc); - } - _ => {} - } + if let Structure(TagUnion(tags, ext)) = desc.content { + if let Structure(EmptyTagUnion) = subs.get_content_without_compacting(ext) { + let new_ext = subs.fresh_unnamed_flex_var(); + subs.set_rank(new_ext, desc.rank); + let new_union = Structure(TagUnion(tags, new_ext)); + desc.content = new_union; + subs.set(var, desc); + } - // Also open up all nested tag unions. - let all_vars = tags.variables().into_iter(); - stack.extend( - all_vars.flat_map(|slice| subs[slice]).map(|var| subs[var]), - ); - } - _ => { - // Today, an "open" constraint doesn't affect any types - // other than tag unions. Recursive tag unions are constructed - // at a later time (during occurs checks after tag unions are - // resolved), so that's not handled here either. - // NB: Handle record types here if we add presence constraints - // to their type inference as well. - } + // Also open up all nested tag unions. + let all_vars = tags.variables().into_iter(); + stack.extend(all_vars.flat_map(|slice| subs[slice]).map(|var| subs[var])); } + + // Today, an "open" constraint doesn't affect any types + // other than tag unions. Recursive tag unions are constructed + // at a later time (during occurs checks after tag unions are + // resolved), so that's not handled here either. + // NB: Handle record types here if we add presence constraints + // to their type inference as well. } state