Strange promote_rule()?

compared to promote_type(), promote_rule() seems to be asymmetric and wrong?

julia> promote_type(Float16, Float32)
Float32

julia> promote_type(Float32, Float16)
Float32

julia> promote_rule(Float16, Float32)    # why???
Union{}

julia> promote_rule(Float32, Float16)
Float32

julia> promote_rule(Float16, Float16)    # why???
Union{}

is it a bug?

No, you can read about it here: https://docs.julialang.org/en/v1/manual/conversion-and-promotion/#Defining-Promotion-Rules-1. In particular:

Also note that one does not need to define both promote_rule(::Type{A}, ::Type{B}) and promote_rule(::Type{B}, ::Type{A}) – the symmetry is implied by the way promote_rule is used in the promotion process.

2 Likes

In short, you define promote_rule but you use promote_type.

2 Likes

what does it mean???

does it mean that

julia> promote_rule(Float32, Float16)
Float32

is well defined.

but,

julia> promote_rule(Float16, Float32)    # why???
Union{}

is NOT defined, so a strange Union{} is returned???

You don’t want to use promote_rule here. Instead use promote_type.

The key is like Stefan said, types define promote_rule for one of the argument orders, and then you call promote_type (or simply promote) to get the type (or values) that result from the promotion. When Julia tries to figure out what a given promotion should be (via promote_type or promote) it tries promote_rule both ways for you and unions the result.

3 Likes

you don’t have to be aggressive. You can reason rule returning Union{} because

julia> Union{Float32, Union{}}
Float32
3 Likes

I was not aggressive … English is not my first language… may not express good enough :pray: