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

Generic Record Types have different Equality semantics to concrete types #527

Open
manofstick opened this issue Jul 8, 2015 · 0 comments
Labels
Area-Compiler-Optimization The F# optimizer, release code gen etc. Bug Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code.
Milestone

Comments

@manofstick
Copy link
Contributor

From #513

The problem is that for concrete types, the implementation of IStructuralEquatable optimizes standard types, which means that the IEqualityComparer is unused.

The following example shows this by using a specialized IEqualityComparer to try to do an uppercase string comparison.

type A = { A : string }
type B<'a> = { B : 'a }

[<EntryPoint>]
let main argv =
    let a1, a2 = { A = "Hello"}, { A = "HELLO" }
    let b1, b2 = { B = "Hello"}, { B = "HELLO" }

    let compareStringWithUpper=
        let toupper (s:string) = s.ToUpper ()
        { new IEqualityComparer with
            member this.GetHashCode item =
                match item with
                | :? string as s -> (toupper s).GetHashCode ()
                | _ -> failwith "Not in this example..."
            member this.Equals (lhs, rhs) =
                match lhs, rhs with
                | (:? string as s1), (:? string as s2) -> (toupper s1).Equals(toupper s2)
                | _ -> failwith "Not in this example..." }

    let a_is_good = (a1 :> IStructuralEquatable).Equals(a2, compareStringWithUpper)
    let b_is_good = (b1 :> IStructuralEquatable).Equals(b2, compareStringWithUpper)

    printfn "A is %s" <| if a_is_good then "Good" else "Bad"
    printfn "B is %s" <| if b_is_good then "Good" else "Bad"

    if a_is_good <> b_is_good then
        printfn "But worse than those results are that they are inconsistent!"

With the output

A is Bad
B is Good
But worse than those results are that they are inconsistent!

I think the implementation of IStructuralEquatable.Equals shouldn't used inlined IL, but rather always defer back to supplied IEqualityComparer.

Fixing this before #513 is implemented would have a performance impact.

@KevinRansom KevinRansom removed the pri-3 label Dec 4, 2015
@dsyme dsyme added Area-Compiler Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code. labels Jan 9, 2016
@cartermp cartermp added this to the Unknown milestone Aug 25, 2018
@cartermp cartermp modified the milestones: Unknown / not bug, Backlog May 23, 2019
@dsyme dsyme added Area-Compiler-Optimization The F# optimizer, release code gen etc. and removed Area-Compiler labels Mar 31, 2022
@vzarytovskii vzarytovskii moved this to Not Planned in F# Compiler and Tooling Jun 17, 2022
@vzarytovskii vzarytovskii reopened this Jan 5, 2024
@github-project-automation github-project-automation bot moved this from Done to In Progress in F# Compiler and Tooling Jan 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compiler-Optimization The F# optimizer, release code gen etc. Bug Impact-Low (Internal MS Team use only) Describes an issue with limited impact on existing code.
Projects
Archived in project
Development

No branches or pull requests

5 participants