diff --git a/src/Fable.Cli/CHANGELOG.md b/src/Fable.Cli/CHANGELOG.md index e0eccefc39..48f2c0c369 100644 --- a/src/Fable.Cli/CHANGELOG.md +++ b/src/Fable.Cli/CHANGELOG.md @@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed char to string type regression with binary operator (by @dbrattli) * Fix `DateTime(..., DateTimeKind.Local).ToString("O")` (by @MangelMaxime) * Fix calling `value.ToString(CultureInfo.InvariantCulture)` (by @MangelMaxime) +* Fix #3605: Fix record equality comparison to works with optional fields (by @MangelMaxime & @dbrattli) ## 4.5.0 - 2023-11-07 diff --git a/src/fable-library-py/fable_library/types.py b/src/fable-library-py/fable_library/types.py index 16c7c23ddf..18bff057dd 100644 --- a/src/fable-library-py/fable_library/types.py +++ b/src/fable-library-py/fable_library/types.py @@ -118,19 +118,32 @@ def record_compare_to(self: Record, other: Record) -> int: if self is other: return 0 - elif hasattr(self, "__dict__") and self.__dict__: - for name in self.__dict__.keys(): - if self.__dict__[name] < other.__dict__.get(name): + def compare_values(self_value: Any, other_value: Any) -> int: + match (self_value, other_value): + case (None, None): + return 0 + case (None, _): + return -1 + case (_, None): + return 1 + case (self_value, other_value) if self_value < other_value: return -1 - elif self.__dict__[name] > other.__dict__.get(name): + case (self_value, other_value) if self_value > other_value: return 1 + case _: + return 0 + + if hasattr(self, "__dict__") and self.__dict__: + for name in self.__dict__.keys(): + result = compare_values(self.__dict__[name], other.__dict__[name]) + if result != 0: + return result elif hasattr(self, "__slots__") and self.__slots__: for name in self.__slots__: - if getattr(self, name) < getattr(other, name): - return -1 - elif getattr(self, name) > getattr(other, name): - return 1 + result = compare_values(getattr(self, name), getattr(other, name)) + if result != 0: + return result return 0 diff --git a/tests/Python/TestRecordType.fs b/tests/Python/TestRecordType.fs index 493dd44bb9..a2aacfe50e 100644 --- a/tests/Python/TestRecordType.fs +++ b/tests/Python/TestRecordType.fs @@ -42,6 +42,9 @@ type Time = type CarInterior = { Seats: int } type Car = { Interior: CarInterior } +type RecordA = + { OptionalField : string option } + [] let ``test Anonymous records work`` () = let r = makeAnonRec() @@ -144,3 +147,14 @@ let ``test Nested record field copy and update works for anonymous records`` = let car2 = {| car with Interior.Seats = 5 |} equal 5 car2.Interior.Seats + +[] +let ``test Record equality when it has optional field`` = + let a = { OptionalField = None } + let b = { OptionalField = None } + let c = { OptionalField = Some "test" } + + equal a b + equal true (a = b) + equal false (a = c) + equal false (c = b)