xref: /aosp_15_r20/external/cronet/base/functional/unretained_traits.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <concepts>
9*6777b538SAndroid Build Coastguard Worker #include <type_traits>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include "base/types/is_complete.h"
12*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker // Various opaque system types that should still be usable with the base
15*6777b538SAndroid Build Coastguard Worker // callback system. Please keep sorted.
16*6777b538SAndroid Build Coastguard Worker #define BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED           \
17*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(ANativeWindow)          \
18*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(DBusMessage)            \
19*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(HWND__)                 \
20*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkBuffer_T)             \
21*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkDeviceMemory_T)       \
22*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkImage_T)              \
23*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(VkSemaphore_T)          \
24*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(VmaAllocation_T)        \
25*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(WGPUAdapterImpl)        \
26*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_action_t__)        \
27*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_annotation_t__)    \
28*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_attachment_t__)    \
29*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_bookmark_t__)      \
30*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_document_t__)      \
31*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_form_handle_t__)   \
32*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_page_t__)          \
33*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(fpdf_structelement_t__) \
34*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(hb_set_t)               \
35*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_gpu)                 \
36*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_shm)                 \
37*6777b538SAndroid Build Coastguard Worker   BASE_INTERNAL_SAFE_FOR_UNRETAINED(wl_surface)
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker #define BASE_INTERNAL_SAFE_FOR_UNRETAINED(x) struct x;
40*6777b538SAndroid Build Coastguard Worker BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED
41*6777b538SAndroid Build Coastguard Worker #undef BASE_INTERNAL_SAFE_FOR_UNRETAINED
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker namespace base::internal {
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker template <typename T, typename... Ts>
46*6777b538SAndroid Build Coastguard Worker concept SameAsAny = (std::same_as<T, Ts> || ...);
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker // Determining whether a type can be used with `Unretained()` requires that `T`
49*6777b538SAndroid Build Coastguard Worker // be completely defined. Some system types have an intentionally opaque and
50*6777b538SAndroid Build Coastguard Worker // incomplete representation, but should still be usable with `Unretained()`.
51*6777b538SAndroid Build Coastguard Worker template <typename T>
52*6777b538SAndroid Build Coastguard Worker concept SafeIncompleteTypeForUnretained =
53*6777b538SAndroid Build Coastguard Worker     SameAsAny<std::remove_cvref_t<T>,
54*6777b538SAndroid Build Coastguard Worker #define BASE_INTERNAL_SAFE_FOR_UNRETAINED(x) x,
55*6777b538SAndroid Build Coastguard Worker               BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED
56*6777b538SAndroid Build Coastguard Worker #undef BASE_INTERNAL_SAFE_FOR_UNRETAINED
57*6777b538SAndroid Build Coastguard Worker               // void* is occasionally used with callbacks; in the future,
58*6777b538SAndroid Build Coastguard Worker               // this may be more restricted/limited, but allow it for now.
59*6777b538SAndroid Build Coastguard Worker               void>;
60*6777b538SAndroid Build Coastguard Worker 
61*6777b538SAndroid Build Coastguard Worker // Customization point. Specialize this to be `false` for types as needed. In
62*6777b538SAndroid Build Coastguard Worker // general, you should not need this; types that do not support `Unretained()`
63*6777b538SAndroid Build Coastguard Worker // should use `DISALLOW_UNRETAINED()`. However, this is necessary when
64*6777b538SAndroid Build Coastguard Worker // disallowing `Unretained()` for types that do not (or cannot) use //base.
65*6777b538SAndroid Build Coastguard Worker template <typename T>
66*6777b538SAndroid Build Coastguard Worker inline constexpr bool kCustomizeSupportsUnretained = true;
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker template <typename T>
69*6777b538SAndroid Build Coastguard Worker concept DisallowsUnretained = !kCustomizeSupportsUnretained<T> || requires {
70*6777b538SAndroid Build Coastguard Worker   // Matches against the marker tag created by the `DISALLOW_UNRETAINED()` macro
71*6777b538SAndroid Build Coastguard Worker   // in //base/functional/disallow_unretained.h.
72*6777b538SAndroid Build Coastguard Worker   typename T::DisallowBaseUnretainedMarker;
73*6777b538SAndroid Build Coastguard Worker };
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker template <typename T>
76*6777b538SAndroid Build Coastguard Worker struct SupportsUnretainedImpl {
77*6777b538SAndroid Build Coastguard Worker   // For context on this "templated struct with a lambda that asserts" pattern,
78*6777b538SAndroid Build Coastguard Worker   // see comments in `Invoker<>`.
79*6777b538SAndroid Build Coastguard Worker   template <bool v = IsComplete<T> || SafeIncompleteTypeForUnretained<T>>
80*6777b538SAndroid Build Coastguard Worker   struct AllowlistIncompleteTypes {
81*6777b538SAndroid Build Coastguard Worker     static constexpr bool value = [] {
82*6777b538SAndroid Build Coastguard Worker // Incrementally enforce the requirement to be completely defined. For now,
83*6777b538SAndroid Build Coastguard Worker // limit the failures to:
84*6777b538SAndroid Build Coastguard Worker //
85*6777b538SAndroid Build Coastguard Worker // - non-test code
86*6777b538SAndroid Build Coastguard Worker // - non-official code (because these builds don't run as part of the default CQ
87*6777b538SAndroid Build Coastguard Worker //   and are slower due to PGO and LTO)
88*6777b538SAndroid Build Coastguard Worker // - Android, Linux or Windows
89*6777b538SAndroid Build Coastguard Worker //
90*6777b538SAndroid Build Coastguard Worker // to make this easier to land without potentially breaking the tree.
91*6777b538SAndroid Build Coastguard Worker //
92*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/1392872): Enable this on all platforms, then in
93*6777b538SAndroid Build Coastguard Worker // official builds, and then in non-test code as well.
94*6777b538SAndroid Build Coastguard Worker #if defined(FORCE_UNRETAINED_COMPLETENESS_CHECKS_FOR_TESTS) || \
95*6777b538SAndroid Build Coastguard Worker     (!defined(UNIT_TEST) && !defined(OFFICIAL_BUILD) &&        \
96*6777b538SAndroid Build Coastguard Worker      (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN)))
97*6777b538SAndroid Build Coastguard Worker       static_assert(v,
98*6777b538SAndroid Build Coastguard Worker                     "Argument requires unretained storage, but type is not "
99*6777b538SAndroid Build Coastguard Worker                     "fully defined. This prevents determining whether "
100*6777b538SAndroid Build Coastguard Worker                     "`Unretained()` is supported.");
101*6777b538SAndroid Build Coastguard Worker       return v;
102*6777b538SAndroid Build Coastguard Worker #else
103*6777b538SAndroid Build Coastguard Worker       return true;
104*6777b538SAndroid Build Coastguard Worker #endif
105*6777b538SAndroid Build Coastguard Worker     }();
106*6777b538SAndroid Build Coastguard Worker   };
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   template <bool v = !DisallowsUnretained<T>>
109*6777b538SAndroid Build Coastguard Worker   struct AllowsUnretained {
110*6777b538SAndroid Build Coastguard Worker     static constexpr bool value = [] {
111*6777b538SAndroid Build Coastguard Worker       static_assert(v,
112*6777b538SAndroid Build Coastguard Worker                     "Argument requires unretained storage, but type does not "
113*6777b538SAndroid Build Coastguard Worker                     "support `Unretained()`. See "
114*6777b538SAndroid Build Coastguard Worker                     "base/functional/disallow_unretained.h for alternatives.");
115*6777b538SAndroid Build Coastguard Worker       return v;
116*6777b538SAndroid Build Coastguard Worker     }();
117*6777b538SAndroid Build Coastguard Worker   };
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker   static constexpr bool value =
120*6777b538SAndroid Build Coastguard Worker       std::conjunction_v<AllowlistIncompleteTypes<>, AllowsUnretained<>>;
121*6777b538SAndroid Build Coastguard Worker };
122*6777b538SAndroid Build Coastguard Worker 
123*6777b538SAndroid Build Coastguard Worker // Not meant for general use: merely checking this concept will
124*6777b538SAndroid Build Coastguard Worker // `static_assert()` if the type does not support unretained. This is meant only
125*6777b538SAndroid Build Coastguard Worker // for use inside the `Bind()` machinery, which wants that assertion.
126*6777b538SAndroid Build Coastguard Worker //
127*6777b538SAndroid Build Coastguard Worker // If we ever want to use this concept outside that machinery, we'll need to not
128*6777b538SAndroid Build Coastguard Worker // only move the "allows unretained" assertion from above to the `Bind()` side,
129*6777b538SAndroid Build Coastguard Worker // we'll also need to hoist or duplicate the incomplete type check there (and
130*6777b538SAndroid Build Coastguard Worker // not assert in that case) so it does not fire multiple `static_assert()`s for
131*6777b538SAndroid Build Coastguard Worker // incomplete types.
132*6777b538SAndroid Build Coastguard Worker template <typename T>
133*6777b538SAndroid Build Coastguard Worker concept SupportsUnretained = SupportsUnretainedImpl<T>::value;
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker }  // namespace base::internal
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker #endif  // BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_
138