gleam icon indicating copy to clipboard operation
gleam copied to clipboard

Inexhaustive warning message is incorrect for case expressions with multiple subjects

Open lpil opened this issue 7 months ago • 4 comments

warning: Inexhaustive patterns
  ┌─ /src/warning/wrn.gleam:3:3
  │  
3 │ ╭   case x, y {
4 │ │     True, _ -> 1
5 │ │   }
  │ ╰───^

This case expression does not have a pattern for all possible values.
If is run on one of the values without a pattern then it will crash.

The missing patterns are:

    False

The missing pattern should be False, _. The fact there are multiple patterns has been lost.

lpil avatar Nov 27 '23 15:11 lpil

An interesting example:

pub fn main() {
  let x = False
  let y = True
  case x, y {
    True, True -> 1
  }
}

The error is:

warning: Inexhaustive patterns
  ┌─ /src/main.gleam:4:3
  │  
4 │ ╭   case x, y {
5 │ │     True, True -> 1
6 │ │   }
  │ ╰───^

This case expression does not have a pattern for all possible values.
If is run on one of the values without a pattern then it will crash.

The missing patterns are:

    False
    True

In a future version of Gleam this will become a compile error.

michallepicki avatar Dec 09 '23 21:12 michallepicki

Copying my notes from Discord to here:

I think it's possibly a mistake that for a multi-pattern the compiler just inserts multiple columns directly without wrapping them in anything In presence of multi-patterns, the first decision created should be a Switch with one Case (like it is for tuples or patterns for custom types with one constructor), or some new dedicated one that works the same way, and then when traversing the tree to print missing patterns it could be handled similarly to a tuple

The columns seem like an internal thing of the exh checking and because of the recursive nature of the algorithm, it's not easy to detect the outermost one for multi-patterns to special-case it when compiling rows. So I would propose to either

  • insert one column, have dedicated data types for handling multi-patterns
  • insert one column using the same data types as a tuple does, but with some flag designating that it's a multi-pattern so that missing patterns get printed correctly
  • continue inserting multiple columns, but in Compiler::compile don't call the recursive compile_rows directly, but first call some function that will handle the presence of multiple outermost columns to create a Switch decision or equivalent somewhere around here (still some changes to data types will be needed to handle printing of missing multi-patterns) - but also I'm not yet clear on how guards are handled, so maybe this is not an option

michallepicki avatar Feb 07 '24 10:02 michallepicki

Helloo 👋 also related, I think there is a grammartical error in the message: If is run should be: if it is run

quadroli avatar Mar 14 '24 03:03 quadroli

Thank you

lpil avatar Mar 14 '24 11:03 lpil