Description
This bug makes it hard to work with converters with concept generic constraints, as any piece of code defining a generic converter with a concept generic constraint will compile very slowly even for trivial examples, once more than one type exists which satisfies the concept, and a proc with many overloads is called.
The compiler then goes on to recurse for a while through the following series of procs:
semexprs.nim(1737) tryExpr
semexprs.nim(2354) semExpr
semstmts.nim(1847) semStmtList
semexprs.nim(2261) semExpr
semexprs.nim(1827) semMagic
semexprs.nim(320) semIs
semexprs.nim(44) semExprWithType
semexprs.nim(2260) semExpr
semexprs.nim(776) semDirectOp
semexprs.nim(626) semOverloadedCallAnalyseEffects
semcall.nim(439) semOverloadedCall
semcall.nim(405) semOverloadedCall
semcall.nim(229) resolveOverloads
semcall.nim(91) pickBestCandidate
sigmatch.nim(2294) matches
sigmatch.nim(2250) matchesAux
sigmatch.nim(1997) paramTypesMatch
sigmatch.nim(1976) paramTypesMatchAux
sigmatch.nim(332) userConvMatch
sigmatch.nim(1015) typeRelImpl
sigmatch.nim(1538) typeRelImpl
sigmatch.nim(735) matchUserTypeClass
This snippet suffices to reproduce the slowdown:
# Those definitions just need to exist:
type
SomeConcept = concept c
# A slowdown is noticable, but less pronounced,
# when the ``is void`` is omitted.
someProc(c) is void
SomeObj = object
SomeOtherObj = object
SomeInterface = object
proc someProc(self: SomeObj) = discard
# Uncomment this for ~4x slowdown in compilation:
# proc someProc(self: SomeOtherObj) = discard
converter toInterface(x: SomeConcept): SomeInterface = discard
# Minimal code to reach the slowdown:
template offendingCallWithManyOverloads(x: untyped) =
# Use ``$`` here, for example, which has a large number
# of overloads (19 for this snippet). What proc we call
# here does not actually matter. The slowdown depends
# just on the number of overloads for that proc.
discard $x
# The argument does not matter.
offendingCallWithManyOverloads(0)
With the overload commented, the snippet takes 0.24 s
to compile on my machine, while uncommenting the overload brings the time up to 0.92 s
, giving a 3.8x slowdown in compilation. More calls to overloaded procs increase the slowdown, which makes compilation times for realistic modules very slow, with e.g. 32 calls to $
pushing compilation times to about half a minute.
Feel free to close this issue, as everything works for code of that form, it just takes a while to compile, making this less of a bug and more of a possibility for optimization.