diff --git a/.gitignore b/.gitignore index ce082b3ee72..47b712c3491 100644 --- a/.gitignore +++ b/.gitignore @@ -139,6 +139,9 @@ positive.exe /src/FSharp.DependencyManager.Nuget/StandardError.txt /src/FSharp.DependencyManager.Nuget/StandardOutput.txt +# Test result files +tests/**/TestResults/*.trx + # Standard output/error files in root directory StandardOutput.txt StandardError.txt diff --git a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md index 8276598fab9..ef1496507f3 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/10.0.100.md @@ -4,6 +4,7 @@ ### Fixed +* Fix SignatureHash to include constant values in hash computation ([Issue #18758](https://github.com/dotnet/fsharp/issues/18758)) * Fix parsing errors using anonymous records and units of measures ([PR #18543](https://github.com/dotnet/fsharp/pull/18543)) * Fix parsing errors using anonymous records and code quotations ([PR #18603](https://github.com/dotnet/fsharp/pull/18603)) * Better error message for attribute targets. ([PR #18641](https://github.com/dotnet/fsharp/pull/18641)) diff --git a/src/Compiler/Utilities/TypeHashing.fs b/src/Compiler/Utilities/TypeHashing.fs index 7907c2148dc..c085bc84ff9 100644 --- a/src/Compiler/Utilities/TypeHashing.fs +++ b/src/Compiler/Utilities/TypeHashing.fs @@ -302,6 +302,28 @@ module HashTastMemberOrVals = combinedHash + /// Hash a constant value with exhaustive pattern matching over all Const cases + let private hashConst (constVal: Const) : Hash = + match constVal with + | Const.Bool b -> hash b + | Const.SByte x -> hash x + | Const.Byte x -> hash x + | Const.Int16 x -> hash x + | Const.UInt16 x -> hash x + | Const.Int32 x -> hash x + | Const.UInt32 x -> hash x + | Const.Int64 x -> hash x + | Const.UInt64 x -> hash x + | Const.IntPtr x -> hash x + | Const.UIntPtr x -> hash x + | Const.Single x -> hash x + | Const.Double x -> hash x + | Const.Char x -> hash x + | Const.String x -> hashText x + | Const.Decimal x -> hash x + | Const.Unit -> 0 + | Const.Zero -> 0 + let private hashNonMemberVal (g: TcGlobals, observer) (tps, v: Val, tau, cxs) = if HashAccessibility.isHiddenToObserver v.Accessibility observer then 0 @@ -315,7 +337,13 @@ module HashTastMemberOrVals = let attribsHash = hashAttributeList v.Attribs let combinedHash = nameHash @@ typarHash @@ typeHash @@ flagsHash @@ attribsHash - combinedHash + + // Include literal constant value in hash for deterministic builds + match v.LiteralValue with + | Some constVal -> + let constHash = hashConst constVal + combinedHash @@ constHash + | None -> combinedHash let hashValOrMemberNoInst (g, obs) (vref: ValRef) = match vref.MemberInfo with diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs index c29c0ecb8a5..ad43e5b7bf0 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs @@ -333,3 +333,21 @@ let inline myFunc x y = x - y""" Assert.Equal(mvid1,mvid2) else Assert.NotEqual(mvid1,mvid2) + + [] + let ``Reference assemblies MVID must change when literal constant value changes`` () = + let codeWithLiteral42 = """ +module TestModule +[] +let X = 42 +""" + + let codeWithLiteral43 = """ +module TestModule +[] +let X = 43 +""" + + let mvid1, mvid2 = calculateRefAssMvids codeWithLiteral42 codeWithLiteral43 + // Different literal values should produce different MVIDs + Assert.NotEqual(mvid1, mvid2)