Can a struct have a variable supertype?


#1

I’m working on beefing up JavaCall.jl and I have a proxy struct (currently called JProxy) that represents a Java object, along with an abstract type hierarchy with one type for each Java type. It would be convenient if the JProxy struct had a variable supertype. Julia lets me do that but doesn’t behave in the way I expect. Here is an example:

abstract type A end
abstract type B <: A end

struct S{T} <: T where {T <: A} end

@show(S{A} <: A)
@show(S{B} <: A)
@show(S{B} <: B)

The @show calls output this:

S{A} <: A = true
S{B} <: A = true
S{B} <: B = false

I expected the last expression to return true but it returned false.

The struct declaration’s AST seems to tell a different story from what I expected:

:(struct S{T} <: T where {T <: A} end)

outputs

:(struct S{T} <: (T where T <: A)
      #= REPL[22]:1 =#
  end)

Which makes it look like there is actually a separate T variable for the supertype. Is this true? It seems like if it is then the variable is unbindable and is actually equivalent to A.


#2

Yes, your analysis is correct. You can also check this be re-writing it

struct S{T} <: U where {U <: A} end

which behaves identically to your example. You’d want something like:

julia> struct (MT{T} <: T) where {T <: A} end
ERROR: syntax: invalid type signature

but that does not work, not this

julia> struct S{T<:A} <: T end
ERROR: invalid subtyping in definition of S

Anyway, bottom line is that you can’t do this. But you can just dispatch on the type parameter, so I don’t think S needs to have the same supertype as its type parameter.