rescript-lang / rescript

ReScript is a robustly typed language that compiles to efficient and human-readable JavaScript.
https://rescript-lang.org
Other
6.77k stars 453 forks source link

Bug in handling the JSON unboxed type when switching on it #6789

Closed jfrolich closed 6 months ago

jfrolich commented 6 months ago

Repro here

zth commented 6 months ago

cc @cristianoc

cristianoc commented 6 months ago

Smaller self contained repro:


type obj = {name:string}

@unboxed
type t =
  | Boolean(bool)
  | Object(obj)
  | Array(array<int>)

switch Object({name: "hello"}) {
| Object(v) => Console.log(v)
| Array(v) => Console.log(v)
| _ => Console.log("Not an object or array1")
}

produces:

var v = {
  name: "hello"
};

if (Array.isArray(v)) {
  console.log(v);
} else {
  switch (typeof v) {
    case "boolean" :
        console.log("Not an object or array1");
        break;
    case "object" :

  }
}

It seems the code for case "object" is not emitted.

cristianoc commented 6 months ago

The issue happens when 2 cases, here Object and Array, have identical body (here Console.log(v)). The switch-generation code, which was not designed with untagged unions in mind, merges the two cases into one (and makes one of the two empty).

However, for Object and Array, what's generated is not a straight switch, but a mix of if-then-else and switch. This means that the Object and Array cases are apart in the generated code, and merging them (making one empty) is wrong.