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