<p dir="auto">When method extension coupled with multiple dispatch mechanism, we tend to be always find ourselves in the loop of continuing adding disambiguating methods. Seriously, this is unsustainable in the long run.</p>
<p dir="auto">Consider the following:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# suppose this is defined in base

type A &lt;: BaseT end

+(::A, ::A) = println(&quot;A + A&quot;)   # this needs to be in front
+(::A, ::BaseT) = println(&quot;A + BaseT&quot;)
+(::BaseT, ::A) = println(&quot;BaseT + A&quot;)"><pre class="notranslate"><span class="pl-c"><span class="pl-c">#</span> suppose this is defined in base</span>

type A <span class="pl-k">&lt;:</span> <span class="pl-c1">BaseT</span> <span class="pl-k">end</span>

<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">A</span>, <span class="pl-k">::</span><span class="pl-c1">A</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>A + A<span class="pl-pds">"</span></span>)   <span class="pl-c"><span class="pl-c">#</span> this needs to be in front</span>
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">A</span>, <span class="pl-k">::</span><span class="pl-c1">BaseT</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>A + BaseT<span class="pl-pds">"</span></span>)
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">BaseT</span>, <span class="pl-k">::</span><span class="pl-c1">A</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>BaseT + A<span class="pl-pds">"</span></span>)</pre></div>
<p dir="auto">If someone want to write a package that extends <code class="notranslate">BaseT</code>, he will need to write</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="module modB
import Base: BaseT, A, +

type B &lt;: BaseT end

# for the second type, you have to put three methods in front
# in order to reduce ambiguity
+(::A, ::B) = println(&quot;A and B&quot;)
+(::B, ::A) = println(&quot;B and A&quot;)
+(::B, ::B) = println(&quot;B and B&quot;)

+(::B, ::BaseT) = println(&quot;B and BaseT&quot;) 
+(::BaseT, ::B) = println(&quot;BaseT and B&quot;)
end"><pre class="notranslate"><span class="pl-k">module</span> modB
<span class="pl-k">import</span> Base<span class="pl-k">:</span> BaseT, A, <span class="pl-k">+</span>

type B <span class="pl-k">&lt;:</span> <span class="pl-c1">BaseT</span> <span class="pl-k">end</span>

<span class="pl-c"><span class="pl-c">#</span> for the second type, you have to put three methods in front</span>
<span class="pl-c"><span class="pl-c">#</span> in order to reduce ambiguity</span>
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">A</span>, <span class="pl-k">::</span><span class="pl-c1">B</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>A and B<span class="pl-pds">"</span></span>)
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">B</span>, <span class="pl-k">::</span><span class="pl-c1">A</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>B and A<span class="pl-pds">"</span></span>)
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">B</span>, <span class="pl-k">::</span><span class="pl-c1">B</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>B and B<span class="pl-pds">"</span></span>)

<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">B</span>, <span class="pl-k">::</span><span class="pl-c1">BaseT</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>B and BaseT<span class="pl-pds">"</span></span>) 
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">BaseT</span>, <span class="pl-k">::</span><span class="pl-c1">B</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>BaseT and B<span class="pl-pds">"</span></span>)
<span class="pl-k">end</span></pre></div>
<p dir="auto">If there are <code class="notranslate">n</code> subtypes of <code class="notranslate">BaseT</code> in the <code class="notranslate">Base</code>, <code class="notranslate">O(n^2)</code> disambiguating methods need to be added.</p>
<p dir="auto">What's worse, if another one independently creates another package that extends <code class="notranslate">BaseT</code>, as below:</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="module modC
import Base: BaseT, A, +

type C &lt;: BaseT end

+(::A, ::C) = println(&quot;A and C&quot;)
+(::C, ::A) = println(&quot;C and A&quot;)
+(::C, ::C) = println(&quot;C and C&quot;)

foo(::C, ::BaseT) = println(&quot;C and BaseT&quot;) 
foo(::BaseT, ::C) = println(&quot;BaseT and C&quot;)
end"><pre class="notranslate"><span class="pl-k">module</span> modC
<span class="pl-k">import</span> Base<span class="pl-k">:</span> BaseT, A, <span class="pl-k">+</span>

type C <span class="pl-k">&lt;:</span> <span class="pl-c1">BaseT</span> <span class="pl-k">end</span>

<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">A</span>, <span class="pl-k">::</span><span class="pl-c1">C</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>A and C<span class="pl-pds">"</span></span>)
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">C</span>, <span class="pl-k">::</span><span class="pl-c1">A</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>C and A<span class="pl-pds">"</span></span>)
<span class="pl-k">+</span>(<span class="pl-k">::</span><span class="pl-c1">C</span>, <span class="pl-k">::</span><span class="pl-c1">C</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>C and C<span class="pl-pds">"</span></span>)

<span class="pl-en">foo</span>(<span class="pl-k">::</span><span class="pl-c1">C</span>, <span class="pl-k">::</span><span class="pl-c1">BaseT</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>C and BaseT<span class="pl-pds">"</span></span>) 
<span class="pl-en">foo</span>(<span class="pl-k">::</span><span class="pl-c1">BaseT</span>, <span class="pl-k">::</span><span class="pl-c1">C</span>) <span class="pl-k">=</span> <span class="pl-c1">println</span>(<span class="pl-s"><span class="pl-pds">"</span>BaseT and C<span class="pl-pds">"</span></span>)
<span class="pl-k">end</span></pre></div>
<p dir="auto">Then when one want to import both packages (even without <code class="notranslate">using</code>, just <code class="notranslate">import</code>), there will be ambiguities warnings about <code class="notranslate">+(B, C)</code> etc.</p>
<p dir="auto">This issue has caused a lot of headaches for packages that try to define their own customized array types, for example:</p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="25105359" data-permission-text="Title is private" data-url="https://github.com/JuliaStats/DataArrays.jl/issues/51" data-hovercard-type="issue" data-hovercard-url="/JuliaStats/DataArrays.jl/issues/51/hovercard" href="https://github.com/JuliaStats/DataArrays.jl/issues/51">JuliaStats/DataArrays.jl#51</a></li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="29322903" data-permission-text="Title is private" data-url="https://github.com/JuliaStats/DataArrays.jl/issues/77" data-hovercard-type="issue" data-hovercard-url="/JuliaStats/DataArrays.jl/issues/77/hovercard" href="https://github.com/JuliaStats/DataArrays.jl/issues/77">JuliaStats/DataArrays.jl#77</a></li>
</ul>
<p dir="auto"><em>Images</em> and some other packages also encounter such problems.</p>
<p dir="auto">Whereas this might be solved by continuously adding disambiguating methods, problems still exist (or even worse) when you use two or more of these packages together.<br>
Are we going to add disambiguating methods for every pair of array types residing in different packages?</p>
<p dir="auto">Just try the following, you will see screens full of ambiguities warnings (though just importing either one will be fine):</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import DataArrays
import Images"><pre class="notranslate"><span class="pl-k">import</span> DataArrays
<span class="pl-k">import</span> Images</pre></div>
<p dir="auto">We seriously need a fundamental solution to this.</p>
<p dir="auto">Branching this Issue off of the conversation here: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="392387472" data-permission-text="Title is private" data-url="https://github.com/JuliaLang/julia/issues/30445" data-hovercard-type="pull_request" data-hovercard-url="/JuliaLang/julia/pull/30445/hovercard?comment_id=243427894&amp;comment_type=review_comment" href="https://github.com/JuliaLang/julia/pull/30445#discussion_r243427894">#30445 (comment)</a></p>
<hr>
<p dir="auto">Reproducing it in this Issue:</p>
<blockquote>
<p dir="auto">Also, I wanted to ask: Does anyone know why <code class="notranslate">signed</code> takes <code class="notranslate">x::Unsigned</code>, but <code class="notranslate">unsigned</code> takes <code class="notranslate">x::BitSigned</code>? I'm <em>guessing</em> it's to prevent <code class="notranslate">BigInt</code> from falling under the <code class="notranslate">reinterpret</code> implementation. I'm currently just copying that in the <code class="notranslate">::Type{T}</code> definitions -- does that seem reasonable?</p>
</blockquote>
<hr>
<blockquote>
<p dir="auto">yes -- the set difference is the presence/absence of <code class="notranslate">BigInt</code><br>
also Signed is an abstract type, BitSigned is a Union (in this context it is immaterial pbly).</p>
</blockquote>
<hr>
<blockquote>
<p dir="auto">Now that you mention it, it is a little weird, because there's nothing about the docstring for <code class="notranslate">Unsigned</code> that specifies it needs to be <code class="notranslate">isprimitivetype</code>. Nothing stops me from defining</p>
<div class="highlight highlight-source-julia notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="struct WeirdUnsigned &lt;: Unsigned
    msg::String
    val::UInt16
end
WeirdUnsigned(x::Int) = WeirdUnsigned(&quot;missing&quot;, UInt16(x))
Base.Signed(x::WeirdUnsigned) = signed(x.val)

julia&gt; signed(WeirdUnsigned(4))
ERROR: bitcast: expected primitive type value for second argument
Stacktrace:
 [1] reinterpret at ./essentials.jl:381 [inlined]
 [2] signed(::WeirdUnsigned) at ./int.jl:162
 [3] top-level scope at none:0"><pre class="notranslate"><span class="pl-k">struct</span> WeirdUnsigned <span class="pl-k">&lt;:</span> <span class="pl-c1">Unsigned</span>
    msg<span class="pl-k">::</span><span class="pl-c1">String</span>
    val<span class="pl-k">::</span><span class="pl-c1">UInt16</span>
<span class="pl-k">end</span>
<span class="pl-en">WeirdUnsigned</span>(x<span class="pl-k">::</span><span class="pl-c1">Int</span>) <span class="pl-k">=</span> <span class="pl-c1">WeirdUnsigned</span>(<span class="pl-s"><span class="pl-pds">"</span>missing<span class="pl-pds">"</span></span>, <span class="pl-c1">UInt16</span>(x))
Base<span class="pl-k">.</span><span class="pl-en">Signed</span>(x<span class="pl-k">::</span><span class="pl-c1">WeirdUnsigned</span>) <span class="pl-k">=</span> <span class="pl-c1">signed</span>(x<span class="pl-k">.</span>val)

julia<span class="pl-k">&gt;</span> <span class="pl-c1">signed</span>(<span class="pl-c1">WeirdUnsigned</span>(<span class="pl-c1">4</span>))
ERROR<span class="pl-k">:</span> bitcast<span class="pl-k">:</span> expected <span class="pl-k">primitive type</span> value <span class="pl-k">for</span> second argument
Stacktrace<span class="pl-k">:</span>
 [<span class="pl-c1">1</span>] reinterpret at <span class="pl-k">./</span>essentials<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">381</span> [inlined]
 [<span class="pl-c1">2</span>] <span class="pl-c1">signed</span>(<span class="pl-k">::</span><span class="pl-c1">WeirdUnsigned</span>) at <span class="pl-k">./</span>int<span class="pl-k">.</span>jl<span class="pl-k">:</span><span class="pl-c1">162</span>
 [<span class="pl-c1">3</span>] top<span class="pl-k">-</span>level scope at none<span class="pl-k">:</span><span class="pl-c1">0</span></pre></div>
<p dir="auto">Of course this isn't a catastrophe: the error is sensible and one could always provide a more specialized definition. (If it returned a borked answer, that would be a genuine problem.) But of course the same could be said of <code class="notranslate">Signed</code>, and <code class="notranslate">reinterpret(UInt, BigInt(4))</code> throws the same error.</p>
</blockquote>
<hr>
<blockquote>
<p dir="auto">Yeah, that's exactly the sort of thing I was referring to. Thanks for including an example.</p>
<blockquote>
<p dir="auto">Of course this isn't a catastrophe: the error is sensible and one could always provide a more specialized definition. (If it returned a borked answer, that would be a genuine problem.) But of course the same could be said of <code class="notranslate">Signed</code>, and <code class="notranslate">reinterpret(UInt, BigInt(4))</code> throws the same error.</p>
</blockquote>
<p dir="auto">Totally, I agree. But I think that it's the inconsistency with <code class="notranslate">unsigned()</code> that's a little weird. I think <em>either</em> we should change this to also accept only <code class="notranslate">BitUnsigned</code>, so that you'd get the correct behavior above, <em>OR</em> we should loosen <code class="notranslate">unsigned()</code> to accept any kind of <code class="notranslate">Signed</code>, and just add an extra overload for <code class="notranslate">BigInt</code>, exactly as you'd have to do for <code class="notranslate">WeirdUnsigned</code> above. Does that seem reasonable to you?</p>
</blockquote>