Switch on an option of an untagged variant with an `@as(undefined)` case takes the wrong arm for `Some` of that case

Aperta
#9,184 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
28/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
javascript, ocaml
Ambito
compilers

Direzione di ricerca

Start with rejects_nested_some in compiler/ml/matching.ml, which decides whether a pattern reads the payload with Pval_from_option_not_nest and skips unwrapping the nested Some box. Reproduce with the g(Some(U)) snippet from the issue and inspect the compiled JavaScript for the typeof and === undefined tests. Done when Some(U) reaches the Some(_) arm and prints SU, with the constant and runtime-built cases agreeing.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Found by differential semantic drift analysis from b123b7c3 to c10223e8.

What is broken

@unboxed type t = @as(undefined) U | S(string) | I(int)

let g = (x: option<t>) =>
  switch x {
  | None => "None"
  | Some(S(_)) => "SS"
  | Some(I(_)) => "SI"
  | Some(_) => "SU"
  }

Console.log(g(Some(U)))

Expected SU. At c10223e8 it prints SI; at b123b7c3 it printed None (the construction bug fixed by #9008). A Some(U) built at run time (let h = v => g(Some(v)), h(U)) prints SI at both commits, so the match bug predates the range; #9008 makes constant values reach it too. Matches that name Some(U) explicitly, and tagged variants, are correct.

The compiled g tests x !== undefined, then x === undefined, then typeof x === "string", and otherwise returns "SI", without unwrapping the nested-Some box first: the boxed Some(U) fails the first two tests and lands in the last case.

rejects_nested_some returns true for _ and for untagged payload patterns, so the match reads the payload with Pval_from_option_not_nest, which skips unwrapping.

Possible cause (speculation only)

rejects_nested_some assumes that each pattern rejects the box on its own test, but the untagged dispatch decides the last remaining case by elimination, without a test of its own.

🤖 Generated with Claude Code

Lingua principale
OCaml
Stelle
7.5k
Fork
484
Merge medio
17h 2m
PR unite (30g)
249

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di rescript-lang/rescript

Tutte le issue di rescript-lang/rescript

Issue simili

Altre issue su Compilers

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.