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

Đang mở
#9,184 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@cknitt đang làm issue này rồi.

Từ ngày 3/11/2026.

  • #9206 của @cknitt — đang mở

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
28/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
javascript, ocaml
Lĩnh vực
compilers

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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

Ngôn ngữ chính
OCaml
Star
7.5k
Fork
484
Merge trung bình
17 giờ 9 phút
Pull request đã merge (30 ngày)
264

Chuẩn bị môi trường

Mở trong Codespaces

Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của rescript-lang/rescript

Tất cả issue của rescript-lang/rescript

Issue tương tự

Thêm issue về Compilers

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.