# Cannot use parametric type within function body

**URL:** <https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224>\
**Category:** New to Julia\
**Tags:** parametric-types\
**Created:** [August 30, 2019, 11:36pm UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224 "2019-08-30T23:36:52Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 30, 2019, 11:36pm UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/1 "2019-08-30T23:36:52Z")

</div>

Hello, guys!

I’m very confused about parametric typing.

I’ve reduced my problem to a minimal working example:

```julia
using LinearAlgebra

function alt(x::Vector{Symmetric{T}}) where {T <: Real}
    return T
end

alt(Vector{Symmetric{Float64}}(undef, 1))

```

When I try to run this function, it errors out saying that T is undefined!

However, any of these other alternatives work:

```julia
function alt(x::Symmetric{T}) where {T <: Real}
    return T
end

function alt(x::Union{Symmetric{T}, Nothing}) where {T <: Real}
    return T
end

```

And the funny thing is that the parametric type definition works, because the method is correctly dispatched; I can even `Juno.@enter` into it and run the function up to the line that tries to access the parametric type.

What am I missing here? ☹

EDIT: Just adding here that this was tested with Julia 1.2.0 and Julia 1.1.1.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [August 31, 2019, 12:14am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/2 "2019-08-31T00:14:22Z")

</div>

To be a full mwe you should add `using LinearAlgebra` and define a test Vector of Symmetric matrix, so we don’t all have to do that.

But without testing it, you probably need another `<:`

```julia
function alt(x::Vector{<:Symmetric{T}}) where {T <: Real}
    return T
end

```

---

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 31, 2019, 12:23am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/3 "2019-08-31T00:23:47Z")

</div>

Thanks for answering!

I already edited the original post.

Your suggestion however, didn’t seem to work:

```julia
julia> using LinearAlgebra

julia> function alt(x::Vector{<: Symmetric{T}}) where {T <: Real}
           return T
       end
alt (generic function with 1 method)

julia> alt(Vector{Symmetric{Float64}}(undef, 1))
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] alt(::Array{Symmetric{Float64,S} where S<:(AbstractArray{#s617,2} where #s617<:Float64),1}) at ./REPL[2]:2
 [2] top-level scope at REPL[3]:1

```

I would like to note that the function I wrote works and is correctly dispatched: the only problem occurs upon using the parametric type `T` within the body.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [August 31, 2019, 12:35am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/4 "2019-08-31T00:35:59Z")

</div>

Try it with an actual vector of Symmetric 🙂

---

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 31, 2019, 12:48am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/5 "2019-08-31T00:48:02Z")

</div>

Thank you!

It actually works, but that’s not so good as it only means I don’t have a minimal working example ☹  
I was making my function types parametric, and had this problem with the following function:

My actual function is this

```julia
function smoother(F::Matrix{RT},
                  G::Matrix{RT},
                  a::Vector{Vector{RT}},
                  R::Vector{Symmetric{RT}},
                  m::Vector{Vector{RT}},
                  C::Vector{Symmetric{RT}}) where {RT <: Real}

    n, p = dlm_dimension(F, G)
    T = size(R, 1)

    s = Vector{Vector{RT}}(undef, T)
    S = Vector{Symmetric{RT}}(undef, T)

    s[T] = m[T]
    S[T] = C[T]

    for t = T-1:-1:1
        B = C[t] * G' * inv(R[t+1])
        s[t] = m[t] + B * (s[t+1] - a[t+1])
        S[t] = C[t] - Symmetric(B * (R[t+1] - S[t+1]) * B')
    end

    return s, S
end

```

As it is, it doesn’t work because it complains RT is undefined.  
If I change the Vector{Symmetric{RT}} into Vector{Symmetric{Float64}} the problem disappears. I am in fact calling it with filled up parameters (not undef as the previous mwe).

I can’t come up with a MWE ☹

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 31, 2019, 12:51am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/6 "2019-08-31T00:51:25Z")

</div>

I think the fact that it’s possible for `T` to be undefined even though dispatch selects the method stems from [https://github.com/JuliaLang/julia/pull/23117](https://github.com/JuliaLang/julia/pull/23117), but I don’t quite understand why `T` should be undefined in this case.

> [@Raf](#):
>
> Try it with an actual vector of Symmetric

But what’s the reason that it shouldn’t work for `Vector{Symmetric{Float64}}(undef, 1)`, or e.g. `Symmetric{Float64}[Symmetric(rand(3, 3))]`, a perfectly valid use case?

---

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 31, 2019, 12:53am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/7 "2019-08-31T00:53:51Z")

</div>

Hey @tkoolen, an interesting thing for me is that in my actual example (see post above yours), even though `RT` is undefined at runtime, I cannot 'compile a function that has the line

```julia
RT = typeof(F[1])

```

because it complains of conflict with the type parameter 😕

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 31, 2019, 1:04am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/8 "2019-08-31T01:04:44Z")

</div>

Although this appears to be an interesting corner case (at least to me), in your production code you should probably stop doing stuff like

```julia
S = Vector{Symmetric{RT}}(undef, T)

```

for performance reasons. Note that something like `Vector{Symmetric{Float64}}` is not a concrete type (it’s a `UnionAll`); `Symmetric` has a second type parameter. As a result, you’re incurring a performance cost due to dynamic dispatch any time you touch `S`. Additionally, your function only accepts stuff like `Vector{Symmetric{Float64}}(undef, 1)` (a `Vector` with non-concrete element type), not e.g. `[Symmetric(rand(3, 3))]` (which _does_ have concrete element type). So you’re inconveniencing callers of the function by forcing them to use a suboptimal storage type, which can be fixed by doing what @Raf proposed in [Cannot use parametric type within function body - #2 by Raf](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/2). Once that’s done, you could just use `S = similar(C, T)` to simultaneously clean up the code and fix the non-concrete element type issue for `S`.

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [August 31, 2019, 1:10am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/9 "2019-08-31T01:10:48Z")

</div>

I _think_ this is the same as: [Dispatching on the result of unwrap\_unionall seems weird?](https://discourse.julialang.org/t/dispatching-on-the-result-of-unwrap-unionall-seems-weird/25677) (which gives an even more MWE).

I’m no type-system expert, but to me it still kind of seems like a bug, e.g. in OPs first example, how can `T` simultaneously be undefined but also have been verified to be `T<:Real` ?

---

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 31, 2019, 1:15am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/10 "2019-08-31T01:15:30Z")

</div>

Thank you a ton!

Great performance tip and now I don’t have the problem of needing to access the type parameter manually anyway!

Though I am still confused about _why_ those original examples didn’t work.

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [August 31, 2019, 1:27am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/11 "2019-08-31T01:27:48Z")

</div>

> [@marius311](#):
>
> to me it still kind of seems like a bug

I agree, or at least I don’t understand why this would have to be the case. Not sure if your earlier `unwrap_unionall` post is exactly related though. Another related paradoxical corner case is [type parameter `UndefVarError` when dispatch matches `UnionAll` · Issue #29788 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/29788), but it doesn’t seem the case in the OP is an exact duplicate of that either. Specifically, in this case there does appear to be a unique correct value for `T`.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [August 31, 2019, 1:37am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/12 "2019-08-31T01:37:36Z")

</div>

It works when Symmetric doesn’t have missing parameters:

```julia
julia> alt(Vector{Symmetric{Float64,AbstractArray{Float64,2}}}(undef, 1))
Float64

julia> Vector{Symmetric{Float64}}(undef, 1)
1-element Array{Symmetric{Float64,S} where S<:(AbstractArray{#s623,2} where #s623<:Float64),
1}:
 #undef

julia> Vector{Symmetric{Float64,AbstractArray{Float64,2}}}(undef, 1)
1-element Array{Symmetric{Float64,AbstractArray{Float64,2}},1}:
 #undef

```

I’m not sure why they don’t both work, I agree it seems like a bug. There is a correct, know value for T here and S being parametric shouldn’t affect that.

Edit: the original example doesn’t work because you need the `<:` subtype operator when the contained type is parametric, as you are not matching any specific types, but some `Symmetric{T,S}` from all the possible `Symmetric{T,S}`. Or something like that.

---

<div class="post-metadata">

**Author:** ![vsart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vsart/32/501_2.png) [@vsart](https://discourse.julialang.org/u/vsart)\
**Post date:** [August 31, 2019, 1:50am UTC](https://discourse.julialang.org/t/cannot-use-parametric-type-within-function-body/28224/13 "2019-08-31T01:50:24Z")

</div>

After some private help from @tkoolen and as pointed out by @Raf in the post above, the problem lied with the fact that `Symmetric` has two parameters.

Upon using `Symmetric{RT, Matrix{RT}}` **everywhere** I was previously using just the `Symmetric{RT}`, not only did the type instabilities (shown by `@code_warntype` in my previous function) go away **but this change allowed me to access the value of `RT` within the function body**.

This means that the instability on the second type from `Symmetric` was not allowing the access on the parametric type `RT`.

This was quite a ride and I want to thank everyone for being so helpful!
