Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MOVED] Add pybind11 IWYU pragmas (for clangd Include Cleaner). #30073

Closed
wants to merge 6 commits into from
Closed
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
68 changes: 68 additions & 0 deletions docs/type_caster_iwyu.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
pybind11 ``type_caster`` design & `clangd Include Cleaner`_
===========================================================

This document is purely to explain — in a nutshell — why pybind11 include
files with ``type_caster`` specializations require this:

.. code-block:: cpp

// IWYU pragma: always_keep

For general technical information about the pybind11 ``type_caster`` mechanism
see the `Custom type casters`_ section.

The problem
-----------

The `clangd Include Cleaner`_ cannot possibly have the ability to detect which
``type_caster`` specialization is the correct one to use in a given C++
translation unit. Without IWYU pragmas, Include Cleaner is likely to suggest
removing ``type_caster`` include files.

The consequences
----------------

1. Incorrect runtime behavior.
2. `ODR violations`_.

Example for 1. Incorrect runtime behavior
-----------------------------------------

.. code-block:: cpp

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

If the stl.h include is removed (as suggested by Include Cleaner), conversions
between e.g. ``std::vector`` and Python ``list`` will no longer work. In most
cases this will be very obvious at runtime, but there are less obvious
situations, most notably for ``type_caster`` specializations that inherit from
``type_caster_base`` (e.g. `pybind11_abseil/status_caster.h`_).
Some conversions may still work correctly, while others will have unexpected
behavior.

Explanation for 2. ODR violations
---------------------------------

This problem only arises if two or more C++ translation units are statically
linked (e.g. one ``.so`` Python extension built from multiple .cpp files), or
all visibility-restricting features (e.g. ``-fvisibility=hidden``,
``namespace pybind11`` ``__attribute__((visibility("hidden")))``,
``RTLD_LOCAL``) are disabled.

Consider the same simple code example as above: if the stl.h include is missing
(as suggested by Include Cleaner) in one translation unit, but not in another
(maybe because Include Cleaner was never applied), the resulting Python
extension will have link incompatibilities, which is often referred to as
ODR violations. The behavior is entirely undefined. For better or worse, the
extension may perform as desired for years, until one day it suddenly does
not, because of some unrelated change in the environment (e.g. new compiler
version, a system library update), resulting in seemingly inexplicable failures

See also: `pybind/pybind11#4022`_ (pybind11 smart_holder branch)

.. _`clangd Include Cleaner`: https://clangd.llvm.org/design/include-cleaner
.. _`Custom type casters`: https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html
.. _`ODR violations`: https://en.cppreference.com/w/cpp/language/definition
.. _`pybind11_abseil/status_caster.h`: https://github.com/pybind/pybind11_abseil/blob/4b883e48ae749ff984c220484d54fdeb0cb4302c/pybind11_abseil/status_caster.h#L52-L53).
.. _`pybind/pybind11#4022`: https://github.com/pybind/pybind11/pull/4022
2 changes: 2 additions & 0 deletions include/pybind11/attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports
#include "cast.h"

#include <functional>
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/buffer_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
#include "detail/descr.h"
#include "detail/native_enum_data.h"
#include "detail/smart_holder_sfinae_hooks_only.h"
#include "detail/type_caster_base.h"
#include "detail/type_caster_odr_guard.h"
#include "detail/typeid.h"
// IWYU pragma: end_exports
#include "pytypes.h"

#include <array>
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#include "pybind11.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#include "pybind11.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/abi_platform_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "common.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "../attr.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#define PYBIND11_VERSION_MAJOR 2
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/cross_extension_shared_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#define PYBIND11_HAS_CROSS_EXTENSION_SHARED_STATE
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/descr.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "common.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"

#pragma once

#include "common.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/function_record_pyobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

// For background see the description of PR google/pywrapcc#30099.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "../attr.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "class.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "../pytypes.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/native_enum_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#define PYBIND11_HAS_NATIVE_ENUM
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/smart_holder_poc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"

/* Proof-of-Concept for smart pointer interoperability.

High-level aspects:
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/smart_holder_sfinae_hooks_only.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "common.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/smart_holder_type_casters.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"

#pragma once

#include "../gil.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/type_caster_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "../pytypes.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/type_caster_odr_guard.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "descr.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/type_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include "common.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/detail/typeid.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"

#pragma once

#include <cstdio>
Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/eigen/matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#include "../numpy.h"
// IWYU pragma: begin_exports
#include "common.h"
// IWYU pragma: end_exports

/* HINT: To suppress warnings originating from the Eigen headers, use -isystem.
See also:
Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/eigen/tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#include "../numpy.h"
// IWYU pragma: begin_exports
#include "common.h"
// IWYU pragma: end_exports

#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/functional.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS
Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/gil.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports

#include <cassert>

#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
// IWYU pragma: begin_exports
# include "detail/internals.h"
// IWYU pragma: end_exports
#endif

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/gil_safe_call_once.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports
#include "gil.h"

#include <cassert>
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/native_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
#include "detail/native_enum_data.h"
#include "detail/type_caster_base.h"
// IWYU pragma: end_exports
#include "cast.h"

#include <limits>
Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/numpy.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
BSD-style license that can be found in the LICENSE file.
*/

// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst

#pragma once

#include "pybind11.h"
// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports
#include "complex.h"
#include "gil_safe_call_once.h"
#include "pytypes.h"
Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/common.h"
// IWYU pragma: end_exports

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@

#pragma once

// IWYU pragma: begin_exports
#include "detail/class.h"
#include "detail/function_record_pyobject.h"
#include "detail/init.h"
#include "detail/native_enum_data.h"
#include "detail/smart_holder_sfinae_hooks_only.h"
// IWYU pragma: end_exports
#include "attr.h"
#include "gil.h"
#include "gil_safe_call_once.h"
Expand Down
Loading
Loading