julia> d[1] = 5
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Tuple{Int64,Int64}
Closest candidates are:
convert(::Type{T<:Tuple{Any,Vararg{Any,N} where N}}, ::T<:Tuple{Any,Vararg{Any,N} where N}) where T<:Tuple{Any,Vararg{Any,N} where N} at essentials.jl:274
convert(::Type{T<:Tuple{Any,Vararg{Any,N} where N}}, ::Tuple{Any,Vararg{Any,N} where N}) where T<:Tuple{Any,Vararg{Any,N} where N} at essentials.jl:275
convert(::Type{T<:Tuple}, ::CartesianIndex) where T<:Tuple at multidimensional.jl:130
...
Stacktrace:
[1] setindex!(::Dict{Tuple{Int64,Int64},Int64}, ::Int64, ::Int64) at ./dict.jl:373
[2] top-level scope at none:0

That certainly appears to be the case, and you seem to expect that. Why wouldn’t it be ?

help?> TypeError
search: TypeError
TypeError(func::Symbol, context::AbstractString, expected::Type, got)
A type assertion failure, or calling an intrinsic function with an incorrect argument type.

Good point - I was definitely conflating this specific MethodError with a TypeError - this inability to convert the type is the one I was expecting.

I’m just trying to imagine what the method signature would have to be in order to have it specialize in the type. Sure it could be done, but it seems more complicated than it’s worth for something that’s going to end at an error in either case. Then again, I’m no expert, so maybe it’s easier than I imagine (but I still don’t really see the benefit).

julia> struct Five end;
julia> Base.isequal(::Five, ::Five)=true;
julia> Base.isequal(::Five, x)= isequal(x, 5);
julia> Base.isequal(x, ::Five)= isequal(x, 5);
julia> Base.hash(::Five, h::UInt)=Base.hash(5, h)
julia> d=Dict(1=>2, 5=>3);
julia> d[Five()]
3
julia> d[Five()]=1
ERROR: MethodError: Cannot `convert` an object of type Five to an object of type Int64