Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inner type parameter depending on outer type parameter loses the fixed outer parameter information #26321

Closed
wsshin opened this issue Mar 5, 2018 · 2 comments
Assignees
Labels
types and dispatch Types, subtyping and method dispatch

Comments

@wsshin
Copy link
Contributor

wsshin commented Mar 5, 2018

This problem was originally reported here in Julia discourse. The following is a simplified description of the problem through the discussion there.

Consider a parametrized type MyType with two type parameters N and S, where the range of the inner type parameter S depends on the outer type parameter N:

julia> VERSION
v"0.7.0-DEV.4465"

julia> struct MyType{N,S<:NTuple{N}}
           t::S
       end

Now, create instances of two different MyType types—one with a tuple of three Int64's and another with a tuple of three Float64's:

julia> mi = MyType{3,NTuple{3,Int64}}((1,2,3))
MyType{3,Tuple{Int64,Int64,Int64}}((1, 2, 3))

julia> mf = MyType{3,NTuple{3,Float64}}((1.0,2.0,3.0))
MyType{3,Tuple{Float64,Float64,Float64}}((1.0, 2.0, 3.0))

Note that both mi and mf have the outer type parameter N = 3, and therefore their inner type parameter S must be subtypes of NTuple{3}. However, the information of N in S is lost when an inhomogeneous array of mi and mf is constructed:

julia> vm = [mi, mf]; typeof(vm)
Array{MyType{3,S} where S<:(Tuple{Vararg{T,N}} where T) where N,1}

Notice that the information N = 3 is correctly passed to the element type MyType{3,S} here, but not in S<:(Tuple{Vararg{T,N}} where T) where N. As a result, the following generates an error:

julia> vm::Vector{<:MyType{3}}
ERROR: TypeError: typeassert: expected Array{#s1,1} where #s1<:(MyType{3,S} where S<:(Tuple{T,T,T} where T)), got Array{MyType{3,S} where S<:(Tuple{Vararg{T,N}} where T) where N,1}

even though both mi and mf are of type MyType{3}:

julia> mi::MyType{3}
MyType{3,Tuple{Int64,Int64,Int64}}((1, 2, 3))

julia> mf::MyType{3}
MyType{3,Tuple{Float64,Float64,Float64}}((1.0, 2.0, 3.0))

Is this an expected behavior?

@wsshin wsshin changed the title Inner type parameter depending on outer type parameter lose the fixed outer parameter information Inner type parameter depending on outer type parameter loses the fixed outer parameter information Mar 5, 2018
@JeffBezanson JeffBezanson added the types and dispatch Types, subtyping and method dispatch label Mar 20, 2018
@JeffBezanson
Copy link
Sponsor Member

This is the result given by typejoin, which is sometimes lazy and gives a wider type than it could. It should be improved in this case: instead of using the original typevar when corresponding parameters don't match, it should use the typevar obtained after substituting values for prior parameters.

@wsshin
Copy link
Contributor Author

wsshin commented Mar 23, 2018

Thanks a lot for fixing this issue so quickly!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

No branches or pull requests

2 participants