# Strange inference problems here

**URL:** <https://discourse.julialang.org/t/strange-inference-problems-here/37734>\
**Category:** General Usage\
**Tags:** parametric-types\
**Created:** [April 17, 2020, 4:48am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734 "2020-04-17T04:48:35Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [April 17, 2020, 4:48am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/1 "2020-04-17T04:48:35Z")

</div>

I’m seeing some weird behavior with respect to type inference. Here’s the code:

```julia
function SimpleGraph{T}(nv::Integer, ne::Integer; rng::AbstractRNG=GLOBAL_RNG) where {T<:Integer}
    tnv = T(nv)
    maxe = div(Int(nv) * (nv - 1), 2)
    @assert(ne <= maxe, "Maximum number of edges for this graph is $maxe")
    ne > div((2 * maxe), 3) && return complement(SimpleGraph(tnv, maxe - ne))
    g = SimpleGraph(tnv)
    while g.ne < ne
        source = rand(rng, one(T):tnv)
        dest = rand(rng, one(T):tnv)
        source != dest && add_edge!(g, source, dest)
    end
    return g
end
SimpleGraph(nv::T, ne::Integer; rng::AbstractRNG=GLOBAL_RNG) where {T<:Integer} =
    SimpleGraph{T}(nv, ne, rng=rng)

```

The problem comes in when I try to create a `SimpleGraph(10, 20, rng=MersenneTwister(1))`:

```julia
julia> @code_warntype SimpleGraphs.Graph(10,20, rng=MersenneTwister(1))
Variables                                                                                                                                             
  #unused#::Core.Compiler.Const(Core.var"#kw#Type"(), false)               
  @_2::NamedTuple{(:rng,),Tuple{MersenneTwister}}                          
  @_3::Type{SimpleGraph}                                                                                                                              
  nv::Int64                                                                                                                                           
  ne::Int64                                                                                                                                           
  rng::MersenneTwister                                                     
  @_7::MersenneTwister       
                                                                                                                                                      
Body::Any                                                                                                                                             
1 ─ %1 = Base.haskey(@_2, :rng)::Core.Compiler.Const(true, false)                                                                                    
│ %1                                                                                                                                          
│ %3 = Base.getindex(@_2, :rng)::MersenneTwister                                                                                                   
│ %4 = (%3 isa LightGraphs.SimpleGraphs.Generators.AbstractRNG)::Core.Compiler.Const(true, false)                                                  
│ %4
└── goto #3
2 ─ Core.Compiler.Const(:(%new(Core.TypeError, Symbol("keyword argument"), :rng, LightGraphs.SimpleGraphs.Generators.AbstractRNG, %3)), false)
└── Core.Compiler.Const(:(Core.throw(%7)), false)
3 ┄ (@_7 = %3)
─ goto #5
4 ─ Core.Compiler.Const(:(@_7 = LightGraphs.SimpleGraphs.Generators.GLOBAL_RNG), false)
5 ┄ (rng = @_7)
│ %13 = (:rng,)::Core.Compiler.Const((:rng,), false)
│ %14 = Core.apply_type(Core.NamedTuple, %13)::Core.Compiler.Const(NamedTuple{(:rng,),T} where T<:Tuple, false)
│ %15 = Base.structdiff(@_2, %14)::Core.Compiler.Const(NamedTuple(), false)
│ %16 = Base.pairs(%15)::Core.Compiler.Const(Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}(), false)
│ %17 = Base.isempty(%16)::Core.Compiler.Const(true, false)
│ %17
└── goto #7
6 ─ Core.Compiler.Const(:(Base.kwerr(@_2, @_3, nv, ne)), false)
7 ┄ %21 = LightGraphs.SimpleGraphs.Generators.:(var"#SimpleGraph#2")(rng, @_3, nv, ne)::Any
└── return %21

```

`SimpleGraph(10, 20)` infers correctly (no type warning). Also weird:

```julia
julia> @edit SimpleGraphs.Graph(10,20, rng=MersenneTwister(1))
ERROR: could not determine location of method definition
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] functionloc(::Method) at ./methodshow.jl:131
 [3] functionloc at ./methodshow.jl:141 [inlined]
 [4] edit(::Function, ::Any) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/InteractiveUtils/src/editless.jl:102
 [5] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/InteractiveUtils/src/macros.jl:15

```

Now, what’s even WEIRDER is that if I start my REPL session off with a `SimpleGraph(10, 20)`, subsequent `SimpleGraph(10, 20, rng=MersenneTwister(1))`s infer correctly.

This issue is causing new type inference problems in the package. I hope I’m just overlooking something trivial. Any ideas?

---

<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:** [April 17, 2020, 5:52am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/2 "2020-04-17T05:52:59Z")

</div>

Not sure about your case, but any time I see order-dependent inference issues, this comes to mind, which describes why some seemingly valid things in Julia won’t infer: [https://juliacomputing.com/blog/2017/05/15/inference-converage2.html](https://juliacomputing.com/blog/2017/05/15/inference-converage2.html)

It seems plausible its that since since you’ve got `SimpleGraphs` recursively calling itself, which is at least one of the conditions to get what’s described there.

If its really this, a possible workaround I think might be to add precompile statements that cause inference to go through things in the order that works, which you could do at least for some of the concrete types you care about.

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [April 17, 2020, 6:00am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/3 "2020-04-17T06:00:06Z")

</div>

A quick update: annotating the return type solves the problem. But this doesn’t happen for the almost identical `SimpleDiGraph` constructor.

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [April 17, 2020, 6:00am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/4 "2020-04-17T06:00:59Z")

</div>

There shouldn’t be any recursion here.

---

<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:** [April 17, 2020, 6:37am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/5 "2020-04-17T06:37:35Z")

</div>

I think there is, it looks like there’s at least one branch in your code above where `SimpleGraph{T}(...)` calls `SimpleGraph(...)` which calls `SimpleGraph{T}(...)` with the argument types being `(Int,Int)` in the first and last calls, so that’d be the part I’d be suspicious could be related to what’s decsribed in that blog post (but I don’t really know enough about this to be sure though).

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [April 17, 2020, 7:32am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/6 "2020-04-17T07:32:26Z")

</div>

sorry, I’m lost. Where is this branch?

---

<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:** [April 17, 2020, 8:39am UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/7 "2020-04-17T08:39:29Z")

</div>

Inside your `SimpleGraph{T}` function, you have a call to `SimpleGraph(...)` with two arguments (specifically in `complement(SimpleGraph(tnv, maxe - ne))`), and that in turn calls `SimpleGraph{T}` again.

You could try changing it to `complement(SimpleGraph{T}(tnv, maxe - ne))` (ie add a `{T}`, and maybe to the other call as well) so `SimpleGraph{T}` is only calling itself, which that post seems to suggest is better.

---

<div class="post-metadata">

**Author:** ![anon94023334](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@anon94023334](https://discourse.julialang.org/u/anon94023334)\
**Post date:** [April 17, 2020, 10:20pm UTC](https://discourse.julialang.org/t/strange-inference-problems-here/37734/8 "2020-04-17T22:20:19Z")

</div>

That was it, precisely. Thank you so much!
