I was working on a project of mine when I realized I had written this, which 
the Nim compiler declared as GC-unsafe:
    
    
    type
      StateKind = enum
        stProcessing, stDone
      
      State = ref object
        case kind: StateKind
        of stProcessing:
          progress: int
        of stDone:
          discard
    
    let doneState = State(kind: stDone) # can't be const since both ref and 
case object
    
    proc main() =
      var state: State
      state = doneState # unsafe
    
    
    Run

I thought this must have been a solved problem, so I took a bit and remembered 
defaultSslContext from asynchttpclient and [the 
fix](https://github.com/nim-lang/Nim/commit/35d48765fb5f5b2f58bf6def54fd744492212097#diff-232b8586e82bf9dedf2b071ec6fd52aa)
 for the [same mistake I made now](https://github.com/nim-lang/Nim/issues/4998).

The fixed code looked a bit overkill, however.
    
    
    var doneStateVal {.threadvar.}: State
    template doneState*: State =
      if doneStateVal.isNil:
        doneStateVal = State(kind: stDone)
      doneStateVal
    
    
    Run

My question is, is there a simpler way to write this, or am I missing the point 
completely and applying the wrong fix?

I have quite a bit of these doneState variables so for the moment I devised a 
template.
    
    
    template defaultVar(name, value): untyped {.dirty.} =
      var `name val` {.gensym, threadvar.}: type(value)
      template `name`*: type(value) =
        if `name val`.isNil:
          `name val` = value
        `name val`
    
    
    Run

Reply via email to