Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[BUG] Fails to preprocess an array of struct inside another struct #7191

@pulkin

Description

@pulkin

Describe the bug

I am generating some cython code to compare arbitrary numpy dtypes (not important). Latest cython 3.1.4 refuses to preprocess one (see the code). The error:

code = <Cython.Compiler.Code.CCodeWriter object at 0x7fa680828ec0>
dtype = <CNumericType int>, maxdepth = 0

    def get_type_information_cname(code, dtype, maxdepth=None):
        """
        Output the run-time type information (__Pyx_TypeInfo) for given dtype,
        and return the name of the type info struct.
    
        Structs with two floats of the same size are encoded as complex numbers.
        One can separate between complex numbers declared as struct or with native
        encoding by inspecting to see if the fields field of the type is
        filled in.
        """
        namesuffix = mangle_dtype_name(dtype)
        name = "__Pyx_TypeInfo_%s" % namesuffix
        structinfo_name = "__Pyx_StructFields_%s" % namesuffix
    
        if dtype.is_error: return "<error>"
    
        # It's critical that walking the type info doesn't use more stack
        # depth than dtype.struct_nesting_depth() returns, so use an assertion for this
        if maxdepth is None: maxdepth = dtype.struct_nesting_depth()
        if maxdepth <= 0:
>           assert False
                   ^^^^^
E           AssertionError

Help appreciated.

Code to reproduce the behaviour:

import cython
cdef packed struct struct_1:
  int f0
  char f1[5]
cdef double compare_struct_1(const struct_1 a, const struct_1 b):
  cdef double result = 0
  cdef Py_ssize_t i0
  result += a.f0 == b.f0
  for i0 in range(5):
    result += a.f1[i0] == b.f1[i0]
  return result / 6
cdef packed struct struct_0:
  long long f0
  struct_1 f1[2]
cdef double compare_struct_0(const struct_0 a, const struct_0 b):
  cdef double result = 0
  cdef Py_ssize_t i0
  result += a.f0 == b.f0
  for i0 in range(2):
    result += compare_struct_1(a.f1[i0], b.f1[i0])
  return result / 3
cdef class Backend:
  cdef const struct_0[:] a
  cdef const struct_0[:] b
  def __init__(self, const struct_0[:] a not None, const struct_0[:] b not None):
    self.a = a
    self.b = b
  @cython.initializedcheck(False)
  @cython.wraparound(False)
  cdef double compare(self, Py_ssize_t i, Py_ssize_t j):
    return compare_struct_0(self.a[i], self.b[j])

Expected behaviour

I expect nested structs/record array dtypes to work in cython as described in the docs.

OS

Fedora

Python version

3.13

Cython version

3.1.4

Additional context

For the context, this is the corresponding numpy dtype. I was simply writing a unit test to check whether it all works with nested structs so there should really be nothing special about it: the thing is a mixture of types and options to maximize test coverage.

dtype_inner = np.dtype([("ix", "i4"), ("name", "S5")])
dtype = np.dtype([("pair_ix", "i8"), ("pair", dtype_inner, 2)])

Not sure what MWE would be.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions