diff --git a/crates/compiler/types/src/subs.rs b/crates/compiler/types/src/subs.rs index d634f2c600..b3c2eeff9b 100644 --- a/crates/compiler/types/src/subs.rs +++ b/crates/compiler/types/src/subs.rs @@ -5444,12 +5444,16 @@ fn is_inhabited(subs: &Subs, var: Variable) -> bool { } } FlatType::TagUnion(tags, ext) | FlatType::RecursiveTagUnion(_, tags, ext) => { - let mut has_no_tags = true; + let mut is_uninhabited = true; + // If any tag is inhabited, the union is inhabited! for (_tag, vars) in tags.unsorted_iterator(subs, *ext) { - has_no_tags = false; - stack.extend(vars); + // Sadly we must recurse here... + let this_tag_is_inhabited = vars.iter().all(|v| is_inhabited(subs, *v)); + if this_tag_is_inhabited { + is_uninhabited = false; + } } - if has_no_tags { + if is_uninhabited { return false; } } diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 677830eabc..ee0fb316f4 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -10545,10 +10545,60 @@ All branches in an `if` must have the same type! Ok {} -> "" "# ), + // no problem! @r###" "### ); + test_report!( + uninhabited_type_is_trivially_exhaustive_nested, + indoc!( + r#" + x : Result (Result [A, B] []) [] + + when x is + Ok (Ok A) -> "" + Ok (Ok B) -> "" + "# + ), + // no problem! + @r###" + "### + ); + + test_report!( + #[ignore = "TODO https://github.com/roc-lang/roc/issues/4068"] + branch_patterns_missing_nested_case, + indoc!( + r#" + x : Result (Result [A, B] {}) {} + + when x is + Ok (Ok A) -> "" + Err _ -> "" + "# + ), + @r###" + TODO + "### + ); + + test_report!( + #[ignore = "TODO https://github.com/roc-lang/roc/issues/4068"] + branch_patterns_missing_nested_case_with_trivially_exhausted_variant, + indoc!( + r#" + x : Result (Result [A, B] []) [] + + when x is + Ok (Ok A) -> "" + "# + ), + @r###" + TODO + "### + ); + test_report!( uninhabited_err_branch_is_redundant_when_err_is_matched, indoc!( @@ -10574,4 +10624,44 @@ All branches in an `if` must have the same type! one should be removed. "### ); + + test_report!( + uninhabited_err_branch_is_redundant_when_err_is_matched_nested, + indoc!( + r#" + x : Result (Result {} []) [] + + when x is + Ok (Ok {}) -> "" + Ok (Err _) -> "" + Err _ -> "" + "# + ), + @r###" + ── REDUNDANT PATTERN ───────────────────────────────────── /code/proj/Main.roc ─ + + The 2nd pattern is redundant: + + 6│ when x is + 7│ Ok (Ok {}) -> "" + 8│> Ok (Err _) -> "" + 9│ Err _ -> "" + + Any value of this shape will be handled by a previous pattern, so this + one should be removed. + + ── REDUNDANT PATTERN ───────────────────────────────────── /code/proj/Main.roc ─ + + The 2nd pattern is redundant: + + 6│ when x is + 7│ Ok (Ok {}) -> "" + 8│ Ok (Err _) -> "" + 9│ Err _ -> "" + ^^^^^ + + Any value of this shape will be handled by a previous pattern, so this + one should be removed. + "### + ); }