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

Wrong type-parameter bounds inside a type alias #56691

Closed
frankwswang opened this issue Nov 26, 2024 · 7 comments
Closed

Wrong type-parameter bounds inside a type alias #56691

frankwswang opened this issue Nov 26, 2024 · 7 comments
Labels
invalid Indicates that an issue or pull request is no longer relevant types and dispatch Types, subtyping and method dispatch

Comments

@frankwswang
Copy link

frankwswang commented Nov 26, 2024

MWE (tested on Julia 1.11.1):

julia> const MyDict{T, C<:AbstractDict{<:Array, <:Array{T}}} = C
AbstractDict{<:Array, <:Array{T}} where T

julia>  MyDict{Float64}
AbstractDict{<:Array, <:Array{Float64}}

julia> MyDict{T, Dict{Vector{Int}, Array{T, 2}}} where {T} # Should have been: `Dict{Vector{Int64}, Matrix{T}} where T`
AbstractDict{Dict{Vector{Int64}, Matrix{T}}, <:Array{T}} where T

julia> MyDict{Float64, Dict{Vector{Float64}, Array{Float64, 2}}} # Should have been: `Dict{Vector{Float64}, Matrix{Float64}`
ERROR: TypeError: in AbstractDict, in #s1, expected var"#s1"<:Array, got Type{Dict{Vector{Float64}, Matrix{Float64}}}
@oscardssmith oscardssmith added bug Indicates an unexpected problem or unintended behavior types and dispatch Types, subtyping and method dispatch labels Nov 26, 2024
@oscardssmith
Copy link
Member

reproduced on master.

@vtjnash
Copy link
Member

vtjnash commented Nov 27, 2024

Those look correct to me. You only have one UnionAll variable, so it should only accept one application, though if that application is a UnionAll variable, then the result can accept another one again

@vtjnash vtjnash added invalid Indicates that an issue or pull request is no longer relevant and removed bug Indicates an unexpected problem or unintended behavior labels Nov 27, 2024
@oscardssmith
Copy link
Member

isn't the TypeError a problem?

@frankwswang
Copy link
Author

Those look correct to me. You only have one UnionAll variable, so it should only accept one application, though if that application is a UnionAll variable, then the result can accept another one again

How is it acceptable that a more specialized version of MyDict is not even the subtype of MyDict?

julia> (MyDict{T, Dict{Vector{Int}, Array{T, 2}}} where {T}) <: MyDict
false

Moreover, MyDict{T, Dict{Vector{Int}, Array{T, 2}}} where {T} <: C does not even meet its bound AbstractDict{<:Array, <:Array{T}} where {T}:

julia> bound = AbstractDict{<:Array, <:Array{T}} where {T}
AbstractDict{<:Array, <:Array{T}} where T

julia> (MyDict{T, Dict{Vector{Int}, Array{T, 2}}} where {T}) <: bound
false

@vtjnash
Copy link
Member

vtjnash commented Nov 27, 2024

Julia does not enforce type constraints applied to type aliases when making new type aliases from them

@frankwswang
Copy link
Author

More problematic examples:

julia> const TypeofMyT{T, C<:Vector{T}} = Type{C}
Type{C} where {T, C<:Vector{T}}

julia> TypeofMyT{Integer, <:Vector{<:Real}}
Type{<:Vector{<:Real}}

which should have been TypeofMyT{Integer, <:Vector{Integer}} (or should not have been allowed, which is debateble) because

julia> Vector{Integer} <: Vector{<:Real}
true

julia> Vector{<:Real} <: Vector{Integer}
false

julia> TypeofMyT{Integer, <:Vector{<:Real}} <: TypeofMyT
false
julia> const MyT{T, C<:Vector{T}} = C
Vector (alias for Array{T, 1} where T)

It is already concerning that the compiler automatically converts MyT back to vector. Consequently, it does not even allow a specification of the second parameter:

julia> MyT{<:Any, Vector{Float64}}
ERROR: too many parameters for type Array

Just because there's a reason for such behavior does not automatically justify it. If you allow the user to rename a type legally with additional type parameters, you should support full feature and consistent type inference for all of these parameters or forbid such construction altogether. Calling this behavior "correct," IMHO, does not seem a convincing solution.

@frankwswang
Copy link
Author

Julia does not enforce type constraints applied to type aliases when making new type aliases from them

What about this?

julia> const MyArray{N, T<:Real} = Array{T, N}
Array{T, N} where {N, T<:Real}

julia> MyArray{1}
Vector{T} where T<:Real (alias for Array{T, 1} where T<:Real)

julia> const MyArrArr{N, T<:MyArray{N, <:Integer}} = Array{T, N}
Array{T, N} where {N, T<:(Array{<:Integer, N})}

julia> MyArrArr{2, Vector{Int}}
ERROR: TypeError: in Array, in T, expected T<:(Matrix{<:Integer}), got Type{Vector{Int64}}

julia> MyArrArr{2, Matrix{Float64}}
ERROR: TypeError: in Array, in T, expected T<:(Matrix{<:Integer}), got Type{Matrix{Float64}}

julia> MyArrArr{2, Matrix{Int}}
Matrix{Matrix{Int64}} (alias for Array{Array{Int64, 2}, 2})

The type constraints seem to propagate properly in this scenario, no?

@vtjnash vtjnash closed this as not planned Won't fix, can't repro, duplicate, stale Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid Indicates that an issue or pull request is no longer relevant types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

No branches or pull requests

3 participants