internal compiler error: openArrayLoc #888

micklat opened this Issue Feb 9, 2014 · 5 comments


None yet

4 participants

micklat commented Feb 9, 2014

When compiling my little test program, I get this error:

Error: internal error: openArrayLoc: PPyRef

Steps to reproduce:
0. use the current nimrod devel (d87579f)

  1. clone, revision 6d2dfa
  2. cd NimBorg/test
  3. nimrod -r -p=../.. c test_mpl.nim

my system is ubuntu 12.04, with gcc 4.6.3.

micklat commented Feb 9, 2014

Here's shorter code that triggers the same error, extracted with some help from reactormonk. Notice the last 5 lines. The problem occurs if to_py is used as a converter, but not when it is used explicitly.

import python except expr

  PyRef = object {.inheritable, byref.} 
    p: PPyObject
  PPyRef* = ref PyRef

  EPyException = object of E_Base

# forward declarations
proc getattr*(o: PPyRef, name: cstring) : PPyRef

proc handle_error(s : string) =
  raise newException(EPyException, s)

proc check(p: PPyObject) : PPyObject =
  if p == nil: handle_error("check(nil)")
  result = p

proc check(x: int) : int =
  if x == -1: handle_error("check(-1)")
  result = x

converter to_PPyRef*(p: PPyObject) : PPyRef = 
  new result
  result.p = check(p)

proc new_list*(size: int): PPyRef = PyList_New(size)
proc new_tuple*(size: int): PPyRef = PyTuple_New(size)

converter to_py*(i: int) : PPyRef = PyInt_FromLong(int32(i))

proc to_tuple*(vals: openarray[PPyRef]): PPyRef = 
  result = new_tuple(len(vals))
  for i in 0..len(vals)-1:
    let p = vals[i].p
    discard check(PyTuple_SetItem(result.p, i, p))
    Py_INCREF(p) # PyTuple_SetItem steals refs, I don't want that

proc `()`*(f: PPyRef, args: varargs[PPyRef]): PPyRef {.discardable.} = 
  let args_tup = to_tuple(args)
  PyObject_CallObject(f.p, args_tup.p)

proc destroy(o: var PyRef) {.destructor.} =
  if o.p != nil:
    echo "decrefing"
    o.p = nil

proc getattr*(o: PPyRef, name: cstring) : PPyRef =
  result = to_PPyRef(PyObject_GetAttrString(o.p, name))

proc py_import*(name : cstring) : PPyRef =

let n = 100
let lx = new_list(0)
# compilation succeeds:
getattr(lx, "append")(to_py(1))
# compilation fails:
getattr(lx, "append")(1)
micklat commented Feb 10, 2014

another way to avoid this bug is replace "varargs[PPyRef]" with "varargs[PPyRef,to_py]" and additionally define:

proc to_py*(x: PPyRef): PPyRef = x

I've noticed that many of your problems involve interfacing with CPython using its extension API . Wouldn't it be better to use Cffi or CTypes? That way whatever you are trying to develop will also work on other Python implementations (such as PyPy)

micklat commented Feb 10, 2014

Varriount: thanks for your suggestion. This issue's comments is probably not the right place to discuss this question. Please mail me at biosap at gmail.

jangko commented Jan 4, 2016

this is the shorter code to reproduce the bug without any dependencies.

  PyRef = object
  PPyRef* = ref PyRef

converter to_py*(i: int) : PPyRef = nil

proc to_tuple*(vals: openarray[PPyRef]): PPyRef = 

proc abc(args: varargs[PPyRef]): PPyRef {.discardable.} = 
  let args_tup = to_tuple(args)

@Araq Araq added the Crash label May 31, 2016
@Araq Araq added a commit that closed this issue Jul 19, 2016
@Araq Araq fixes #888 d4573f1
@Araq Araq closed this in d4573f1 Jul 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment