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 providing an `absl_nullability_compatible` nested type. The 132 // actual definition of this inner type is not relevant as it is used merely as 133 // a marker. It is common to use a using declaration of 134 // `absl_nullability_compatible` set to void. 135 // 136 // // Example: 137 // struct MyPtr { 138 // using absl_nullability_compatible = void; 139 // ... 140 // }; 141 // 142 // DISCLAIMER: 143 // =========================================================================== 144 // These nullability annotations are primarily a human readable signal about the 145 // intended contract of the pointer. They are not *types* and do not currently 146 // provide any correctness guarantees. For example, a pointer annotated as 147 // `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't 148 // alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`. 149 // =========================================================================== 150 #ifndef ABSL_BASE_NULLABILITY_H_ 151 #define ABSL_BASE_NULLABILITY_H_ 152 153 #include "absl/base/internal/nullability_impl.h" 154 155 namespace absl { 156 157 // absl::Nonnull 158 // 159 // The indicated pointer is never null. It is the responsibility of the provider 160 // of this pointer across an API boundary to ensure that the pointer is never be 161 // set to null. Consumers of this pointer across an API boundary may safely 162 // dereference the pointer. 163 // 164 // Example: 165 // 166 // // `employee` is designated as not null. 167 // void PaySalary(absl::Nonnull<Employee *> employee) { 168 // pay(*employee); // OK to dereference 169 // } 170 template <typename T> 171 using Nonnull = nullability_internal::NonnullImpl<T>; 172 173 // absl::Nullable 174 // 175 // The indicated pointer may, by design, be either null or non-null. Consumers 176 // of this pointer across an API boundary should perform a `nullptr` check 177 // before performing any operation using the pointer. 178 // 179 // Example: 180 // 181 // // `employee` may be null. 182 // void PaySalary(absl::Nullable<Employee *> employee) { 183 // if (employee != nullptr) { 184 // Pay(*employee); // OK to dereference 185 // } 186 // } 187 template <typename T> 188 using Nullable = nullability_internal::NullableImpl<T>; 189 190 // absl::NullabilityUnknown (default) 191 // 192 // The indicated pointer has not yet been determined to be definitively 193 // "non-null" or "nullable." Providers of such pointers across API boundaries 194 // should, over time, annotate such pointers as either "non-null" or "nullable." 195 // Consumers of these pointers across an API boundary should treat such pointers 196 // with the same caution they treat currently unannotated pointers. Most 197 // existing code will have "unknown" pointers, which should eventually be 198 // migrated into one of the above two nullability states: `Nonnull<T>` or 199 // `Nullable<T>`. 200 // 201 // NOTE: Because this annotation is the global default state, pointers without 202 // any annotation are assumed to have "unknown" semantics. This assumption is 203 // designed to minimize churn and reduce clutter within the codebase. 204 // 205 // Example: 206 // 207 // // `employee`s nullability state is unknown. 208 // void PaySalary(absl::NullabilityUnknown<Employee *> employee) { 209 // Pay(*employee); // Potentially dangerous. API provider should investigate. 210 // } 211 // 212 // Note that a pointer without an annotation, by default, is assumed to have the 213 // annotation `NullabilityUnknown`. 214 // 215 // // `employee`s nullability state is unknown. 216 // void PaySalary(Employee* employee) { 217 // Pay(*employee); // Potentially dangerous. API provider should investigate. 218 // } 219 template <typename T> 220 using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>; 221 222 } // namespace absl 223 224 #endif // ABSL_BASE_NULLABILITY_H_ 225