Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions mypyc/lib-rt/vecs/librt_vecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,8 @@ PyTypeObject VecGenericAliasType = {
// The 'vec' type
//
// This cannot be instantiated, and it's only used for isinstance and indexing: vec[T].

typedef struct {
PyObject_HEAD
} Vec;
// All specialized vec types (VecI64Type, VecI32Type, etc.) inherit from this base type,
// so isinstance(v, vec) returns True for any specialized vec instance.

static PyObject *extract_optional_item(PyObject *item) {
PyObject *args = PyObject_GetAttrString(item, "__args__");
Expand Down Expand Up @@ -374,9 +372,9 @@ static PyMethodDef vec_methods[] = {
PyTypeObject VecType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "vec",
.tp_basicsize = sizeof(Vec),
.tp_basicsize = sizeof(VecBaseObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_flags = Py_TPFLAGS_DEFAULT, // No Py_TPFLAGS_BASETYPE - prevent Python subclassing
.tp_methods = vec_methods,
};

Expand Down
7 changes: 7 additions & 0 deletions mypyc/lib-rt/vecs/librt_vecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ typedef struct _VecObject {
Py_ssize_t len;
} VecObject;

// Base vec type object (for isinstance checks)
// This is an abstract base type that all specialized vec types inherit from.
// It cannot be instantiated directly - only used for isinstance(x, vec).
typedef struct _VecBaseObject {
PyObject_HEAD
} VecBaseObject;

// Boxed vec[i64]
typedef struct _VecI64Object {
PyObject_HEAD
Expand Down
2 changes: 2 additions & 0 deletions mypyc/lib-rt/vecs/vec_nested.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "librt_vecs.h"
#include "vecs_internal.h"

static inline VecNested vec_error() {
VecNested v = { .len = -1 };
Expand Down Expand Up @@ -439,6 +440,7 @@ PyTypeObject VecNestedType = {
.tp_doc = "Mutable sequence-like container optimized for compilation with mypyc",
.tp_basicsize = sizeof(VecNestedObject),
.tp_itemsize = 0,
.tp_base = &VecType, // Inherit from base vec type for isinstance() support
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)VecNested_traverse,
.tp_clear = (inquiry)VecNested_clear,
Expand Down
2 changes: 2 additions & 0 deletions mypyc/lib-rt/vecs/vec_t.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "librt_vecs.h"
#include "vecs_internal.h"

static inline VecT vec_error() {
VecT v = { .len = -1 };
Expand Down Expand Up @@ -433,6 +434,7 @@ PyTypeObject VecTType = {
.tp_doc = "Mutable sequence-like container optimized for compilation with mypyc",
.tp_basicsize = sizeof(VecTObject),
.tp_itemsize = 0,
.tp_base = &VecType, // Inherit from base vec type for isinstance() support
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)VecT_traverse,
.tp_clear = (inquiry)VecT_clear,
Expand Down
2 changes: 2 additions & 0 deletions mypyc/lib-rt/vecs/vec_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "librt_vecs.h"
#include "vecs_internal.h"

inline static VEC vec_error() {
VEC v = { .len = -1 };
Expand Down Expand Up @@ -370,6 +371,7 @@ PyTypeObject VEC_TYPE = {
.tp_doc = "Mutable sequence-like container optimized for compilation with mypyc",
.tp_basicsize = sizeof(VEC_OBJECT),
.tp_itemsize = 0,
.tp_base = &VecType, // Inherit from base vec type for isinstance() support
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_new = vec_new,
//.tp_free = PyObject_Del,
Expand Down
11 changes: 11 additions & 0 deletions mypyc/lib-rt/vecs/vecs_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef VECS_INTERNAL_H_INCL
#define VECS_INTERNAL_H_INCL

// Internal header for mypyc/lib-rt/vecs implementation

#include <Python.h>

// The base vec type
extern PyTypeObject VecType;

#endif // VECS_INTERNAL_H_INCL
8 changes: 8 additions & 0 deletions mypyc/test-data/run-vecs-misc-interp.test
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ def test_construct_empty() -> None:
assert type(v) is vec[t]
assert len(v) == 0

def test_isinstance() -> None:
for t in ITEM_TYPES:
v = vec[t]()
assert isinstance(v, vec)
assert not isinstance(vec[t], vec)
assert not isinstance("x", vec)
assert not isinstance(vec, vec)

def test_basic_int_operations() -> None:
# All of the non-bool item types support int values 0 to 255
for t in ITEM_TYPES:
Expand Down
4 changes: 4 additions & 0 deletions mypyc/test-data/run-vecs-nested-interp.test
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ def test_construct_from_initializer_nested() -> None:
with assertRaises(TypeError):
vec[str]([vec[bytes]()])

def test_isinstance() -> None:
assert isinstance(vec[vec[str]](), vec)
assert isinstance(vec[vec[Optional[str]]](), vec)

def test_repr() -> None:
assert str(vec[vec[str]]()) == "vec[vec[str]]([])"
assert str(vec[vec[Optional[str]]]()) == "vec[vec[str | None]]([])"
Expand Down
4 changes: 4 additions & 0 deletions mypyc/test-data/run-vecs-t-interp.test
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ def test_construct_from_initializer_optional() -> None:
with assertRaises(TypeError):
vec[Optional[str]]([1])

def test_isinstance() -> None:
assert isinstance(vec[str](), vec)
assert isinstance(vec[Optional[str]](), vec)

def test_append() -> None:
v = vec[str]()
v = append(v, '1')
Expand Down