Skip to content

BUG: function built with -F pyo3/abi3t raises TypeError at runtime (CPython 3.15.0b2-free-threaded)) #555

Closed

Description

@neutrinoceros

Context: I'm trying out PEP 803 support in neutrinoceros/rlic#423.
I found that function bindings generated for cp315-abi3.abi3t produced a TypeError at runtime against Python 3.15.0b2 (free-threaded) + numpy 2.6.0dev0 (nightly cp315-cp315t wheel). Here's a minimal reproducer1

use pyo3::prelude::*;
use numpy::borrow::PyReadonlyArray2;

#[pymodule]
fn _core<'py>(_py: Python<'py>, m: &Bound<'py, PyModule>) -> PyResult<()> {
    use pyo3::prelude::*;

    #[pyfunction]
    fn func<'py>(
        _py: Python<'py>,
        _array: PyReadonlyArray2<'py, f64>,
    ) -> i64 {
        0
    }
    m.add_function(wrap_pyfunction!(func, m)?)?;

    Ok(())
}
>>> import reprod
>>> import numpy as np
>>> reprod.func(np.eye(2, dtype="float64"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    reprod.func(np.eye(2, dtype="float64"))
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'ndarray' object is not an instance of 'ndarray'

adjacent to #547

Footnotes

  1. minimal, but not self-contained. I can share a more fleshed out example if it helps. I just assumed the rest wasn't important. ↩

Activity

  1. Icxolu commented on Jun 15, 2026

    @Icxolu
    Member

    I can reproduce this problem and managed to observe that this dimensionality check failed:

    rust-numpy/src/array.rs

    Lines 163 to 169 in 4ef0102

    // Check if the dimensionality matches `D`.
    let src_ndim = array.ndim();
    if let Some(dst_ndim) = D::NDIM {
    if src_ndim != dst_ndim {
    return Err(DimensionalityError::new(src_ndim, dst_ndim).into());
    }
    }

    Python 3.15.0b2 free-threading build (main, Jun 11 2026, 04:25:23) [MSC v.1951 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from pyo3_scratch.whatever import func
    >>> import numpy as np
    >>> e = np.eye(2, dtype="float64")
    >>> func(e)
    [..\pyo3-workspace\rust-numpy\src\array.rs:153:16] check(ob.py(), ob.as_ptr()) = 1
    [..\pyo3-workspace\rust-numpy\src\array.rs:164:24] array.ndim() = 0
    [..\pyo3-workspace\rust-numpy\src\array.rs:165:33] D::NDIM = Some(
        2,
    )
    Traceback (most recent call last):
      File "<python-input-3>", line 1, in <module>
        func(e)
        ~~~~^^^
    TypeError: 'ndarray' object is not an instance of 'ndarray'
    while processing '_array'

    In the version specific build it succeeds as expected:

    Python 3.15.0b2 free-threading build (main, Jun 11 2026, 04:25:23) [MSC v.1951 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from pyo3_scratch.whatever import func
    >>> import numpy as np
    >>> e = np.eye(2, dtype="float64")
    >>> func(e)
    [..\pyo3-workspace\rust-numpy\src\array.rs:153:16] check(ob.py(), ob.as_ptr()) = 1
    [..\pyo3-workspace\rust-numpy\src\array.rs:164:24] array.ndim() = 2
    [..\pyo3-workspace\rust-numpy\src\array.rs:165:33] D::NDIM = Some(
        2,
    )
    [..\pyo3-workspace\rust-numpy\src\array.rs:174:12] !src_dtype.is_equiv_to(&dst_dtype) = false
    0

    My best guess currently is that there are ABI changes in npyffi (most likely in object.rs) for ABI3T. There was no specific work yet to support abi3t, so I would not be surprised if something is missing.

    cc @ngoldbaum

  2. ngoldbaum commented on Jun 15, 2026

    @ngoldbaum
    Contributor

    @kumaraditya303 updated the headers for abi3t support: numpy/numpy#31091

    The FFI bindings over here are going to need to be updated to match.

  3. ngoldbaum commented on Jun 15, 2026

    @ngoldbaum
    Contributor

    (maybe npyffi could grow something like pyo3's ffi-check macro?)

  4. Icxolu commented on Jun 16, 2026

    @Icxolu
    Member

    Thanks @ngoldbaum. I went though this and opened #556 with the initial changes to make this work. GIL enabled CI is still green and locally the failing abi3t example from above works now. We still would need to figure out CI testing for this though.

    @neutrinoceros Maybe you want to try building against #556 and see if that would work for your example?

  5. neutrinoceros commented on Jun 16, 2026

    @neutrinoceros
    Author

    Thanks a lot ! I'll try it out in my CI first thing in the morning !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions