The situation is the following: I’m defining some iterators with the following structure
module foo
module Generic
import Base: iterate
abstract type Gen
struct iterator{G} where {G<:Gen}
end
Base.iterate(S::iterator{Gen}, state) = ...
end
module Specific
using ..Generic
import Base:iterate
struct Spec<:Gen
end
Base.iterate(S::iterator{Spec}, state)=...
end
But the compiler seems like it cannot find Base.iterate(S::iterator{Spec}, state), i.e., it tries to dispatch on the Generic method and not on the Specific.
It’s not different–those method definitions are exactly the same:
julia> abstract type A end
julia> f(x::A) = 1
f (generic function with 1 method)
julia> f(x::T) where {T <: A} = 2
f (generic function with 1 method)
Note how f still has exactly one method, because A and T where T <: A are exactly identical:
julia> (T where T <: A) === A
true
Reading between the lines in your example, I wonder if you were actually doing something like:
julia> struct Container{T}; end
julia> g(x::Container{A}) = 1
g (generic function with 1 method)
vs.
julia> g(x::Container{T}) where {T <: A} = 2
g (generic function with 2 methods)
Because parametric types in Julia are not covariant, Container{A} and Container{T} where {T <: A} are indeed different.
This comes up often in arrays, since an Array{Real} is an array in which each element can be any (different) kind of Real, while an Array{T} where {T <: Real} is an array with an element type which is itself some subtype of Real. Thus, Array{Int} is a subtype of Array{T} where {T <: Real}, but Array{Int} is not a subtype of Array{Real}. Invariance can be hard to wrap your head around the first time–I had to read this section of the manual a few times before I got it: Types · The Julia Language
Yes, you’re right, it was a parametric type! I missed the huge yellow warning in the page you linked… Thank you for the nice answer, it cleared up things.