Repository: llvm/llvm-project
File: mlir/include/mlir/Bindings/Python/NanobindUtils.h (C/C++)

Code before:
  intptr_t size() { return length; }

  /// Returns a new vector (mapped to Python list) containing elements from two
  /// slices. The new vector is necessary because slices may not be contiguous
  /// or even come from the same original sequence.
  std::vector<ElementTy> dunderAdd(Derived &other) {
    std::vector<ElementTy> elements;
    elements.reserve(length + other.length);
    for (intptr_t i = 0; i < length; ++i) {
      elements.push_back(static_cast<Derived *>(this)->getElement(i));
    }
    for (intptr_t i = 0; i < other.length; ++i) {
      elements.push_back(static_cast<Derived *>(&other)->getElement(i));
    }
    return elements;
  }

  // Manually implement the sequence protocol via the C API. We do this
  // because it is approx 4x faster than via nanobind, largely because that
  // formulation requires a C++ exception to be thrown to detect end of
  // sequence.
  // Since we are in a C-context, any C++ exception that happens here
  // will terminate the program. There is nothing in this implementation
  // that should throw in a non-terminal way, so we forgo further
  // exception marshalling.
  // See: https://github.com/pybind/nanobind/issues/2842
  //
  /// Binds the indexing and length methods in the Python class.
  static void bind(nanobind::module_ &m) {
    // These slots are passed via nanobind::type_slots() at class creation
    // time, which is compatible with both the full and limited (stable ABI)
    // Python APIs.
    static PyType_Slot sequenceSlots[] = {
        {Py_sq_length, (void *)(+[](PyObject *rawSelf) -> Py_ssize_t {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           return self->length;
         })},
        // sq_item is called as part of the sequence protocol for iteration,
        // list construction, etc.
        {Py_sq_item,
         (void *)(+[](PyObject *rawSelf, Py_ssize_t index) -> PyObject * {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           return self->getItem(index).release().ptr();
         })},
        // mp_subscript is used for both slices and integer lookups.
        {Py_mp_subscript,
         (void *)(+[](PyObject *rawSelf, PyObject *rawSubscript) -> PyObject * {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           Py_ssize_t index =
               PyNumber_AsSsize_t(rawSubscript, PyExc_IndexError);
           if (!PyErr_Occurred()) {

Review comment (suggestion):
nit (not your fault):
```suggestion
  // See: https://github.com/pybind/pybind11/issues/2842
```

Code after:
  intptr_t size() { return length; }

  /// Returns a new vector (mapped to Python list) containing elements from two
  /// slices. The new vector is necessary because slices may not be contiguous
  /// or even come from the same original sequence.
  std::vector<ElementTy> dunderAdd(Derived &other) {
    std::vector<ElementTy> elements;
    elements.reserve(length + other.length);
    for (intptr_t i = 0; i < length; ++i) {
      elements.push_back(static_cast<Derived *>(this)->getElement(i));
    }
    for (intptr_t i = 0; i < other.length; ++i) {
      elements.push_back(static_cast<Derived *>(&other)->getElement(i));
    }
    return elements;
  }

  // Manually implement the sequence protocol via the C API. We do this
  // because it is approx 4x faster than via nanobind, largely because that
  // formulation requires a C++ exception to be thrown to detect end of
  // sequence.
  // Since we are in a C-context, any C++ exception that happens here
  // will terminate the program. There is nothing in this implementation
  // that should throw in a non-terminal way, so we forgo further
  // exception marshalling.
  // See: https://github.com/pybind/pybind11/issues/2842
  //
  /// Binds the indexing and length methods in the Python class.
  static void bind(nanobind::module_ &m) {
    // These slots are passed via nanobind::type_slots() at class creation
    // time, which is compatible with both the full and limited (stable ABI)
    // Python APIs.
    static PyType_Slot sequenceSlots[] = {
        {Py_sq_length, (void *)(+[](PyObject *rawSelf) -> Py_ssize_t {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           return self->length;
         })},
        // sq_item is called as part of the sequence protocol for iteration,
        // list construction, etc.
        {Py_sq_item,
         (void *)(+[](PyObject *rawSelf, Py_ssize_t index) -> PyObject * {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           return self->getItem(index).release().ptr();
         })},
        // mp_subscript is used for both slices and integer lookups.
        {Py_mp_subscript,
         (void *)(+[](PyObject *rawSelf, PyObject *rawSubscript) -> PyObject * {
           auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
           Py_ssize_t index =
               PyNumber_AsSsize_t(rawSubscript, PyExc_IndexError);
           if (!PyErr_Occurred()) {