From 9b2a267b2cfbf2a3ecadce8c9921b26476c8183d Mon Sep 17 00:00:00 2001 From: ncave <777696+ncave@users.noreply.github.com> Date: Fri, 9 Oct 2026 14:10:54 -0700 Subject: [PATCH] fix(rust): Fix temporary struct locals type --- src/Fable.Build/Quicktest/Rust.fs | 7 ++++- src/Fable.Transforms/Rust/Fable2Rust.fs | 34 +++++++++++++++++-------- tests/Rust/tests/src/RecordTests.fs | 12 +++++++-- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/Fable.Build/Quicktest/Rust.fs b/src/Fable.Build/Quicktest/Rust.fs index 91fe780de6..d08715b24a 100644 --- a/src/Fable.Build/Quicktest/Rust.fs +++ b/src/Fable.Build/Quicktest/Rust.fs @@ -2,13 +2,18 @@ module Build.Quicktest.Rust open Build.FableLibrary open Build.Quicktest.Core +open SimpleExec let handle (args: string list) = + let projectDir = "src/quicktest-rust" + + Command.Run("cargo", "clean", workingDirectory = projectDir) + genericQuicktest { Language = "rust" FableLibBuilder = BuildFableLibraryRust() - ProjectDir = "src/quicktest-rust" + ProjectDir = projectDir Extension = ".rs" RunMode = RunScript } diff --git a/src/Fable.Transforms/Rust/Fable2Rust.fs b/src/Fable.Transforms/Rust/Fable2Rust.fs index 229b582dcf..a86bfda20d 100644 --- a/src/Fable.Transforms/Rust/Fable2Rust.fs +++ b/src/Fable.Transforms/Rust/Fable2Rust.fs @@ -1469,6 +1469,14 @@ module Util = // transformIdent com ctx None id // | _ -> com.TransformExpr(ctx, expr) + let isTempLocal (ident: Fable.Ident) = + ident.IsCompilerGenerated + && (ident.Name = "copyOfStruct" || ident.Name = "inputRecord") + + // let isMutableOrByRef (ident: Fable.Ident) = + // (ident.IsMutable || isByRefType ident) + // && not (isTempLocal ident) + let transformIdentGet com ctx r (ident: Fable.Ident) = let expr = transformIdent com ctx r ident @@ -1487,16 +1495,22 @@ module Util = mutableSet expr value let transformIdentType com ctx isCaptured (ident: Fable.Ident) = - let ty = transformType com ctx ident.Type - - if isByRefType com ident.Type then - ty // already wrapped - elif ident.IsMutable && isCaptured then - ty |> makeMutTy com ctx |> makeLrcPtrTy com ctx - elif ident.IsMutable then - ty |> makeMutTy com ctx - else - ty + // let typ = Replacements.Util.getIdentValueType com ident ident.Type + match ident.Type with + | Replacements.Util.IsByRefType com typ when isTempLocal ident -> + // transform temporary local byref type to a reference type + transformType com ctx typ |> mkRefTy None + | _ -> + let ty = transformType com ctx ident.Type + + if isByRefType com ident.Type then + ty // already wrapped + elif ident.IsMutable && isCaptured then + ty |> makeMutTy com ctx |> makeLrcPtrTy com ctx + elif ident.IsMutable then + ty |> makeMutTy com ctx + else + ty let getField r (expr: Rust.Expr) (fieldName: string) = mkFieldExpr expr (fieldName |> sanitizeMember) // ?loc=r) diff --git a/tests/Rust/tests/src/RecordTests.fs b/tests/Rust/tests/src/RecordTests.fs index ce0d9000ab..4913a83613 100644 --- a/tests/Rust/tests/src/RecordTests.fs +++ b/tests/Rust/tests/src/RecordTests.fs @@ -126,14 +126,22 @@ let processStructByValue (s: StructRecord) = [] let ``Struct record works`` () = - let r1 = { i=1; s="hello" } - let r2 = { i=1; s="world" } + let r1 = { i = 1; s = "hello" } + let r2 = { i = 1; s = "world" } let (sres1, ires1) = r1 |> processStructByValue let (sres2, ires2) = r1 |> processStructByValue let (sres3, ires3) = r2 |> processStructByValue //cannot actually test this, but since this is the only reference, the output should not .clone() ires2 |> equal 2 sres3.s |> equal "world" +[] +let ``Struct record temp locals work`` () = + let r1 = { i = 1; s = "hello" } + let r2 = { i = 2; s = "world" } + let r3 = { r1 with i = r2.i ; s = r2.s } + r3.i |> equal 2 + r3.s |> equal "world" + type MutableRecord = { mutable MutValue: int }