No automatic type promotion for parametric structs

When using different (but convertible) types in a constructor, for “standard” structs the types get converted automatically, e.g.

struct Struct1
    x:: Float64

s1b = Struct1(5, 1) # output: Struct1b(5.0, 1)

However, this is not done if the struct has a type parameter (even if this parameter is for a different field), instead I get a MethodError:

struct Struct2{T}
    x:: Float64
    y:: T

s2b = Struct2(5, 1) # MethodError, I would expect Struct2{Int64}(5.0, 1)

s2c = Struct2(5.0, 1) # this works, output: Struct2{Int64}(5.0, 1)

This behavior is confusing for me, I would expect that type promotion is also done for parametric structs. Or is there a good reason for it which I am not aware of?


I think it isn’t about automatic promotion, but rather about
what constructors are automatically provided.

In particular that the constructors provided for a UnionAll (like Struct2 i.e. Struct2{T} where T]) don’t have one that calls convert.

julia> methods(Struct1)  # method of concrete type
# 2 methods for type constructor:
[1] Struct1(x::Float64, y) in Main at REPL[5]:2
[2] Struct1(x, y) in Main at REPL[5]:2

julia> methods(Struct2)  # method of the UnionAll 
# 1 method for type constructor:
[1] Struct2(x::Float64, y::T) where T in Main at REPL[1]:2

julia> methods(Struct2{Int})  # method of concrete type
# 1 method for type constructor:
[1] Struct2{T}(x, y) where T in Main at REPL[1]:2

We can see if we pass the type parameter to Struct2 so we have a concrete type the convert does happen

julia> Struct2{Int}(5, 1.)
Struct2{Int64}(5.0, 1)

So question is kind why isn’t there a constructor
Struct2(a, b::B) where B = Struct2{B}(a, b)

If we define that then it works:

julia> Struct2(a, b::B) where B = Struct2{B}(a, b)

julia> Struct2(5,1)
Struct2{Int64}(5.0, 1)

I was just replying the same, but your is way better, so thanks! I still want to know the answer to your question, though:

Why isn’t there an automatic contructor that does this?