# I am surprised that promotion does not occur here

**URL:** https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133
**Category:** New to Julia
**Created:** [March 14, 2021, 4:08pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133 "2021-03-14T16:08:49Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 4:08pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/1 "2021-03-14T16:08:49Z")

</div>

Consider the following:

```julia
julia> [[1,2,3]//3,[1,2,3]*Int128(1)]
2-element Array{Array{T,1} where T,1}:
 Rational{Int64}[1//3, 2//3, 1//1]
 Int128[1, 2, 3]

```

Julia cannot compute the type of the combined array, but Julia is able to compute

```julia
julia> promote_type(Rational{Int64},Int128)
Rational{Int128}

```

but curiously this does not carry over to arrays:

```julia
julia> promote_type(Vector{Rational{Int64}},Vector{Int128})
Array{T,1} where T

```

Though this works in a slightly different case:

```julia
julia> promote_type(Vector{Int64},Vector{Int128})
Array{Int128,1}

```

I am surprised and went through the source to find what happens. The stuff happens in `typejoin`,  
which is very complicated and does not seem to use promotion of `eltype`. Can someone explain that to me, and why the simpler case is handled but not the more complicated one?

---

<div class="post-metadata">

### Author: ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)
#### Post date: [March 14, 2021, 4:17pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/2 "2021-03-14T16:17:47Z")

</div>

Seems like it should happen, given that

```julia
julia> [[1,2,3]//3,[1,2,3]*0.5]
2-element Vector{Vector{Float64}}:
 [0.3333333333333333, 0.6666666666666666, 1.0]
 [0.5, 1.0, 1.5]

```

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 4:30pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/3 "2021-03-14T16:30:04Z")

</div>

Actually my question is motivated by a problem I have in my code, with different types. I am expecting that when I have defined (or Julia has defined) `T=promote_type(T1,T2)` (and a `promote_rule` also) then elements in a mixed vector of `T1` and `T2` are promoted to `T` (this happens) and also that mixed `Vector{T1}` and `Vector{T2}` in a `Vector` are promoted to `Vector{T}` (this is very inconsistent, depending on `T1` and `T2`).

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [March 14, 2021, 4:40pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/4 "2021-03-14T16:40:50Z")

</div>

yeah no that should not be expected:

```julia
julia> promote_type(BigInt, Float32)
BigFloat

julia> promote_rule(Vector{BigInt}, Vector{Float32})
Vector{T} where T (alias for Array{T, 1} where T)

```

Basically I think 1) it’s not clear there’s a definitive rule regarding how far should Julia go to promote different nested types such that it appears to be natural and “completed” to our eyes. 2) even if there is a mathematically sound rule, it may be too much cost to \*always do it.

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 4:46pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/5 "2021-03-14T16:46:14Z")

</div>

Ok but then can anyone document what happens? Which examples work and which do not?

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [March 14, 2021, 4:49pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/6 "2021-03-14T16:49:21Z")

</div>

I **believe** this is an implementation detail (depending on heuristics). (think of trying to document when will a function be inlined)

Overall, there is never a type-promotion covariance(?) promised by Julia in the docs anywhere to begin with, so there’s no need to document a non-feature.

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 4:51pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/7 "2021-03-14T16:51:39Z")

</div>

I had in my mind that Julia should have something like

`promote_rule(Array{T},Array{T1})=Array{promote_type(T,T1)}`

but perhaps it does not make sense…

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [March 14, 2021, 4:55pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/8 "2021-03-14T16:55:48Z")

</div>

(sorry my previous example post had a bug that I used `promote_rule` in both places)

I would have imagined the same, maybe others would agree we should specialize on promote\_rule for `Array`s.

That mental model seem to work on `Real` subtypes except for when you mix `BigInt` and `Float**` together.

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [March 14, 2021, 5:29pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/9 "2021-03-14T17:29:37Z")

</div>

I think it’s the right thing to not promote container types.

```julia
julia> [[1,2,3]//3,[1,2,3]*0.5]
2-element Vector{Vector{Float64}}:
 [0.3333333333333333, 0.6666666666666666, 1.0]
 [0.5, 1.0, 1.5]

```

is fine because it’s the result of a literal evaluation, but let’s put it slightly differently:

```julia
julia> vec_rat = [1,2,3]//3;

julia> vec_float = [1,2,3]*0.5;

julia> vecs = [vec_rat, vec_float]
2-element Array{Array{Float64,1},1}:
 [0.3333333333333333, 0.6666666666666666, 1.0]
 [0.5, 1.0, 1.5]

```

Do you spot a problem?

Now `vecs[2]` is bound to `vec_float` but `vecs[1]` and `vec_rat` are completely decoupled. WTH?

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 5:35pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/10 "2021-03-14T17:35:04Z")

</div>

I don’t spot a problem since `promote_type(Rational{Int},Float64)==Float64`. I wish this would happen consistently. Do you spot a problem?

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [March 14, 2021, 5:48pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/11 "2021-03-14T17:48:49Z")

</div>

The problem is, when one writes `c = [a, b]`, is it fine if `c[1] !== a` or `c[2] !== b` when `a` and `b` are mutable?

---

<div class="post-metadata">

### Author: ![Jean\_Michel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jean_michel/32/8282_2.png) [@Jean\_Michel](https://discourse.julialang.org/u/Jean_Michel)
#### Post date: [March 14, 2021, 5:56pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/12 "2021-03-14T17:56:05Z")

</div>

Well, we saw some examples where the promotion happened. I would think there is no problem  
when `a` and `b` are arrays; or otherwise one should prohibit the examples which worked above.  
For me the problem is the inconsistency.

---

<div class="post-metadata">

### Author: ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)
#### Post date: [March 14, 2021, 7:13pm UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/13 "2021-03-14T19:13:33Z")

</div>

Inconsistency is indeed a problem.  
I’d just ignore the existence of type promotion for arrays of arrays and write my own function for the specific case I need, though.

---

<div class="post-metadata">

### Author: ![path-doc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/path-doc/32/19183_2.png) [@path-doc](https://discourse.julialang.org/u/path-doc)
#### Post date: [March 15, 2021, 12:23am UTC](https://discourse.julialang.org/t/i-am-surprised-that-promotion-does-not-occur-here/57133/14 "2021-03-15T00:23:38Z")

</div>

> [@Vasily\_Pisarev](#):
>
> !==

One could argue that the problem you highlight is a question of `!==` being too coarse a measure of equality for the case in hand.

According to the manual:

> **39.18 Be careful with type equality**  
> You generally want to use isa and \<: for testing types, not ==. Checking types for exact equality typically only makes sense when comparing to a known concrete type (e.g. T == Float64), or if you really, really know what you’re doing.
