# Why can't this named tuple be converted to a supertype?

**URL:** <https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 16, 2022, 7:10am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329 "2022-11-16T07:10:33Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)\
**Post date:** [November 16, 2022, 7:10am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/1 "2022-11-16T07:10:33Z")

</div>

In the following two somewhat similar chunks of code the first generates an error, the other does not. Any ideas about why?

```julia
using DataFrames, Dates

NT1 = NamedTuple{(:DFPrecalc,:VPrecalc), Tuple{DataFrame,S}} where S

nt1 = (DFPrecalc = DataFrame(:A => [1]), VPrecalc = [Dates.today()])

cv1 = convert(NT1, nt1)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] convert(#unused#::Type{NamedTuple{(:DFPrecalc, :VPrecalc), Tuple{DataFrame, S}} where S}, nt::NamedTuple{(:DFPrecalc, :VPrecalc), Tuple{DataFrame, Vector{Date}}})
   @ Base .\namedtuple.jl:151
 [2] top-level scope
   @ REPL[4]:1

NT2 = NamedTuple{(:A,:B), Tuple{Int,Vector{T}}} where T

nt2 = (A = 1, B = [1])

cv2 = convert(NT2, nt2)
(A = 1, B = [1])

```

After looking at the comments and making some mistakes I realized that the problem is that the parameter S is representing a Vector. So if the second example is modified to have the parameter S to represent the vector and not the eltype of the vector the code does not work, as in the first example. This is shown below.

```julia
NT3 = NamedTuple{(:A,:B), Tuple{Int,S}} where S

nt3 = (A = 1, B = [1])

cv3 = convert(NT3, nt3)
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] convert(#unused#::Type{NamedTuple{(:A, :B), Tuple{Int64, T}} where T}, nt::NamedTuple{(:A, :B), Tuple{Int64, Vector{Int64}}})
   @ Base .\namedtuple.jl:151
 [2] top-level scope
   @ REPL[32]:1

```

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 16, 2022, 8:13am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/2 "2022-11-16T08:13:43Z")

</div>

This looks like a bug to me. Smaller demonstration:

```julia
julia> convert(@NamedTuple{a::Vector{S}} where S, (; a=[1]))
(a = [1],)

julia> convert(@NamedTuple{a::S} where S, (; a=1))
ERROR: UndefVarError: T not defined
Stacktrace:
 [1] convert(#unused#::Type{NamedTuple{(:a,), Tuple{S}} where S}, nt::NamedTuple{(:a,), Tuple{Int64}})
   @ Base ./namedtuple.jl:152
 [2] top-level scope
   @ REPL[71]:1

```

You might want to file an issue.

---

<div class="post-metadata">

**Author:** ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)\
**Post date:** [November 16, 2022, 8:37am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/3 "2022-11-16T08:37:02Z")

</div>

This works:

```julia
julia> convert(@NamedTuple{a::S where S}, (; a=1))
NamedTuple{(:a,), Tuple{Any}}((1,))

```

I think you just accidentally put the `where S` in the wrong “scope”. That is, it’s the inner `Tuple` that is parameterized by `S`, not the `NamedTuple`

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 16, 2022, 9:01am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/4 "2022-11-16T09:01:29Z")

</div>

I think both should work, and putting `where` on the outside is often required to reference the type parameter. Here’s an example where you have to put `where S` as in OP’s code:

```julia
julia> (a=[1], b=1) isa (@NamedTuple{a::Vector{S}, b::S} where S)
true

julia> (a=[1], b=1.0) isa (@NamedTuple{a::Vector{S}, b::S} where S)
false

```

---

<div class="post-metadata">

**Author:** ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)\
**Post date:** [November 16, 2022, 9:08am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/5 "2022-11-16T09:08:22Z")

</div>

Yes, you might be right.

---

<div class="post-metadata">

**Author:** ![jakobnissen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobnissen/32/13477_2.png) [@jakobnissen](https://discourse.julialang.org/u/jakobnissen)\
**Post date:** [November 16, 2022, 9:15am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/6 "2022-11-16T09:15:41Z")

</div>

Wait, I think I might be confused. As far as I understand, it’s the same as the following example:

```julia
julia> convert(
           NamedTuple{(:a,), Tuple{S}} where S,
           (;a=1)
       )
ERROR: UndefVarError: T not defined

```

However, it’s legitimately unspecified what it’s supposed to convert into. `NamedTuple{(:a,), Tuple{S}} where S` is not a concrete type.

The other example, namely this:

```julia
julia> convert(
           NamedTuple{(:a,), Tuple{Vector{S}}} where S,
           (;a=[1])
       )
(a = [1],)

```

Is somewhat different. Here, `NamedTuple{(:a,), Tuple{Vector{S}}} where S` is not a concrete type either, but the input type `(a = [1],)` is a subtype of the target unionall-type, so it’s obvious it can just return the input.

Edit: Ah, but in the first example, the input is also an instance of the type…

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 16, 2022, 9:35am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/7 "2022-11-16T09:35:17Z")

</div>

Indeed I’m not sure the original code makes sense, it’s like doing `convert(Real, 1)`, which does nothing since `Int` is already `Real`. @Soldalma maybe you could clarify what the end goal is? Note that in Julia every value has a concrete type and you cannot “remove” it by converting to an abstract type.

But whatever the goal, it seems to me this has uncovered a bug.

---

<div class="post-metadata">

**Author:** ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)\
**Post date:** [November 16, 2022, 12:16pm UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/8 "2022-11-16T12:16:19Z")

</div>

I poosted some new cases in the original post.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 17, 2022, 8:51am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/9 "2022-11-17T08:51:31Z")

</div>

I filed an issue here: [convert on named tuple can give "T not defined" error · Issue #47604 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/47604)

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 17, 2022, 8:52am UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/10 "2022-11-17T08:52:56Z")

</div>

@Soldalma it’s not clear what you are trying to do. It doesn’t make sense to do `convert(NT3, nt3)` because `nt3` is already an `NT3`: the value `nt3` has concrete type `NamedTuple{(:A, :B), Tuple{Int64, Vector{Int64}}}` and this concrete type is already a subtype of `NamedTuple{(:A,:B), Tuple{Int,S}} where S`:

```julia
julia> nt3 = (A = 1, B = [1]);

julia> nt3 isa (NamedTuple{(:A,:B), Tuple{Int,S}} where S)
true

```

so there is nothing to convert. It seems you found a bug, but maybe this bug should not really affect you because you don’t need this `convert` call anyway.

---

<div class="post-metadata">

**Author:** ![Soldalma](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soldalma/32/29388_2.png) [@Soldalma](https://discourse.julialang.org/u/Soldalma)\
**Post date:** [November 18, 2022, 12:48pm UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/11 "2022-11-18T12:48:01Z")

</div>

Well, if there was nothing to convert my program would not crash. I spent many hours on this and finally fixed the problem switching from a named tuple to a struct.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [November 18, 2022, 2:03pm UTC](https://discourse.julialang.org/t/why-cant-this-named-tuple-be-converted-to-a-supertype/90329/12 "2022-11-18T14:03:43Z")

</div>

By crash you mean the `ERROR: UndefVarError: T not defined`?

Anyway there is really nothing to convert here:

```julia
NT3 = NamedTuple{(:A,:B), Tuple{Int,S}} where S
nt3 = (A = 1, B = [1])

julia> nt3 isa NT3
true

```

As you can see the `nt3` value is already a `NT3`. Of course `NT3` is not the concrete type of `nt3` (that’s impossible, a value cannot have an abstract type like `NT3` as concrete type) but it’s a supertype of the concrete type. Really `nt3` is as much `NT3` as possible, you cannot make it “more NT3”!

It’s like the value `1.0` is a `Float64` (concrete type) but it’s also a `Real` (abstract supertype of `Float64`). You cannot make a value that is “more `Real`” than 1.0.
