# Compiling jitclass before first instantiation

**URL:** <https://numba.discourse.group/t/compiling-jitclass-before-first-instantiation/547>\
**Category:** Support: How do I do ...?\
**Created:** [February 22, 2021, 9:28pm UTC](https://numba.discourse.group/t/compiling-jitclass-before-first-instantiation/547 "2021-02-22T21:28:09Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomasgareau](https://yyz2.discourse-cdn.com/free1/user_avatar/numba.discourse.group/tomasgareau/32/242_2.png) [@tomasgareau](https://numba.discourse.group/u/tomasgareau)\
**Post date:** [February 22, 2021, 9:28pm UTC](https://numba.discourse.group/t/compiling-jitclass-before-first-instantiation/547/1 "2021-02-22T21:28:10Z")

</div>

Is there is `jitclass` equivalent to `generated_jit`? I’d like Numba to compile a class with a given type before I instantiate it for the first time (alternative approaches certainly welcome).

A minimally reproducible example would be:

```python
from functools import lru_cache

import numba as nb

class _DequeNode:
    """A wrapper around some item type.

    This class will be jitclassed in a factory function (so we can define 
    multiple types to wrap in a DequeNode).
    """
    def __init__ (self, item, left=None, right=None):
        self.item = item
        self.left = left
        self.right = right

@lru_cache(maxsize=32)
def _make_deque_node_class(item_type):
    """Returns a specialization of DequeNode for the given item type.

    The return value from this function is cached so that we can access
    the same type across multiple calls (plus we avoid compiling the same
    thing over and over).
    """
    node_type = nb.deferred_type()
    spec = [
        ("item", item_type),
        ("left", nb.types.optional(node_type)),
        ("right", nb.types.optional(node_type)),
    ]

    DequeNode = nb.experimental.jitclass(spec)(_DequeNode)
    node_type.define(DequeNode.class_type.instance_type)

    return DequeNode

@lru_cache(maxsize=32)
def make_deque(item_type):
    DequeNode = _make_deque_node_class(item_type)
    deque_spec = [
        ("first_node", nb.types.optional(DequeNode.class_type.instance_type)),
        ("last_node", nb.types.optional(DequeNode.class_type.instance_type)),
        ("len", nb.types.uint64),
    ]

    @nb.experimental.jitclass(deque_spec)
    class Deque:
        def __init__ (self):
            self.first_node = None
            self.last_node = None
            self.len = 0

        # ... rest of implementation of Deque, using the DequeNode above to
        # wrap any items added to the container

    return Deque

```

Running `make_deque` almost works:

```python
>>> Deque = make_deque(nb.types.int64)
>>> d = Deque()

RuntimeError: Failed in nopythyon mode pipeline (step: nopython mode backend)
LLVM IR parsing error
<string>:35:122: error: base element of getelementptr must be sized
  %".18" = getelementptr inbounds {...etc etc}

```

I don’t know anything really about LLVM IR parsing but “must be sized” sounds to me like LLVM has no idea how big the specialized DequeNode class will be while creating the Deque type. My suspicion is that Numba is only compiling the DequeNode class the first time it’s instantiated and (in make\_deque) it has never been instantiated.

Sure enough, manually instantiating a DequeNode before running the code above works mint (since the results of `_make_deque_node_class` are cached, we access the same type as the Deque)

```python
>>> DequeNode = _make_deque_node_class(nb.types.int64)
>>> DequeNode(1, None, None)
>>> Deque = make_deque(nb.types.int64)
>>> d = Deque()

( no errors, d works)

```

---

<div class="post-metadata">

**Author:** ![Hannes](https://yyz2.discourse-cdn.com/free1/user_avatar/numba.discourse.group/hannes/32/188_2.png) [@Hannes](https://numba.discourse.group/u/Hannes)\
**Post date:** [February 23, 2021, 9:00am UTC](https://numba.discourse.group/t/compiling-jitclass-before-first-instantiation/547/2 "2021-02-23T09:00:00Z")

</div>

Hi Tomas,

unfortunately I cannot personally help you on this issue (tried playing around a bit but nothing conclusive).

I just wanted to point out that there is a small problem with your otherwise very nice reproducer: In the `make_deque` function, you forgot to pass the `deque_spec` to `jitclass`.

Also here is the full error message I received (without traceback), I have a hunch that the deferred types may be the culprit here, that’s why I am sharing it.

```auto
RuntimeError: Failed in nopython mode pipeline (step: nopython mode backend)
Failed in nopython mode pipeline (step: nopython mode backend)
Failed in nopython mode pipeline (step: nopython mode backend)
LLVM IR parsing error
<string>:37:118: error: base element of getelementptr must be sized
  %".18" = getelementptr inbounds {i32, {%"deferred.2200476111704.data", i8}, {%"deferred.2200476111704.data", i8}}, {i32, {%"deferred.2200476111704.data", i8}, {%"deferred.2200476111704.data", i8}}* %".17", i32 0, i32 0

```

Hope someone else can help you out on this one 🙂

Cheers  
Hannes

---

<div class="post-metadata">

**Author:** ![agupta](https://avatars.discourse-cdn.com/v4/letter/a/e8c25b/32.png) [@agupta](https://numba.discourse.group/u/agupta)\
**Post date:** [May 10, 2021, 3:20am UTC](https://numba.discourse.group/t/compiling-jitclass-before-first-instantiation/547/3 "2021-05-10T03:20:21Z")

</div>

Were you able to figure out an implementation for Deque?
