• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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