Copy-and-update of a let mutable struct record loses the unchanged fields

Đang mở
#5,253 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

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

Từ ngày 5/11/2026.

  • #5270 của @MangelMaxime — đang mở

Đánh giá

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

Hướng nghiên cứu

Start from the copy-and-update ({ mark with S = ... }) case in the compiler, where a let mutable local of a [<Struct>] record is wrapped in an FSharpRef and the unchanged fields are read from the wrapper. Reproduce with the Mark example in the issue and compare the emitted JavaScript with the non-struct output, which reads mark.T directly. Done when the struct case emits mark.T and the sample prints 1 c; 2 c.

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

Mô tả

When the source of a copy-and-update expression is a let mutable local of a [<Struct>] record type, the generated code wraps the local in an FSharpRef and reads the unchanged fields from the ref object, which doesn’t have them. Every field not named in the with comes out undefined. A reference record, or an immutable struct local, compiles correctly.

[<Struct>]
type Mark = { T: float; S: string }

let copies () =
    let mutable mark = { T = 1.0; S = "a" }
    let out = ResizeArray()

    for i in 1..2 do
        mark <- { T = float i; S = "b" }
        out.Add { mark with S = "c" }

    out |> Seq.map (fun m -> sprintf "%g %s" m.T m.S) |> String.concat "; "

printfn "%s" (copies ())

Under .NET 10, output is as expected 1 c; 2 c. For Fable 5.26.0, output is undefined c; undefined c. When [<Struct>] is removed from Mark, the correct result 1 c; 2 c will be emitted.

The emitted JavaScript reads the unchanged field from an FSharpRef wrapped around the local not from the local itself.

mark = (new Mark(i, "b"));
void (out.push(new Mark((new FSharpRef(() => mark, (v) => {
    mark = v; })).T, "c")));

FSharpRef exposes the value as .contents and has no T accessor, hence the field is undefined. Without [<Struct>] the same line is new Mark(mark.T, "c").

Ngôn ngữ chính
F#
Star
3.2k
Fork
335
Merge trung bình
19 giờ 39 phút
Pull request đã merge (30 ngày)
158

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.

  • Không có Dockerfile hay tệp Docker Compose
  • Không có mẫu pull request
  • Không có hướng dẫn đóng góp

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 fable-compiler/Fable

Tất cả issue của fable-compiler/Fable

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.