gleam-lang / gleam

⭐️ A friendly language for building type-safe, scalable systems!
https://gleam.run
Apache License 2.0
17.26k stars 715 forks source link

Invalid Erlang code generated when comparing type containing a function in case guard #3069

Open richard-viney opened 4 months ago

richard-viney commented 4 months ago

The following Gleam code compiles to invalid Erlang code. The problem is due to the guard expression and the presence of a function in the type being compared.

The comparison works as expected if the equality check is done directly, i.e. foo == hello_greeting_wrapper.

Note that everything works correctly when targeting JavaScript, this is an Erlang-specific issue.

type GreetingWrapper {
  GreetingWrapper(greeting_fn: fn() -> String)
}

fn hello_greeting() {
  "Hello!"
}

const hello_greeting_wrapper = GreetingWrapper(hello_greeting)

fn is_hello(foo: GreetingWrapper) {
  case foo {
    f if f == hello_greeting_wrapper -> True
    _ -> False
  }
}

pub fn main() {
  is_hello(hello_greeting_wrapper)
}

The output from gleam run is:

Compiling bug_repro
/bug_repro/build/dev/erlang/bug_repro/_gleam_artefacts/bug_repro.erl:16:41: illegal guard expression
%   16|         F when F =:= {greeting_wrapper, fun hello_greeting/0} ->
%     |                                         ^

error: Shell command failure

There was a problem when running the shell command `escript`.

Tested on Gleam v1.1.0 on macOS.

lpil commented 4 months ago

Oh dear. It'll be a bit tricky to fix this one. I think we may need to lift the function constant out of the case expression.