internal compiler error: openArrayLoc #888

Closed
micklat opened this Issue Feb 9, 2014 · 5 comments

Projects

None yet

4 participants

@micklat
Contributor
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 https://github.com/micklat/NimBorg, 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
Contributor
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

type
  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) =
  PyErr_Print()
  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"
    Py_DECREF(o.p)
    o.p = nil

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

proc py_import*(name : cstring) : PPyRef =
  PyImport_ImportModule(name)

Py_Initialize()
let n = 100
let lx = new_list(0)
# compilation succeeds:
getattr(lx, "append")(to_py(1))
# compilation fails:
getattr(lx, "append")(1)
Py_Finalize()
@micklat
Contributor
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
@Varriount
Contributor

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
Contributor
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
Contributor
jangko commented Jan 4, 2016

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

type
  PyRef = object
  PPyRef* = ref PyRef

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

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

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

abc(1)
@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