From 92baf5220bcb21961d89dbb81e193d4f673979b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:17:24 +0000 Subject: [PATCH 1/5] Initial plan From fc9430ce039224218d2e61decb399493870f3e69 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 12:49:42 +0000 Subject: [PATCH 2/5] Fix units-of-measure signature hashing and add test Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- src/Compiler/Utilities/TypeHashing.fs | 21 ++++++++++++++----- .../Signatures/ImpliedSignatureHashTests.fs | 10 +++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Utilities/TypeHashing.fs b/src/Compiler/Utilities/TypeHashing.fs index 8e3752d5d33..f7bcc229c45 100644 --- a/src/Compiler/Utilities/TypeHashing.fs +++ b/src/Compiler/Utilities/TypeHashing.fs @@ -188,13 +188,24 @@ module rec HashTypes = |> pipeToHash memberHash /// Hash a unit of measure expression - let private hashMeasure unt = - let measuresWithExponents = + let private hashMeasure g unt = + let measureVarsWithExponents = ListMeasureVarOccsWithNonZeroExponents unt |> List.sortBy (fun (tp: Typar, _) -> tp.DisplayName) - measuresWithExponents - |> hashListOrderIndependent (fun (typar, exp: Rational) -> hashTyparRef typar @@ hash exp) + let measureConsWithExponents = + ListMeasureConOccsWithNonZeroExponents g false unt + |> List.sortBy (fun (tcref: TyconRef, _) -> tcref.DisplayName) + + let varHash = + measureVarsWithExponents + |> hashListOrderIndependent (fun (typar, exp: Rational) -> hashTyparRef typar @@ hash exp) + + let conHash = + measureConsWithExponents + |> hashListOrderIndependent (fun (tcref, exp: Rational) -> hashTyconRef tcref @@ hash exp) + + varHash @@ conHash /// Hash a type, taking precedence into account to insert brackets where needed let hashTType (g: TcGlobals) ty = @@ -217,7 +228,7 @@ module rec HashTypes = let argTys, retTy = stripFunTy g ty argTys |> hashListOrderMatters (hashTType g) |> pipeToHash (hashTType g retTy) | TType_var(r, _) -> hashTyparRefWithInfo r - | TType_measure unt -> hashMeasure unt + | TType_measure unt -> hashMeasure g unt // Hash a single argument, including its name and type let private hashArgInfo (g: TcGlobals) (ty, argInfo: ArgReprInfo) = diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/ImpliedSignatureHashTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/ImpliedSignatureHashTests.fs index a7ee96305ad..93ffca0d74c 100644 --- a/tests/FSharp.Compiler.ComponentTests/Signatures/ImpliedSignatureHashTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Signatures/ImpliedSignatureHashTests.fs @@ -288,6 +288,16 @@ type BAttribute() = let a ([] c: int) : int = 0 """)>] +[] type kg +[] type m +type MyRecord = { Mass: int }""" +(*AFTER*),"""module MyTest +[] type kg +[] type m +type MyRecord = { Mass: int }""")>] + //TODO add a lot more negative tests - in which cases should hash in fact change [] From 20f86b0f6ff17cf23c33e4256684d1cf58cc99f0 Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Wed, 5 Nov 2025 11:24:05 +0100 Subject: [PATCH 3/5] Apply suggestion from @T-Gro --- src/Compiler/Utilities/TypeHashing.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compiler/Utilities/TypeHashing.fs b/src/Compiler/Utilities/TypeHashing.fs index f7bcc229c45..a0d9922a1b4 100644 --- a/src/Compiler/Utilities/TypeHashing.fs +++ b/src/Compiler/Utilities/TypeHashing.fs @@ -195,7 +195,6 @@ module rec HashTypes = let measureConsWithExponents = ListMeasureConOccsWithNonZeroExponents g false unt - |> List.sortBy (fun (tcref: TyconRef, _) -> tcref.DisplayName) let varHash = measureVarsWithExponents From 15bacad5baf6ddc852aa991941e426b48dd5c8ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 10:37:44 +0000 Subject: [PATCH 4/5] Add release notes for units-of-measure fix Co-authored-by: T-Gro <46543583+T-Gro@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/11.0.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index 219ee92ba9f..c2358744c8f 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -7,6 +7,7 @@ * Fix: warn FS0049 on upper union case label. ([PR #19003](https://github.com/dotnet/fsharp/pull/19003)) * Type relations cache: handle potentially "infinite" types ([PR #19010](https://github.com/dotnet/fsharp/pull/19010)) * Disallow recursive structs with lifted type parameters ([Issue #18993](https://github.com/dotnet/fsharp/issues/18993), [PR #19031](https://github.com/dotnet/fsharp/pull/19031)) +* Fix units-of-measure changes not invalidating incremental builds. ([Issue #19049](https://github.com/dotnet/fsharp/issues/19049)) ### Added From 327b4900db2ffbaf367294d9f4ed7b7c8b201fae Mon Sep 17 00:00:00 2001 From: GH Actions Date: Wed, 5 Nov 2025 14:52:51 +0000 Subject: [PATCH 5/5] Apply patch from /run fantomas --- src/Compiler/Utilities/TypeHashing.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compiler/Utilities/TypeHashing.fs b/src/Compiler/Utilities/TypeHashing.fs index a0d9922a1b4..e026411ed71 100644 --- a/src/Compiler/Utilities/TypeHashing.fs +++ b/src/Compiler/Utilities/TypeHashing.fs @@ -193,8 +193,7 @@ module rec HashTypes = ListMeasureVarOccsWithNonZeroExponents unt |> List.sortBy (fun (tp: Typar, _) -> tp.DisplayName) - let measureConsWithExponents = - ListMeasureConOccsWithNonZeroExponents g false unt + let measureConsWithExponents = ListMeasureConOccsWithNonZeroExponents g false unt let varHash = measureVarsWithExponents