1 // Copyright 2023 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: nullability.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This header file defines a set of "templated annotations" for designating the 20 // expected nullability of pointers. These annotations allow you to designate 21 // pointers in one of three classification states: 22 // 23 // * "Non-null" (for pointers annotated `Nonnull<T>`), indicating that it is 24 // invalid for the given pointer to ever be null. 25 // * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is 26 // valid for the given pointer to be null. 27 // * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating 28 // that the given pointer has not been yet classified as either nullable or 29 // non-null. This is the default state of unannotated pointers. 30 // 31 // NOTE: unannotated pointers implicitly bear the annotation 32 // `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used 33 // in the codebase explicitly. 34 // 35 // ----------------------------------------------------------------------------- 36 // Nullability and Contracts 37 // ----------------------------------------------------------------------------- 38 // 39 // These nullability annotations allow you to more clearly specify contracts on 40 // software components by narrowing the *preconditions*, *postconditions*, and 41 // *invariants* of pointer state(s) in any given interface. It then depends on 42 // context who is responsible for fulfilling the annotation's requirements. 43 // 44 // For example, a function may receive a pointer argument. Designating that 45 // pointer argument as "non-null" tightens the precondition of the contract of 46 // that function. It is then the responsibility of anyone calling such a 47 // function to ensure that the passed pointer is not null. 48 // 49 // Similarly, a function may have a pointer as a return value. Designating that 50 // return value as "non-null" tightens the postcondition of the contract of that 51 // function. In this case, however, it is the responsibility of the function 52 // itself to ensure that the returned pointer is not null. 53 // 54 // Clearly defining these contracts allows providers (and consumers) of such 55 // pointers to have more confidence in their null state. If a function declares 56 // a return value as "non-null", for example, the caller should not need to 57 // check whether the returned value is `nullptr`; it can simply assume the 58 // pointer is valid. 59 // 60 // Of course most interfaces already have expectations on the nullability state 61 // of pointers, and these expectations are, in effect, a contract; often, 62 // however, those contracts are either poorly or partially specified, assumed, 63 // or misunderstood. These nullability annotations are designed to allow you to 64 // formalize those contracts within the codebase. 65 // 66 // ----------------------------------------------------------------------------- 67 // Using Nullability Annotations 68 // ----------------------------------------------------------------------------- 69 // 70 // It is important to note that these annotations are not distinct strong 71 // *types*. They are alias templates defined to be equal to the underlying 72 // pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a 73 // pointer of type `T*`. Each annotation acts as a form of documentation about 74 // the contract for the given pointer. Each annotation requires providers or 75 // consumers of these pointers across API boundaries to take appropriate steps 76 // when setting or using these pointers: 77 // 78 // * "Non-null" pointers should never be null. It is the responsibility of the 79 // provider of this pointer to ensure that the pointer may never be set to 80 // null. Consumers of such pointers can treat such pointers as non-null. 81 // * "Nullable" pointers may or may not be null. Consumers of such pointers 82 // should precede any usage of that pointer (e.g. a dereference operation) 83 // with a a `nullptr` check. 84 // * "Unknown" pointers may be either "non-null" or "nullable" but have not been 85 // definitively determined to be in either classification state. Providers of 86 // such pointers across API boundaries should determine -- over time -- to 87 // annotate the pointer in either of the above two states. Consumers of such 88 // pointers across an API boundary should continue to treat such pointers as 89 // they currently do. 90 // 91 // Example: 92 // 93 // // PaySalary() requires the passed pointer to an `Employee` to be non-null. 94 // void PaySalary(absl::Nonnull<Employee *> e) { 95 // pay(e->salary); // OK to dereference 96 // } 97 // 98 // // CompleteTransaction() guarantees the returned pointer to an `Account` to 99 // // be non-null. 100 // absl::Nonnull<Account *> balance CompleteTransaction(double fee) { 101 // ... 102 // } 103 // 104 // // Note that specifying a nullability annotation does not prevent someone 105 // // from violating the contract: 106 // 107 // Nullable<Employee *> find(Map& employees, std::string_view name); 108 // 109 // void g(Map& employees) { 110 // Employee *e = find(employees, "Pat"); 111 // // `e` can now be null. 112 // PaySalary(e); // Violates contract, but compiles! 113 // } 114 // 115 // Nullability annotations, in other words, are useful for defining and 116 // narrowing contracts; *enforcement* of those contracts depends on use and any 117 // additional (static or dynamic analysis) tooling. 118 // 119 // NOTE: The "unknown" annotation state indicates that a pointer's contract has 120 // not yet been positively identified. The unknown state therefore acts as a 121 // form of documentation of your technical debt, and a codebase that adopts 122 // nullability annotations should aspire to annotate every pointer as either 123 // "non-null" or "nullable". 124 // 125 // ----------------------------------------------------------------------------- 126 // Applicability of Nullability Annotations 127 // ----------------------------------------------------------------------------- 128 // 129 // By default, nullability annotations are applicable to raw and smart 130 // pointers. User-defined types can indicate compatibility with nullability 131 // annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute. 132 // 133 // // Example: 134 // struct ABSL_NULLABILITY_COMPATIBLE MyPtr { 135 // ... 136 // }; 137 // 138 // Note: For the time being, nullability-compatible classes should additionally 139 // be marked with an `absl_nullability_compatible` nested type (this will soon 140 // be deprecated). The actual definition of this inner type is not relevant as 141 // it is used merely as a marker. It is common to use a using declaration of 142 // `absl_nullability_compatible` set to void. 143 // 144 // // Example: 145 // struct MyPtr { 146 // using absl_nullability_compatible = void; 147 // ... 148 // }; 149 // 150 // DISCLAIMER: 151 // =========================================================================== 152 // These nullability annotations are primarily a human readable signal about the 153 // intended contract of the pointer. They are not *types* and do not currently 154 // provide any correctness guarantees. For example, a pointer annotated as 155 // `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't 156 // alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`. 157 // =========================================================================== 158 #ifndef ABSL_BASE_NULLABILITY_H_ 159 #define ABSL_BASE_NULLABILITY_H_ 160 161 #include "absl/base/config.h" 162 #include "absl/base/internal/nullability_impl.h" 163 164 namespace absl { 165 ABSL_NAMESPACE_BEGIN 166 167 // absl::Nonnull 168 // 169 // The indicated pointer is never null. It is the responsibility of the provider 170 // of this pointer across an API boundary to ensure that the pointer is never 171 // set to null. Consumers of this pointer across an API boundary may safely 172 // dereference the pointer. 173 // 174 // Example: 175 // 176 // // `employee` is designated as not null. 177 // void PaySalary(absl::Nonnull<Employee *> employee) { 178 // pay(*employee); // OK to dereference 179 // } 180 template <typename T> 181 using Nonnull = nullability_internal::NonnullImpl<T>; 182 183 // absl::Nullable 184 // 185 // The indicated pointer may, by design, be either null or non-null. Consumers 186 // of this pointer across an API boundary should perform a `nullptr` check 187 // before performing any operation using the pointer. 188 // 189 // Example: 190 // 191 // // `employee` may be null. 192 // void PaySalary(absl::Nullable<Employee *> employee) { 193 // if (employee != nullptr) { 194 // Pay(*employee); // OK to dereference 195 // } 196 // } 197 template <typename T> 198 using Nullable = nullability_internal::NullableImpl<T>; 199 200 // absl::NullabilityUnknown (default) 201 // 202 // The indicated pointer has not yet been determined to be definitively 203 // "non-null" or "nullable." Providers of such pointers across API boundaries 204 // should, over time, annotate such pointers as either "non-null" or "nullable." 205 // Consumers of these pointers across an API boundary should treat such pointers 206 // with the same caution they treat currently unannotated pointers. Most 207 // existing code will have "unknown" pointers, which should eventually be 208 // migrated into one of the above two nullability states: `Nonnull<T>` or 209 // `Nullable<T>`. 210 // 211 // NOTE: Because this annotation is the global default state, unannotated 212 // pointers are assumed to have "unknown" semantics. This assumption is designed 213 // to minimize churn and reduce clutter within the codebase. 214 // 215 // Example: 216 // 217 // // `employee`s nullability state is unknown. 218 // void PaySalary(absl::NullabilityUnknown<Employee *> employee) { 219 // Pay(*employee); // Potentially dangerous. API provider should investigate. 220 // } 221 // 222 // Note that a pointer without an annotation, by default, is assumed to have the 223 // annotation `NullabilityUnknown`. 224 // 225 // // `employee`s nullability state is unknown. 226 // void PaySalary(Employee* employee) { 227 // Pay(*employee); // Potentially dangerous. API provider should investigate. 228 // } 229 template <typename T> 230 using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>; 231 232 ABSL_NAMESPACE_END 233 } // namespace absl 234 235 // ABSL_NULLABILITY_COMPATIBLE 236 // 237 // Indicates that a class is compatible with nullability annotations. 238 // 239 // For example: 240 // 241 // struct ABSL_NULLABILITY_COMPATIBLE MyPtr { 242 // ... 243 // }; 244 #if ABSL_HAVE_FEATURE(nullability_on_classes) 245 #define ABSL_NULLABILITY_COMPATIBLE _Nullable 246 #else 247 #define ABSL_NULLABILITY_COMPATIBLE 248 #endif 249 250 #endif // ABSL_BASE_NULLABILITY_H_ 251