Stack overflow in type inference... julia 1.9.0-DEV

Below is code that exhibits the problem, and if a character is changed, does not exhibit the problem. I removed 600+ lines of code, leaving about 163.

As noted above, splitting a certain printfmt call into two parts disappears the problem for this code. If the code below (which exhibits “Internal error: stack overflow in type inference…” problem) is in file toverflow5.jl, the sed command sed -e 's/if 1<2/if 1>2/' toverflow5.jl > toverflow3.jl will produce toverflow3.jl that runs without overflows.

Here is output from diff toverflow3.jl overflow5.jl:

<     if 1>2           # sed changes < to > for other version
---
>     if 1<2           # sed changes < to > for other version

Here is output from running the two programs. Script Running uses a command like julia-latest toverflow3.jl to run a program and a command like cat outP00 to print out file outP00. [Like splitting the print, writing to standard output instead of outP00 makes the problem go away.]

Running toverflow5
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
Internal error: stack overflow in type inference of (::toverflow.var"#findMore#7"{Array{Array{Float64, 1}, 1}, Array{Tuple, 1}, Array{Array{Float64, 1}, 1}, Array{Int32, 1}, Array{Int32, 1}, Array{Float64, 1}, Int64, Float64})(Int64).
This might be caused by recursion over very long tuples or argument lists.
RPtotals = Int32[0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0]
 contents:
( 0,  4,  1.41,  2.00, -0.31, 13.00, [13.00, 13.00, 13.00], [ 0.00,  0.00, -4.00], [ 1,  0,  4,  5]);
( 1,  4,  1.41,  2.00,  0.00, 13.00, [13.00, 13.00, 13.00], [ 0.00, -4.00,  0.00], [ 6,  2,  3,  7]);
( 2,  4,  1.41,  2.00,  0.00, 13.00, [13.00, 13.00, 13.00], [-4.00,  0.00,  0.00], [ 9,  8, 10, 11]);
toverflow5 done in ~ 9 seconds

Running toverflow3
RPtotals = Int32[0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0]
 contents:
( 0,  4,  1.41,  2.00, -0.31, 13.00, [13.00, 13.00, 13.00], [ 0.00,  0.00, -4.00], [ 1,  0,  4,  5]);
( 1,  4,  1.41,  2.00,  0.00, 13.00, [13.00, 13.00, 13.00], [ 0.00, -4.00,  0.00], [ 6,  2,  3,  7]);
( 2,  4,  1.41,  2.00,  0.00, 13.00, [13.00, 13.00, 13.00], [-4.00,  0.00,  0.00], [ 9,  8, 10, 11]);
toverflow3 done in ~ 2 seconds

Here is output from julia-latest <<< 'versioninfo()':

Julia Version 1.9.0-DEV.485
Commit 6e06132243 (2022-05-07 08:12 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: 4 × Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake)
  Threads: 1 on 4 virtual cores

Here is the toverflow5.jl program as cut down: [Note, see my later reply for slightly smaller version]

# -*- mode: julia; -*- 
# jiw - 10 May 2022 - exhibit (or not) errors like "Internal error:
# stack overflow in type inference of (::findRP.var"#findMore#11"
# {Array{Array{Float64, 1}, 1}, ... Int64, Float64})(Int64)."

module toverflow
using Formatting, LinearAlgebra

const eps=1e-6
mutable struct DataRP
    counts :: Array{Int} 
    csize  :: Int 
    sLo    :: Int
    sHi    :: Int
    RPnumber::Int
    fnumber:: Int
    Pfi; Cfi;
end
const DRP=DataRP(zeros(Int,200),200,0,0,0,0,0,0)
#------------------------------------------------------------
struct SDitem
    sd ::Float64
    j  ::Int32
    k  ::Int32
end
function Base.isless(a::SDitem, b::SDitem)
    a.sd < b.sd-eps || (abs(a.sd-b.sd)<eps && (a.j<b.j ||(a.j==b.j && a.k<b.k)))
end
#------------------------------------------------------------
struct CoItem
    co :: Int32
    ln :: Int32
end
function Base.zero(::Type{CoItem})
    CoItem(0,0)
end
#------------------------------------------------------------
function ccc3(A,B,C)
    v = (B-A)×(C-B)
    if v[3] > eps
        return true
    elseif v[3] < -eps
        return false
    elseif v[2] > eps
        return true
    elseif v[2] < -eps
        return false
    else
        return v[1] > 0
    end
end
#------------------------------------------------------------
function cosAngle3(A,B,C)
    p, q = A-B, C-B
    return min(1.0, max(-1.0, (p·q)/sqrt((p·p)*(q·q))))
end
#------------------------------------------------------------
function writeRP(points, v)::Nothing
    # writeRP is called by recursive findMore (and, in real code, by findPoly3)
    n = length(v)
    pp1 = 1;  pp2 = max(1+pp1, (n+4)÷3);  pp3 = max(1+pp2, (2n+3)÷3)
    p1, p2, p3 = points[v[pp1]], points[v[pp2]], points[v[pp3]]
    s0, s1, s2 = p1-points[v[2]], p1-p2, p3-p2
    s  = sqrt(s0⋅s0)
    r  = s/(2*sin(π/n))
    c = [13.,13.,13.]
    nnnv = s1×s2
    atra= [nnnv[2], -nnnv[1], 0.13]
    raxi = π/2 - acos(nnnv[3]/13)
    zaxi = 13.
    pz = [vj-1 for vj in v]

    # One long arg list vs two short ones in next few lines happens to
    # trigger "Internal error: stack overflow in type inference..."
    # message.  Besides splitting the prints, dropping `DRP.Pfi` from
    # the prints sidesteps the problem.

    if 1<2           # sed changes < to > for other version
        printfmt(DRP.Pfi, "({:2d}, {:2d}, {:5.2f}, {:5.2f}, {:5.2f}, {:5.2f}, [{:5.2f}, {:5.2f}, {:5.2f}], [{:5.2f}, {:5.2f}, {:5.2f}], ", DRP.RPnumber, n, r, s, raxi, zaxi, c[1],c[2],c[3], nnnv[1],nnnv[2],nnnv[3])
    else
        printfmt(DRP.Pfi, "({:2d}, {:2d}, {:5.2f}, {:5.2f}, {:5.2f}, {:5.2f}, ", DRP.RPnumber, n, r, s, raxi, zaxi)
        printfmt(DRP.Pfi, "[{:5.2f}, {:5.2f}, {:5.2f}], [{:5.2f}, {:5.2f}, {:5.2f}], ", c[1],c[2],c[3], nnnv[1],nnnv[2],nnnv[3])
    end
    printfmt(DRP.Pfi, "[$(join(["{:2d}" for i in pz], ", "))]);\n", pz...)
    DRP.RPnumber += 1
    return nothing
end
#------------------------------------------------------------
function findPoly3(points, maxVerts, cots)
    αlo, αhi = π/2-eps, π/2+eps
    RPcounts = zeros(Int32, maxVerts)
    v = zeros(Int32, maxVerts)
    p = [[0.,0.,0.] for j in 1:maxVerts]
    cSiz = length(cots)
    for v[1] in 1:cSiz
        p[1] = points[v[1]]
        for v[2] in cots[v[1]]
            # Changing > to == will double the number of outputs and number
            # of "Internal error: stack overflow in type inference" messages
            if v[2] > v[1]
                continue
            end
            p[2] = points[v[2]]
            for v[3] in cots[v[2]]
                p[3] = points[v[3]]
                if ccc3(p[1],p[2],p[3])
                    γ = cosAngle3(p[1],p[2],p[3])
                    α = acos(γ)
                    if αlo > α || α > αhi
                        continue
                    end
                    tVerts = 4
                    munnv = (p[1]-p[2])×(p[2]-p[3])
                    # Recursive function
                    function findMore(level)::Nothing
                        for v[level] in cots[v[level-1]]
                            p[level] = points[v[level]]
                            if v[level] < v[1] || !ccc3(p[level-2],p[level-1],p[level])
                                continue
                            end
                            γt = cosAngle3(p[level-2],p[level-1],p[level])
                            if abs(γ-γt) > eps
                                continue
                            end
                            unnv = (p[level-2]-p[level-1])×(p[level-1]-p[level])
                            if norm(unnv-munnv) > eps
                                continue
                            end
                            if level ≥ tVerts
                                RPcounts[tVerts] += 1
                                writeRP(points, v[1:tVerts])
                            else
                                findMore(level+1)
                            end
                        end
                        return nothing
                    end
                    findMore(4) # Start recursion
                end
            end
        end
    end
    return RPcounts
end
#------------------------------------------------------------
function toverR()
    ppoints = [
        [-1.0, -1.0, 0.0], [-1.0, 1.0, 0.0], [-1.0, 0.0, -1.0], [-1.0, 0.0, 1.0],
        [1.0, -1.0, 0.0],  [1.0, 1.0, 0.0],  [1.0, 0.0,-1.0],   [1.0, 0.0, 1.0],
        [0.0, -1.0, -1.0], [0.0, -1.0, 1.0], [0.0, 1.0, -1.0],  [0.0, 1.0, 1.0]];
    sds = [SDitem(4.0,1,2),SDitem(2.0,1,3),SDitem(2.0,1,4),SDitem(4.0,1,5),SDitem(8.0,1,6),SDitem(6.0,1,7),SDitem(6.0,1,8),SDitem(2.0,1,9),SDitem(2.0,1,10),SDitem(6.0,1,11),SDitem(6.0,1,12),SDitem(2.0,2,3),SDitem(2.0,2,4),SDitem(8.0,2,5),SDitem(4.0,2,6),SDitem(6.0,2,7),SDitem(6.0,2,8),SDitem(6.0,2,9),SDitem(6.0,2,10),SDitem(2.0,2,11),SDitem(2.0,2,12),SDitem(4.0,3,4),SDitem(6.0,3,5),SDitem(6.0,3,6),SDitem(4.0,3,7),SDitem(8.0,3,8),SDitem(2.0,3,9),SDitem(6.0,3,10),SDitem(2.0,3,11),SDitem(6.0,3,12),SDitem(6.0,4,5),SDitem(6.0,4,6),SDitem(8.0,4,7),SDitem(4.0,4,8),SDitem(6.0,4,9),SDitem(2.0,4,10),SDitem(6.0,4,11),SDitem(2.0,4,12),SDitem(4.0,5,6),SDitem(2.0,5,7),SDitem(2.0,5,8),SDitem(2.0,5,9),SDitem(2.0,5,10),SDitem(6.0,5,11),SDitem(6.0,5,12),SDitem(2.0,6,7),SDitem(2.0,6,8),SDitem(6.0,6,9),SDitem(6.0,6,10),SDitem(2.0,6,11),SDitem(2.0,6,12),SDitem(4.0,7,8),SDitem(2.0,7,9),SDitem(6.0,7,10),SDitem(2.0,7,11),SDitem(6.0,7,12),SDitem(6.0,8,9),SDitem(2.0,8,10),SDitem(6.0,8,11),SDitem(2.0,8,12),SDitem(4.0,9,10),SDitem(4.0,9,11),SDitem(8.0,9,12),SDitem(8.0,10,11),SDitem(4.0,10,12),SDitem(4.0,11,12)]
    DRP.Pfi = open("outP00", "w")
    DRP.RPnumber = 0
    cots = Tuple[(2, 5), (1, 6), (4, 7), (3, 8), (1, 6), (2, 5), (3, 8), (4, 7), (10, 11), (9, 12), (9, 12), (10, 11)]
    RPtotals = findPoly3(ppoints, 12, cots)
    close(DRP.Pfi)
    println("RPtotals = $RPtotals")
end
toverR()
end # module