# Type annotations in struct vs. struct fields

**URL:** https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530
**Category:** General Usage
**Created:** [April 25, 2019, 8:32pm UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530 "2019-04-25T20:32:35Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![joemiller](https://avatars.discourse-cdn.com/v4/letter/j/258eb7/32.png) [@joemiller](https://discourse.julialang.org/u/joemiller)
#### Post date: [April 25, 2019, 8:32pm UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530/1 "2019-04-25T20:32:35Z")

</div>

Hey everyone. I’ve been curious for a while about the performance implications and behavior of the following types of structs:

```julia
struct MyType1{Int64,Float64}
    a::Int64
    b::Float64
end

```

versus

```julia
struct MyType2{T1<:Int64,T2<:Float64}
    a::T1
    b::T2
end

```

Also,

```julia
struct MyType3{Int64,Float64}
    a
    b
end

```

It seems like `MyType1` and `MyType2` are identical in all respects; is this right? Also, evidently I can’t construct an instance of type MyType3, which I didn’t expect (“no method matching” error).

It also raises a question about the relationship between the typed elements in a field and the type annotation of the struct. What is the default behavior here? For example,

```r
struct MyBizarreType{Int64,Float64}
    a::Float64
    b::Int64
end

dump(MyBizarreType(1,1.0))
# MyBizarreType{Float64,Int64}
# a: Int64 1
# b: Float64 1.0

dump(MyBizarreType(1.0,1))
# MyBizarreType{Int64,Float64}
# a: Float64 1.0
# b: Int64 1

```

seems like it’s applying some non-obvious rules, which is puzzling especially in relation to the behavior in `MyType3`.

Thanks in advance for the help!

---

<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: [April 25, 2019, 9:18pm UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530/2 "2019-04-25T21:18:26Z")

</div>

No, `Type3` is not equivalent to the other two. You have to explicitly specify the type of fields in a struct, otherwise they are assumed to be of type `Any`. You can see this if you look at the output of `@code_warntype Type3(1, 2)`, which just gives `Any`. The parameters of the struct are just additional information on the specific instance of the type, but don’t have any special meaning regarding the types of the fields if you don’t specify that explicitly.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [April 25, 2019, 9:20pm UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530/3 "2019-04-25T21:20:08Z")

</div>

Actually, none of these definitions are doing what I suspect you think they’re doing. The annotations inside the `{}` block create type _variables_. The names of those variables are arbitrary–the fact that you’ve chosen the names “Int64” and “Float64” has no effect on the behavior of the code, and the fact that there happen to be other types with those same names also has no effect.

So, this definition:

```julia
julia> struct MyType1{Int64,Float64}
           a::Int64
           b::Float64
       end

```

is exactly the same as this definition:

```julia
julia> struct MyType1{T1, T2}
           a::T1
           b::T2
       end

```

you just happened to choose names that were the same as other, existing types.

With that in mind, your `MyType1` and `MyType2` are not equivalent, since only `MyType2` actually restricts the types of its parameters.

Hopefully this should make it more clear why `MyType3` doesn’t work. Since the type parameters are just variable names, we can change their names with no effect:

```julia
julia> struct MyType3{T1, T2}
         a
         b
       end

```

You can still construct an instance of this type, but you have to explicitly specify T1 and T2, since there’s no way for Julia to deduce them from the values of a and b:

```julia
julia> MyType3{Int, Int}("hello", π)
MyType3{Int64,Int64}("hello", π = 3.1415926535897...)

```

And this should hopefully also clarify why `MyBizarreType` is so weird. Again, you are introducing new type variables whose names are `Int64` and `Float64`, with no connection at all to any other meaning of those symbols. Try replacing them with `T1` and `T2` and the behavior should be more obvious.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 25, 2019, 9:30pm UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530/4 "2019-04-25T21:30:39Z")

</div>

Just as `a` and `b` are defining the fields of your structure in your examples, you can think of the things that go inside the curly braces in `struct MyType{...}` as defining fields _that define the type itself_. You can then use and refer to these “type fields” elsewhere in the definition.

That aside, the question you probably intended to ask is, given:

```julia
struct MyType4
    a::Int64
    b::Float64
end
struct MyType5{T1,T2}
    a::T1
    b::T2
end

```

Do `MyType4` and `MyType5{Int64, Float64}` behave and perform the same? The answer is yes, `MyType4` and `MyType5{Int64, Float64}` will perform and behave identically. But note that `MyType5` could be parameterized differently, allowing it to hold absolutely anything.

---

<div class="post-metadata">

### Author: ![joemiller](https://avatars.discourse-cdn.com/v4/letter/j/258eb7/32.png) [@joemiller](https://discourse.julialang.org/u/joemiller)
#### Post date: [April 26, 2019, 1:23am UTC](https://discourse.julialang.org/t/type-annotations-in-struct-vs-struct-fields/23530/5 "2019-04-26T01:23:39Z")

</div>

[rdeits](https://discourse.julialang.org/u/rdeits), thanks! That’s what I was missing.

[mbauman](https://discourse.julialang.org/u/mbauman), also good to know. I was under the impression that it’s necessary to do

```julia
struct MyType4{T1<:Int64,T2<:Float64}
    a::T1
    b::T2
end

```

to get all that type information into the struct for performance which seems clunky.
