gleam-lang / gleam

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

Type variables preserve record variant inference when inside tuples #3797

Open joshi-monster opened 13 hours ago

joshi-monster commented 13 hours ago

(Gleam nightly)

type Either(a, b) {
  Left(value: a)
  Right(value: b)
}

fn always_second(_first: value, second: value) -> value {
  second
}

pub fn main() {
  let #(right) = always_second(#(Left(5)), #(Right("hello")))
  Left(..right, inner: 10)
}

compiles, except for a "redundant record update" warning. It is important that the values here are wrapped in tuples - the size of the tuple doesn't matter, and a Box record works correctly.

There might be a second bug here about type unification not dropping the inferred variant, but it also works without having 2 different values for the compiler to infer:

fn twice(state: state, fun: fn(state) -> state) -> state {
  fun(fun(state))
}

fn main() {
  twice(#(Left(5)), fn(value) {
    case value.0 {
      Left(_) -> #(Right("hello"))
      Right(_) -> value
    }
  })
}

produces

warning: Unreachable case clause
   ┌─ /home/arkan/Projects/oss/gleam/probe/src/probe.gleam:25:7
   │
25 │       Right(_) -> value
   │       ^^^^^^^^^^^^^^^^^

This case clause cannot be reached as it matches on a variant of a type
which is never present.

I'm sorry Gears ~ :purple_heart:

GearsDatapacks commented 5 hours ago

Type unification does remove the inferred variant, but only if unifying directly with a named type. I suppose we'll have to iterate over tuples and remove any inferred variants inside those too. I'm pretty sure tuples are the only datatype which can contain values with variant information, since anything else requires unification and so the variants would be removed there.

lpil commented 30 minutes ago

Thanks both. You looking into this @GearsDatapacks ?

GearsDatapacks commented 20 minutes ago

Yep. I have a working implementation. I can PR it now

lpil commented 13 minutes ago

You're a machine!