# \[Breaking\] Should \`isequal(convert(T, x), x)\` always be true?

**URL:** https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169
**Category:** Internals & Design
**Created:** [August 24, 2023, 8:47pm UTC](https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169 "2023-08-24T20:47:59Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [August 24, 2023, 8:47pm UTC](https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169/1 "2023-08-24T20:47:59Z")

</div>

In Julia 1.x, it seems like `isequal(convert(T, x), x)` is usually true for Base and standard library types. However, there is one notable exception: `Char` to `Int` and `Int` to `Char`. It is a little odd that this works:

```julia
julia> struct A
           x::Int
       end

julia> A('a')
A(97)

```

`Dict` and `Set` have an [explicit workaround](https://github.com/JuliaLang/julia/blob/4ac6b053473c4a588984b313ee0ee12dc7503e41/base/dict.jl#L365) for cases where `isequal(convert(T, x), x)` is not true:

```julia
function setindex!(h::Dict{K,V}, v0, key0) where V where K
    if key0 isa K
        key = key0
    else
        key = convert(K, key0)::K
        if !(isequal(key, key0)::Bool)
            throw(ArgumentError("$(limitrepr(key0)) is not a valid key for type $K"))
        end
    end
    setindex!(h, v0, key)
end

```

As you can see, the `setindex!` method tests to see whether the converted key `isequal` to the input key. You can see this check in action here:

```julia
julia> push!(Set('a'), 99)
ERROR: ArgumentError: 99 is not a valid key for type Char
Stacktrace:
 [1] setindex!(h::Dict{Char, Nothing}, v0::Nothing, key0::Int64)
   @ Base ./dict.jl:376
 [2] push!(s::Set{Char}, x::Int64)
   @ Base ./set.jl:67
 [3] top-level scope
   @ REPL[21]:1

```

Would it make sense in Julia 2.0 to add a note to the `convert` docstring that says that `isequal(convert(T, x), x)` should always be true? Are there any other examples of Base or standard library types for which `isequal(convert(T, x), x)` is not true?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [August 24, 2023, 8:54pm UTC](https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169/2 "2023-08-24T20:54:01Z")

</div>

The other main example is floating point types where we allow rounding in `convert`

---

<div class="post-metadata">

### Author: ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)
#### Post date: [August 24, 2023, 8:54pm UTC](https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169/3 "2023-08-24T20:54:05Z")

</div>

```julia
julia> convert(Char, 100)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)

julia> isequal('d', 100)
false

```

I would be quite surprised if `isequal('d', 100)` evaluated `true`

I can see the desire, but I would rather obtain it by making `convert` less permissive rather than making `isequal` more permissive. but even then, I think the same case is more strongly made for `reinterpret` than it is for `convert`

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [August 24, 2023, 9:00pm UTC](https://discourse.julialang.org/t/breaking-should-isequal-convert-t-x-x-always-be-true/103169/4 "2023-08-24T21:00:47Z")

</div>

I suppose I was not clear enough in my original post. My fix would be to remove the `convert` methods for `Int -> Char` and `Char -> Int`, not to make `isequal` more permissive.
