# Ominous type instability

**URL:** https://discourse.julialang.org/t/ominous-type-instability/85169
**Category:** Performance
**Tags:** bug, code\_warntype, type-stability
**Created:** [August 2, 2022, 2:25pm UTC](https://discourse.julialang.org/t/ominous-type-instability/85169 "2022-08-02T14:25:28Z")
**Posts on this page:** 1
**Showing post:** 11

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [August 20, 2022, 3:46am UTC](https://discourse.julialang.org/t/ominous-type-instability/85169/11 "2022-08-20T03:46:06Z")

</div>

> [@arik](#):
>
> instable instability

This seems to be a known issue:

> <https://github.com/JuliaLang/julia/issues/45388>
>
> Hi there,
> 
> this issue was already discussed on \[discourse\](https://discourse.j…ulialang.org/t/need-help-with-incomprehensible-typeinference/81056). While we could gather some clarification, it couldn't be solved. Hence I raise it as an issue here.
> 
> I am the author of \[ExtensibleEffects.jl\](https://github.com/JuliaFunctional/ExtensibleEffects.jl) and \[TypeClasses.jl\](https://github.com/JuliaFunctional/TypeClasses.jl) and experience crucial performance difficulties due to bad type inference. As I got multiple requests from the community whether ExtensibleEffects.jl could be made fast, I want to tackle these problems. 
> 
> ExtensibleEffects.jl is an advanced functional package, hence please bear with me if the following example looks not understandable why you ever would like to do something like this. It is a minified version of the actual ExtensibleEffects code, and I am very sorry that I was not able to simplify it anyway further so far. At least it is reproducible and fits into an issue.
> 
> \# My Motivation
> \<details\>
> \<summary\>if you want to understand the motivation for the example, this might help\</summary\>
> \`\`\`julia
> using ExtensibleEffects
> using TypeClasses
> using Test
> 
> vector\_of\_eff\_of\_vector = map(x -\> noeffect(\[x\]), \[1, 20\])
> e1 = vector\_of\_eff\_of\_vector\[1\]
> e2 = vector\_of\_eff\_of\_vector\[2\]
> 
> \# some functional monadic helpers to work WITHIN the effects
> mygoal(e1, e2) = @syntax\_flatmap begin
> v1 = e1
> v2 = e2
> @pure \[v1; v2\]
> end
> \`\`\`
> \`\`\`julia
> julia\> mygoal(e1, e2)
> Eff(effectful=NoEffect{Vector{Int64}}(\[1, 20\]), length(cont)=0)
> 
> julia\> @inferred mygoal(e1, e2)
> ERROR: return type ExtensibleEffects.Eff{NoEffect{Vector{Int64}}, Tuple{}} does not match inferred return type ExtensibleEffects.Eff
> 
> julia\> @code\_warntype mygoal(e1, e2) 
> \# on the terminal this gives nice color output and will show that only the last step does not infer
> \`\`\`
> 
> The case boils down to something like the following
> \`\`\`julia
> function test\_fails(e1, e2)
> combine(v1, v2) = \[v1; v2\]
> curried\_combine(v1) = v2 -\> combine(v1, v2)
>     
> e1\_f = map(curried\_combine, e1)
> f\_flatmap(f) = TypeClasses.map(v2 -\> f(v2), e2)
> TypeClasses.flatmap(f\_flatmap, e1\_f)
> end
> 
> @inferred test\_fails(e1, e2) # same as before
> \# ERROR: return type ExtensibleEffects.Eff{NoEffect{Vector{Int64}}, Tuple{}} does not match inferred return type ExtensibleEffects.Eff
> @code\_warntype test\_fails(e1, e2) # same as before
> \`\`\`
> If this could be stabilized, much is gained for ExtensibleEffects.jl
> \</details\>
> 
> \# Same code, two execution orders, one fails, the other infers
> 
> Here the one which works
> \`\`\`julia
> using ExtensibleEffects
> using TypeClasses
> using Test
> 
> vector\_of\_eff\_of\_vector = map(x -\> noeffect(\[x\]), \[1, 20\])
> e1 = vector\_of\_eff\_of\_vector\[1\]
> e2 = vector\_of\_eff\_of\_vector\[2\]
> 
> function prepare\_test(e1, e2)
> combine(v1, v2) = \[v1; v2\]
> curried\_combine(v1) = v2 -\> combine(v1, v2)
>     
> e1\_f = map(curried\_combine, e1)
> f\_flatmap(f) = TypeClasses.map(v2 -\> f(v2), e2)
> f\_flatmap, e1\_f
> end
> 
> f\_flatmap, e1\_f = prepare\_test(e1, e2)
> @inferred TypeClasses.flatmap(f\_flatmap, e1\_f) # infers perfectly
> 
> function test\_infers(e1, e2)
> f\_flatmap, e1\_f = prepare\_test(e1, e2)
> TypeClasses.flatmap(f\_flatmap, e1\_f)
> end
> 
> @inferred test\_infers(e1, e2) # infers perfectly
> \`\`\`
> 
> And here the one which fails
> \`\`\`julia
> using ExtensibleEffects
> using TypeClasses
> using Test
> 
> vector\_of\_eff\_of\_vector = map(x -\> noeffect(\[x\]), \[1, 20\])
> e1 = vector\_of\_eff\_of\_vector\[1\]
> e2 = vector\_of\_eff\_of\_vector\[2\]
> 
> function prepare\_test(e1, e2)
> combine(v1, v2) = \[v1; v2\]
> curried\_combine(v1) = v2 -\> combine(v1, v2)
>     
> e1\_f = map(curried\_combine, e1)
> f\_flatmap(f) = TypeClasses.map(v2 -\> f(v2), e2)
> f\_flatmap, e1\_f
> end
> 
> function test\_infers(e1, e2)
> f\_flatmap, e1\_f = prepare\_test(e1, e2)
> TypeClasses.flatmap(f\_flatmap, e1\_f)
> end
> 
> @inferred test\_infers(e1, e2)
> \# ERROR: return type ExtensibleEffects.Eff{NoEffect{Vector{Int64}}, Tuple{}} does not match inferred return type ExtensibleEffects.Eff
> 
> f\_flatmap, e1\_f = prepare\_test(e1, e2)
> @inferred TypeClasses.flatmap(f\_flatmap, e1\_f) 
> \# ERROR: return type ExtensibleEffects.Eff{NoEffect{Vector{Int64}}, Tuple{}} does not match inferred return type ExtensibleEffects.Eff
> \`\`\`
> 
> It seems that a top-level call to \`TypeClasses.flatmap\` at the right place informs the compiler about things it usually does not have available (but should have available).
> 
> \------------
> 
> This drives me crazy :smile: I feel like a little child: 10 years programming experience are not enough to solve this on my own, I am depending on you deep core Julia developers and hope someone recognizes what is going on here.
> 
> \<details\>
> \<summary\>(tested on Julia 1.7.1 and Julia 1.8.0-beta3.4)\</summary\>
> \`\`\`julia
> julia\> versioninfo()
> Julia Version 1.7.1
> Commit ac5cc99908 (2021-12-22 19:35 UTC)
> Platform Info:
> OS: Linux (x86\_64-pc-linux-gnu)
> CPU: Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
> WORD\_SIZE: 64
> LIBM: libopenlibm
> LLVM: libLLVM-12.0.1 (ORCJIT, icelake-client)
> \`\`\`
> 
> \`\`\`julia
> julia\> versioninfo()
> Julia Version 1.8.0-beta3.4
> Commit a4e69c5088 (2022-05-20 09:32 UTC)
> Platform Info:
> OS: Linux (x86\_64-unknown-linux-gnu)
> CPU: 8 × Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
> WORD\_SIZE: 64
> LIBM: libopenlibm
> LLVM: libLLVM-13.0.1 (ORCJIT, icelake-client)
> Threads: 1 on 8 virtual cores
> Environment:
> LD\_LIBRARY\_PATH = /run/opengl-driver/lib:/run/opengl-driver-32/lib:/usr/lib:/usr/lib32:/nix/store/0fih0yvy9lwxkaaci06gw0x1f5a5aqld-sane-config/lib/sane
> \`\`\`
> \</details\>

> <https://github.com/JuliaLang/julia/issues/35800>
>
> Using Julia master (newer than 301db971daaeeb627ba768375538e6e7ff36d215), the fo…llowing does not infer the correct type (see also the discussion in #34048):
> \`\`\`julia
> using Test, LinearAlgebra
> \# @inferred mapreduce(norm, +, \[rand(1)\]);
> @inferred mapreduce(norm, +, \[rand(1)\]; init = 0.);
> \`\`\`
> Note that the third line works if you comment out the second line (start from a fresh Julia session), which makes testing this issue difficult.

> [@Why is this expression type unstable?](https://discourse.julialang.org/t/why-is-this-expression-type-unstable/80648):
>
> I have the following function, and I’ve written two return statements which are identical in an input-output sense, but they have different syntax and mechanics. I like the format of the former statement because it’s a generator, and there’s less syntax there so it’s clearer. But the former return statement is not type stable, until I run the second return statement! The latter return statement is always type stable. function lagrangepolynomial(x::AbstractVector, y::AbstractVector, z::Number = …

> [@Need help with incomprehensible typeinference](https://discourse.julialang.org/t/need-help-with-incomprehensible-typeinference/81056):
>
> Hi there, I am the author of [ExtensibleEffects.jl](https://github.com/JuliaFunctional/ExtensibleEffects.jl). This is an advanced functional package, hence please bear with me if the following example looks totally alien and not understandable why you ever would like to do something like this. It is a minified version of the actual ExtensibleEffects code, and I am very sorry that I was not able to simplify it anyway further so far. At least it is reproducible and fits into a discourse issue, hence I want to ask for help. The Goal using ExtensibleEffe…

---

_[View the full topic](https://discourse.julialang.org/t/ominous-type-instability/85169)._
