# No automatic conversion with abstract type

**URL:** <https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 19, 2018, 11:23am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710 "2018-11-19T11:23:57Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![mikolajpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikolajpp/32/2742_2.png) [@mikolajpp](https://discourse.julialang.org/u/mikolajpp)\
**Post date:** [November 19, 2018, 11:23am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/1 "2018-11-19T11:23:57Z")

</div>

I have the following minimal example:

```julia
abstract type Gate{N} end;

struct IdentGate{N} <: Gate{N}
    wire::UInt8

    function IdentGate{N}(w::Int) where {N}
        @assert 1 <= w <= N
        new(w)
    end
end

GateProduct{N} = Array{Gate{N}, 1}
convert(::Type{GateProduct{N}}, g::Gate{N}) where {N} = GateProduct{N}([g])

```

Explicit conversion of `IdentGate` to `GateProduct` works.  
However, it is never called automatically.

In particular,

```julia
a = Array{GateProduct{2}, 1}()
push!(a, IdentGate{2}(1))

```

Does not work. Is this expected behaviour?  
As per documentation, convert should be called to construct GateProduct{2} from IdentGate{2}  
which is a Gate{2} instance.

---

<div class="post-metadata">

**Author:** ![mikolajpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikolajpp/32/2742_2.png) [@mikolajpp](https://discourse.julialang.org/u/mikolajpp)\
**Post date:** [November 19, 2018, 11:33am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/2 "2018-11-19T11:33:25Z")

</div>

I verified that the snippet I posted does indeed work when compiled separately.  
What could render it broken?

The code is part of larger codebase which is `included` from REPL and it throws exception when part of it.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [November 19, 2018, 11:38am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/3 "2018-11-19T11:38:14Z")

</div>

You probably just forgot to `import Base: convert`.

---

<div class="post-metadata">

**Author:** ![mikolajpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikolajpp/32/2742_2.png) [@mikolajpp](https://discourse.julialang.org/u/mikolajpp)\
**Post date:** [November 19, 2018, 11:39am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/4 "2018-11-19T11:39:40Z")

</div>

No, in fact import `Base.convert` was included more than once.

I have narrowed down the issue to one file which imported `Base.convert` being `included` more than once.  
Once includes are made unique, the issue goes away.  
Does this sound like a bug?

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [November 19, 2018, 11:42am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/5 "2018-11-19T11:42:23Z")

</div>

Ok, the example in your top post works with an `import Base: convert` so would be good if you could supply an example that duplicates the broken behavior.

---

<div class="post-metadata">

**Author:** ![mikolajpp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikolajpp/32/2742_2.png) [@mikolajpp](https://discourse.julialang.org/u/mikolajpp)\
**Post date:** [November 19, 2018, 11:59am UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/6 "2018-11-19T11:59:34Z")

</div>

Ok, I got a minimal repo: [https://github.com/mikolajpp/inhibited-convert](https://github.com/mikolajpp/inhibited-convert)

The issue is following. For some reason in my codebase I ended up with one convert definition  
which was not preceded with `import Base.convert`. Then all subsequent Base.convert import were inhibited until it hit Gate conversion.

I don’t know if this is technically bug, because I saw a warning in the console, so there is that 🙂

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [November 19, 2018, 12:40pm UTC](https://discourse.julialang.org/t/no-automatic-conversion-with-abstract-type/17710/7 "2018-11-19T12:40:41Z")

</div>

You should be able to work around this by explicitly defining `Base.convert(::Type{GateProduct[N}}, g::Gate{N}) where {N} = ...` - that way the definition of the conversion method doesn’t depend on `convert` not being overwritten before importing `Base.convert`.

> **Working**
>
> ```julia
> julia> struct Dummy end
> 
> julia> convert(::Type{Dummy}, x::Int) = 2
> convert (generic function with 1 method)
> 
> julia> abstract type Gate{N} end;
> 
> julia> struct IdentGate{N} <: Gate{N}
> wire::UInt8
> 
> function IdentGate{N}(w::Int) where {N}
> @assert 1 <= w <= N
> new(w)
> end
> end
> 
> julia> GateProduct{N} = Array{Gate{N}, 1}
> Array{Gate{N},1} where N
> 
> julia> Base.convert(::Type{GateProduct{N}}, g::Gate{N}) where {N} = GateProduct{N}([g])
> 
> julia> using Test
> 
> julia> @testset "Double include overloading bug" begin
> a = Array{GateProduct{2}, 1}()
> push!(a, IdentGate{2}(1))
> 
> @test true == true
> end
> Test Summary: | Pass Total
> Double include overloading bug | 1 1
> Test.DefaultTestSet("Double include overloading bug", Any[], 1, false)
> 
> ```

> **Broken**
>
> ```julia
> julia> struct Dummy end
> 
> julia> convert(::Type{Dummy}, x::Int) = 2
> convert (generic function with 1 method)
> 
> julia> import Base.convert
> WARNING: import of Base.convert into Main conflicts with an existing identifier; ignored.
> 
> julia> abstract type Gate{N} end;
> 
> julia> struct IdentGate{N} <: Gate{N}
> wire::UInt8
> 
> function IdentGate{N}(w::Int) where {N}
> @assert 1 <= w <= N
> new(w)
> end
> end
> 
> julia> GateProduct{N} = Array{Gate{N}, 1}
> Array{Gate{N},1} where N
> 
> julia> convert(::Type{GateProduct{N}}, g::Gate{N}) where {N} = GateProduct{N}([g])
> convert (generic function with 2 methods)
> 
> julia> using Test
> 
> julia> @testset "Double include overloading bug" begin
> 
> a = Array{GateProduct{2}, 1}()
> push!(a, IdentGate{2}(1))
> 
> @test true == true
> end
> Double include overloading bug: Error During Test at REPL[9]:1
> Got exception outside of a @test
> MethodError: Cannot `convert` an object of type IdentGate{2} to an object of type Array{Gate{2},1}
> Closest candidates are:
> convert(::Type{T<:Array}, !Matched::AbstractArray) where T<:Array at array.jl:489
> convert(::Type{T<:AbstractArray}, !Matched::T<:AbstractArray) where T<:AbstractArray at abstractarray.jl:14
> 
> ```

Note how the REPL already mentions the problem:

```julia
julia> struct Dummy end

julia> convert(::Type{Dummy}, x::Int) = 2
convert (generic function with 1 method)

julia> import Base.convert
WARNING: import of Base.convert into Main conflicts with an existing identifier; ignored.

```

I suspect this is intended behaviour, because the imported identfier really should not overwrite existing things.
