Fable
Fable copied to clipboard
[Python] Custom hash functions are never called on Record Types.
Description
Custom hash functions are never called on Record Types.
Repro code
test.fsx
[<CustomEquality>]
[<NoComparison>]
type MyRecord =
{Name : string; Age: int }
override this.Equals(that) =
this.GetHashCode() = that.GetHashCode()
/// Hash should just return age of person
override this.GetHashCode() =
this.Age
let p1 = {Name = "John"; Age = 30}
// Should return 30, but returns -4426817161268664163
printfn "Hash1: %A" (p1.GetHashCode())
test.cmd
dotnet fable . --lang python
python test.py
Explanation
In the transpiled code, the class MyRecord
now implements a __hash__
method. But the method call is transpiled to safe_hash
, which first checks for the existence of an GetHashCode
method. This is always true for Record Types, so the custom __hash__
methdo is never called.
Related information
-
dotnet fable --version
: 4.13.0 -
dotnet tool list/update/install
: 4.13.0 - Windows11
Workaround Code
#if FABLE_COMPILER_PYTHON
[<Emit("hasattr($0,\"__hash__\")")>]
let pyHasCustomHash (obj) : bool = nativeOnly
[<Emit("$0.__hash__()")>]
let pyCustomHash (obj) : int = nativeOnly
#endif
let hash obj =
#if FABLE_COMPILER_PYTHON
if pyHasCustomHash obj then
pyCustomHash obj
else
obj.GetHashCode()
#else
obj.GetHashCode()
#endif
@freymaurer