Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: LanguagePrimitives.PhysicalEquality not transpiled to check reference equality #3998

Open
kMutagene opened this issue Jan 3, 2025 · 1 comment

Comments

@kMutagene
Copy link

kMutagene commented Jan 3, 2025

Description

LanguagePrimitives.PhysicalEquality in F# returns true when two object references refer to the same underlying object.

There are equivalents to this, namely === in JS and is in python. While the call gets transpiled to use === in JS, in python it is transpiled into ==, leading to different results.

Repro code

See also this REPL

Transpiling this code

let r1 = ResizeArray([1; 2])
let r2 = ResizeArray([1; 2])
let r3 = r1

printfn "%A" (LanguagePrimitives.PhysicalEquality r1 r2) // false, both arrays are instantiated seperately
printfn "%A" (LanguagePrimitives.PhysicalEquality r2 r2) // true, refers to the same thing
printfn "%A" (LanguagePrimitives.PhysicalEquality r3 r1) // true, refers to the same thing via reference assignment

Expected and actual results

Should print

false
true
true

(and does so in F# and JS)

But prints

true
true
true
@MangelMaxime
Copy link
Member

I found a potential place to fix this issue at

| BinaryEqual, false ->
match left, right with
// Use == with literals
| Constant _, _ -> compare Eq
| _, Constant _ -> compare Eq
// Use `is` with None (except literals)
| _, IsNone -> compare Is
| IsNone, _ -> compare Is
// Use == for the rest
| _ -> compare Eq

however changing | _ -> compare Eq to | _ -> compare Is make the following test fails:

let xs = [| 0 .. 500 |]
let ys =
    Array.append xs xs
    |> Array.distinctBy(fun x -> x.ToString())
ys |> equal xs
  xs: Array[int] = to_array(range_big_int(0, 1, 500))
  def projection(x: int, argv: Any=argv) -> str:
      return int32_to_string(x)

  class ObjectExpr1:
      @property
      def Equals(self) -> Callable[[str, str], bool]:
          def _arrow0(x_1: str, y: str) -> bool:
              return x_1 is y // This line here is the culpit

          return _arrow0

      @property
      def GetHashCode(self) -> Callable[[str], int]:
          return string_hash

  ys: Array[int] = Array_distinctBy(projection, append(xs, xs, Int32Array), ObjectExpr1())
  equal(xs, ys)

But I have a feeling this is not exactly due to the changes from this PR but because the generated ys array contains one too many value:

Exception: Expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - Actual: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants