# Promotion rules for custom structs

**URL:** <https://discourse.julialang.org/t/promotion-rules-for-custom-structs/50548>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 21, 2020, 5:54pm UTC](https://discourse.julialang.org/t/promotion-rules-for-custom-structs/50548 "2020-11-21T17:54:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![cadojo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cadojo/32/25328_2.png) [@cadojo](https://discourse.julialang.org/u/cadojo)\
**Post date:** [November 21, 2020, 5:54pm UTC](https://discourse.julialang.org/t/promotion-rules-for-custom-structs/50548/1 "2020-11-21T17:54:31Z")

</div>

I have a custom struct `Body` (shown below). For another struct, I’d like to be able to keep vectors of `Body` variables, and **I’d like to be able to promote** `Body{Float32}` to `Body{Float64}`, `Body{Float64}` to `Body{BigFloat}`, etc.

The following definition does run, but it still doesn’t allow for `Body` promotion.

```julia
julia> promote_rule(::Type{Body{A}}, ::Type{Body{B}}) where {A<:AbstractFloat, B<:AbstractFloat} = Body{promote_type(A, B)}

julia> b1 = Body(Float32.([1, 2, 3]u"m"), Float32.([1,2,3]u"m/s"), Float32(1u"kg"))

julia> b2 = Body(Float64.([1, 2, 3]u"m"), Float64.([1,2,3]u"m/s"), Float64(1u"kg"))

julia> promote(b1, b2)
ERROR: promotion of types Body{Float32} and Body{Float64} failed to change any arguments

```

Is what I’m trying to do possible?

**`Body` Definition:**

```julia
using Unitful
using StaticArrays

struct Body{F<:AbstractFloat}
   
    r̅::SVector{3, Unitful.Length{F}}
    v̅::SVector{3, Unitful.Velocity{F}}
    m::Unitful.Mass{F}

    function Body(r::R, v::V, m::M) where {
            T <: AbstractFloat, 
            R <: AbstractVector{Unitful.Length{T}}, 
            V <: AbstractVector{Unitful.Velocity{T}},
            M <: Unitful.Mass{T}
    }

        if length(r) ≢ length(v) ≢ 3
            error("The `Body` constructor requires 3 element vectors for position `r` and velocity `v`")
        else
            return new{T}(SVector{3}(T.(r)), SVector{3}(T.(v)), M(T(m)))
        end

    end

end

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [November 21, 2020, 6:05pm UTC](https://discourse.julialang.org/t/promotion-rules-for-custom-structs/50548/2 "2020-11-21T18:05:24Z")

</div>

You need to make sure, you actually overload `Base.promote_rule`. What you are doing is defining a new function locally, that just happens to be called `promote_rule`.
