# Clarification of Abstract Type and Specialized Code

**URL:** <https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289>\
**Category:** General Usage\
**Created:** [August 29, 2021, 3:48pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289 "2021-08-29T15:48:06Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![anon60034542](https://avatars.discourse-cdn.com/v4/letter/a/90ced4/32.png) [@anon60034542](https://discourse.julialang.org/u/anon60034542)\
**Post date:** [August 29, 2021, 3:48pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/1 "2021-08-29T15:48:06Z")

</div>

In the performance tips, under [Annotate values taken from untyped locations](https://docs.julialang.org/en/v1/manual/performance-tips/#Annotate-values-taken-from-untyped-locations), it says:

> Type annotation will not enhance (and can actually hinder) performance if the type is **abstract** , or constructed at run-time. This is because the compiler cannot use the annotation to specialize the subsequent code, and the type-check itself takes time.

When it says the abstract, does it mean that this code will hinder performance?

```julia
abstract type Character end
struct SpaceMarine <: Character end

svetlana :: Character = SpaceMarine()

```

Would it be better to write:

```julia
svetlana = SpaceMarine()

```

Suppose if I were to expand my types:

```julia
abstract type Character end

abstract type Infantry <: Character
abstract type Medic <: Character

struct SpaceMarine <: Infantry end
struct SARC <: Medic end 

```

Without type annotations `svetlana` could be a `Medic` without throwing an error:

```julia
svetlana = SARC()

```

What if I want to keep `svetlana` within the `infantry` subtype without hindering performance, what is the recommended way of doing it?

---

<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:** [August 29, 2021, 3:53pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/2 "2021-08-29T15:53:24Z")

</div>

> [@anon60034542](#):
>
> `svetlana :: Character = SpaceMarine()`

This just does a `convert`, in this case, nothing happens. Variables in Julia doesn’t need type annotation, they are what they.

```julia
julia> function f()
           a::Integer = 3
           return a
       end
f (generic function with 1 method)

julia> @code_warntype f()
MethodInstance for f()
  from f() in Main at REPL[10]:1
Arguments
  #self#::Core.Const(f)
Locals
  a::Int64
Body::Int64
1 ─ %1 = Base.convert(Main.Integer, 3)::Core.Const(3)
│ (a = Core.typeassert(%1, Main.Integer))
└── return a::Core.Const(3)

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 29, 2021, 4:14pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/3 "2021-08-29T16:14:23Z")

</div>

> [@anon60034542](#):
>
> What if I want to keep `svetlana` within the `infantry` subtype without hindering performance, what is the recommended way of doing it?

In the hierarchy you’ve written, you can’t do that:

```julia
julia> convert(Infantry, svetlana)                                                       
ERROR: MethodError: Cannot `convert` an object of type SARC to an object of type Infantry
Closest candidates are:                                                                  
  convert(::Type{T}, ::T) where T at essentials.jl:218                                   
Stacktrace:                                                                              
 [1] top-level scope                                                                     
   @ REPL[6]:1                                                                           

```

Your hierarchy is this:

- Character
  - Infantry
    - SpaceMarine

  - Medic
    - SARC

A `SARC` here can never be an `Infantry`, as `SARC` is only a subtype of `Medic`, which is a subtype of `Character`.

* * *

What is meant by

> [@anon60034542](#):
>
> Type annotation will not enhance (and can actually hinder) performance if the type is **abstract** , or constructed at run-time.

is that when you have some untyped source (like the `Vector{Any}` in the example you linked) and annotate an element you get from it with an abstract type like `Character`, you don’t help the compiler with figuring out which methods to choose down the road when passing that element around, because it still has to check the _concrete runtime type_ for dispatch. In julia, all values have a concrete type which is used for dispatch. Abstract types are only used when defining methods, for restricting the types of arguments the subtypes of the annotated type - asserting an abstract type for a variable means inserting more type checks, which can hinder performance.

---

<div class="post-metadata">

**Author:** ![EmpressSvetlana](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empresssvetlana/32/29969_2.png) [@EmpressSvetlana](https://discourse.julialang.org/u/EmpressSvetlana)\
**Post date:** [October 15, 2021, 5:28pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/4 "2021-10-15T17:28:20Z")

</div>

> [@Sukera](#):
>
> asserting an abstract type for a variable means inserting more type checks, which can hinder performance.

You see, the confusing part is, in the documentation for [type annotations](https://docs.julialang.org/en/v1/manual/types/#Type-Declarations), it says differently.

> To provide extra type information to the compiler, which can then improve performance in some cases

If I were to do:

```julia
svetlana :: Character = SpaceMarine()

```

Is it correct to say, I’m **not** hindering performance, but I’m not helping it either? In other words, it doesn’t do anything other than indicate that `svetlana` is a type of `Character`?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 15, 2021, 5:38pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/5 "2021-10-15T17:38:20Z")

</div>

Ah yes, I can see how that may sound conflicting 🤔

The documentation is thinking of situations where a variable would be assigned a type unstable result, forcing the variable to have the `Union` as its type as well. In that case, asserting a type (either concrete or abstract) can indeed improve performance, because that can eliminate the union. If the asserted type is part of the union, this helps the compiler.

If however the type is `Any` or the asserted type is not part of the union, the compiler will not be able to make use of the information (it sees conflicting information after all), having to insert a dynamic call to the conversion method instead of just a static type check at compile time. This is the situation I was thinking of.

> [@EmpressSvetlana](#):
>
> If I were to do:
> 
> ```julia
> svetlana :: Character = SpaceMarine()
> 
> ```
> 
> Is it correct to say, I’m **not** hindering performance, but I’m not helping it either? In other words, it doesn’t do anything other than indicate that `svetlana` is a type of `Character` ?

In this specific case, yes, assuming `SpaceMarine()` is a type stable function. You’re not gaining anything when called functions are type stable, which we’re always striving for anyway. That’s why the manual says “_can_ improve performance” (emphasis mine), because in the vast majority of cases it probably won’t, but it’s not impossible either.

I haven’t checked, but I’m fairly certain that because `SpaceMarine` is already a concrete type and you’re asserting an abstract super type of that, the compiler may just ignore your assertion and tag the variable `SpaceMarine` anyway (provided nothing else with a different subtype of `Character` gets assigned to that variable).

---

<div class="post-metadata">

**Author:** ![EmpressSvetlana](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/empresssvetlana/32/29969_2.png) [@EmpressSvetlana](https://discourse.julialang.org/u/EmpressSvetlana)\
**Post date:** [October 15, 2021, 6:01pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/6 "2021-10-15T18:01:32Z")

</div>

Ah! Much appreciated.

If you’re striving to write clean maintainable code and want to include the type annotations, provided `SpaceMarine()` is a type stable function, it would be okay, correct? Much like type hints in Python.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 15, 2021, 6:06pm UTC](https://discourse.julialang.org/t/clarification-of-abstract-type-and-specialized-code/67289/7 "2021-10-15T18:06:05Z")

</div>

It doesn’t hurt, but it also won’t help further 🤷‍♂️

I’ve come to the understanding that if I need type annotations in long functions (such that the possibly typed arguments to the functions are not enough), I should write smaller/more composable functions since julia is kinda good at deciding when to inline and when not to inline. You’re of course free to have a different custom though.
