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