Consider this example:

```
julia> abstract type AbstractT end
julia> struct A <: AbstractT
i::Int
end
julia> struct Param
myparam::Int
end
julia> (::Type{T})(p::Param) where T<:AbstractT = T(p.myparam)
julia> A(Param(4))
ERROR: MethodError: A(::Param) is ambiguous. Candidates:
(::Type{T})(p::Param) where T<:AbstractT in Main at REPL[4]:1
A(i) in Main at REPL[2]:2
Possible fix, define
A(::Param)
Stacktrace:
[1] top-level scope
@ REPL[5]:1
```

Why is `(::Type{T})(p::Param)`

conflicting with `A(::Any)`

? I would expect it to be chosen as it is more specified.

In `A(i)`

, `A`

is an exact type (you could write the signature as `(::Type{T})(p::Param) where A<:T<:A`

), but the argument is `<:Any`

. The opposite is true for `(::Type{T})(p::Param) where T<:AbstractT`

.

You could re-write the problem as

```
julia> f(::Type{T}, p::Param) where T<:AbstractT = 1
f (generic function with 1 method)
julia> f(::Type{A}, p) = 2
f (generic function with 2 methods)
julia> f(A, Param(2))
ERROR: MethodError: f(::Type{A}, ::Param) is ambiguous. Candidates:
f(::Type{T}, p::Param) where T<:AbstractT in Main at REPL[73]:1
f(::Type{A}, p) in Main at REPL[74]:1
```

which hopefully makes the ambiguity more obvious.

1 Like

Thank you, that helps clear up my confusion.

One option to avoid ambiguity then is to specify an inner constructor, so the `::Any`

-method is never created:

```
julia> struct B <: AbstractT
i::Int
B(i::Int) = new(i)
end
julia> B(Param(4))
B(4)
```

1 Like