Skip to content

Commit 9e5f44d

Browse files
committed
Source of truth for google3_iwyu_pragmas.patch
Merging and upstreaming this PR is deferred until Include Cleaner supports removing the "third_party/pybind11/include/" path name parts.
1 parent f5269ca commit 9e5f44d

38 files changed

+158
-0
lines changed

docs/type_caster_iwyu.rst

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
pybind11 ``type_caster`` design & `clangd Include Cleaner`_
2+
===========================================================
3+
4+
This document is purely to explain — in a nutshell — why pybind11 include
5+
files with ``type_caster`` specializations require this:
6+
7+
.. code-block:: cpp
8+
9+
// IWYU pragma: always_keep
10+
11+
For general technical information about the pybind11 ``type_caster`` mechanism
12+
see the `Custom type casters`_ section.
13+
14+
The problem
15+
-----------
16+
17+
The `clangd Include Cleaner`_ cannot possibly have the ability to detect which
18+
``type_caster`` specialization is the correct one to use in a given C++
19+
translation unit. Without IWYU pragmas, Include Cleaner is likely to suggest
20+
removing ``type_caster`` include files.
21+
22+
The consequences
23+
----------------
24+
25+
1. Incorrect runtime behavior.
26+
2. `ODR violations`_.
27+
28+
Example for 1. Incorrect runtime behavior
29+
-----------------------------------------
30+
31+
.. code-block:: cpp
32+
33+
#include <pybind11/pybind11.h>
34+
#include <pybind11/stl.h>
35+
36+
If the stl.h include is removed (as suggested by Include Cleaner), conversions
37+
between e.g. ``std::vector`` and Python ``list`` will no longer work. In most
38+
cases this will be very obvious at runtime, but there are less obvious
39+
situations, most notably for ``type_caster`` specializations that inherit from
40+
``type_caster_base`` (e.g. `pybind11_abseil/status_caster.h`_).
41+
Some conversions may still work correctly, while others will have unexpected
42+
behavior.
43+
44+
Explanation for 2. ODR violations
45+
---------------------------------
46+
47+
This problem only arises if two or more C++ translation units are statically
48+
linked (e.g. one ``.so`` Python extension built from multiple .cpp files), or
49+
all visibility-restricting features (e.g. ``-fvisibility=hidden``,
50+
``namespace pybind11`` ``__attribute__((visibility("hidden")))``,
51+
``RTLD_LOCAL``) are disabled.
52+
53+
Consider the same simple code example as above: if the stl.h include is missing
54+
(as suggested by Include Cleaner) in one translation unit, but not in another
55+
(maybe because Include Cleaner was never applied), the resulting Python
56+
extension will have link incompatibilities, which is often referred to as
57+
ODR violations. The behavior is entirely undefined. For better or worse, the
58+
extension may perform as desired for years, until one day it suddenly does
59+
not, because of some unrelated change in the environment (e.g. new compiler
60+
version, a system library update), resulting in seemingly inexplicable failures
61+
62+
See also: `pybind/pybind11#4022`_ (pybind11 smart_holder branch)
63+
64+
.. _`clangd Include Cleaner`: https://clangd.llvm.org/design/include-cleaner
65+
.. _`Custom type casters`: https://pybind11.readthedocs.io/en/stable/advanced/cast/custom.html
66+
.. _`ODR violations`: https://en.cppreference.com/w/cpp/language/definition
67+
.. _`pybind11_abseil/status_caster.h`: https://github.com/pybind/pybind11_abseil/blob/4b883e48ae749ff984c220484d54fdeb0cb4302c/pybind11_abseil/status_caster.h#L52-L53).
68+
.. _`pybind/pybind11#4022`: https://github.com/pybind/pybind11/pull/4022

include/pybind11/attr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
#pragma once
1212

13+
// IWYU pragma: begin_exports
1314
#include "detail/common.h"
15+
// IWYU pragma: end_exports
1416
#include "cast.h"
1517

1618
#include <functional>

include/pybind11/buffer_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
#pragma once
1111

12+
// IWYU pragma: begin_exports
1213
#include "detail/common.h"
14+
// IWYU pragma: end_exports
1315

1416
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1517

include/pybind11/cast.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@
88
BSD-style license that can be found in the LICENSE file.
99
*/
1010

11+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
12+
1113
#pragma once
1214

15+
// IWYU pragma: begin_exports
1316
#include "detail/common.h"
1417
#include "detail/descr.h"
1518
#include "detail/native_enum_data.h"
1619
#include "detail/smart_holder_sfinae_hooks_only.h"
1720
#include "detail/type_caster_base.h"
1821
#include "detail/type_caster_odr_guard.h"
1922
#include "detail/typeid.h"
23+
// IWYU pragma: end_exports
2024
#include "pytypes.h"
2125

2226
#include <array>

include/pybind11/chrono.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
BSD-style license that can be found in the LICENSE file.
99
*/
1010

11+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
12+
1113
#pragma once
1214

1315
#include "pybind11.h"

include/pybind11/complex.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
11+
1012
#pragma once
1113

1214
#include "pybind11.h"

include/pybind11/detail/abi_platform_id.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#include "common.h"

include/pybind11/detail/class.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#include "../attr.h"

include/pybind11/detail/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#define PYBIND11_VERSION_MAJOR 2

include/pybind11/detail/cross_extension_shared_state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#define PYBIND11_HAS_CROSS_EXTENSION_SHARED_STATE

include/pybind11/detail/descr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
BSD-style license that can be found in the LICENSE file.
1111
*/
1212

13+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
14+
1315
#pragma once
1416

1517
#include "common.h"

include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"
6+
57
#pragma once
68

79
#include "common.h"

include/pybind11/detail/init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#include "class.h"

include/pybind11/detail/internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#include "../pytypes.h"

include/pybind11/detail/native_enum_data.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#define PYBIND11_HAS_NATIVE_ENUM

include/pybind11/detail/smart_holder_poc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"
6+
57
/* Proof-of-Concept for smart pointer interoperability.
68
79
High-level aspects:

include/pybind11/detail/smart_holder_sfinae_hooks_only.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#include "common.h"

include/pybind11/detail/smart_holder_type_casters.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/smart_holder.h"
6+
57
#pragma once
68

79
#include "../gil.h"

include/pybind11/detail/type_caster_base.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#include "../pytypes.h"

include/pybind11/detail/type_caster_odr_guard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#include "descr.h"

include/pybind11/detail/type_map.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
6+
57
#pragma once
68

79
#include "common.h"

include/pybind11/detail/typeid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: private, include "third_party/pybind11/include/pybind11/pybind11.h"
11+
1012
#pragma once
1113

1214
#include <cstdio>

include/pybind11/eigen/matrix.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
11+
1012
#pragma once
1113

1214
#include "../numpy.h"
15+
// IWYU pragma: begin_exports
1316
#include "common.h"
17+
// IWYU pragma: end_exports
1418

1519
/* HINT: To suppress warnings originating from the Eigen headers, use -isystem.
1620
See also:

include/pybind11/eigen/tensor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
BSD-style license that can be found in the LICENSE file.
66
*/
77

8+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
9+
810
#pragma once
911

1012
#include "../numpy.h"
13+
// IWYU pragma: begin_exports
1114
#include "common.h"
15+
// IWYU pragma: end_exports
1216

1317
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
1418
static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");

include/pybind11/functional.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
11+
1012
#pragma once
1113

1214
#define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS

include/pybind11/gil.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@
99

1010
#pragma once
1111

12+
// IWYU pragma: begin_exports
1213
#include "detail/common.h"
14+
// IWYU pragma: end_exports
1315

1416
#include <cassert>
1517

1618
#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
19+
// IWYU pragma: begin_exports
1720
# include "detail/internals.h"
21+
// IWYU pragma: end_exports
1822
#endif
1923

2024
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

include/pybind11/gil_safe_call_once.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
#pragma once
44

5+
// IWYU pragma: begin_exports
56
#include "detail/common.h"
7+
// IWYU pragma: end_exports
68
#include "gil.h"
79

810
#include <cassert>

include/pybind11/native_enum.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
#pragma once
66

7+
// IWYU pragma: begin_exports
78
#include "detail/common.h"
89
#include "detail/native_enum_data.h"
910
#include "detail/type_caster_base.h"
11+
// IWYU pragma: end_exports
1012
#include "cast.h"
1113

1214
#include <limits>

include/pybind11/numpy.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
BSD-style license that can be found in the LICENSE file.
88
*/
99

10+
// IWYU pragma: always_keep // See pybind11/docs/type_caster_iwyu.rst
11+
1012
#pragma once
1113

1214
#include "pybind11.h"
15+
// IWYU pragma: begin_exports
1316
#include "detail/common.h"
17+
// IWYU pragma: end_exports
1418
#include "complex.h"
1519
#include "gil_safe_call_once.h"
1620
#include "pytypes.h"

include/pybind11/options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
#pragma once
1111

12+
// IWYU pragma: begin_exports
1213
#include "detail/common.h"
14+
// IWYU pragma: end_exports
1315

1416
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
1517

include/pybind11/pybind11.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
#pragma once
1212

13+
// IWYU pragma: begin_exports
1314
#include "detail/class.h"
1415
#include "detail/init.h"
1516
#include "detail/native_enum_data.h"
1617
#include "detail/smart_holder_sfinae_hooks_only.h"
18+
// IWYU pragma: end_exports
1719
#include "attr.h"
1820
#include "gil.h"
1921
#include "gil_safe_call_once.h"

include/pybind11/pytypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
#pragma once
1111

12+
// IWYU pragma: begin_exports
1213
#include "detail/common.h"
14+
// IWYU pragma: end_exports
1315
#include "buffer_info.h"
1416

1517
#include <assert.h>

0 commit comments

Comments
 (0)