diff --git a/absl/base/nullability.h b/absl/base/nullability.h index 2ffc840bbd4..37e910ac91c 100644 --- a/absl/base/nullability.h +++ b/absl/base/nullability.h @@ -16,21 +16,21 @@ // File: nullability.h // ----------------------------------------------------------------------------- // -// This header file defines a set of "templated annotations" for designating the -// expected nullability of pointers. These annotations allow you to designate -// pointers in one of three classification states: +// This header file defines a set of annotations for designating the expected +// nullability of pointers. These annotations allow you to designate pointers in +// one of three classification states: // -// * "Non-null" (for pointers annotated `Nonnull`), indicating that it is +// * "Non-null" (for pointers annotated `absl_nonnull`), indicating that it is // invalid for the given pointer to ever be null. -// * "Nullable" (for pointers annotated `Nullable`), indicating that it is +// * "Nullable" (for pointers annotated `absl_nullable`), indicating that it is // valid for the given pointer to be null. -// * "Unknown" (for pointers annotated `NullabilityUnknown`), indicating -// that the given pointer has not been yet classified as either nullable or +// * "Unknown" (for pointers annotated `absl_nullability_unknown`), indicating +// that the given pointer has not yet been classified as either nullable or // non-null. This is the default state of unannotated pointers. // -// NOTE: unannotated pointers implicitly bear the annotation -// `NullabilityUnknown`; you should rarely, if ever, see this annotation used -// in the codebase explicitly. +// NOTE: Unannotated pointers implicitly bear the annotation +// `absl_nullability_unknown`; you should rarely, if ever, see this annotation +// used in the codebase explicitly. // // ----------------------------------------------------------------------------- // Nullability and Contracts @@ -64,16 +64,46 @@ // formalize those contracts within the codebase. // // ----------------------------------------------------------------------------- +// Annotation Syntax +// ----------------------------------------------------------------------------- +// +// The annotations should be positioned as a qualifier for the pointer type. For +// example, the position of `const` when declaring a const pointer (not a +// pointer to a const type) is the position you should also use for these +// annotations. +// +// Example: +// +// // A const non-null pointer to an `Employee`. +// Employee* absl_nonnull const e; +// +// // A non-null pointer to a const `Employee`. +// const Employee* absl_nonnull e; +// +// // A non-null pointer to a const nullable pointer to an `Employee`. +// Employee* absl_nullable const* absl_nonnull e = nullptr; +// +// // A non-null function pointer. +// void (*absl_nonnull func)(int, double); +// +// // A non-null std::unique_ptr to an `Employee`. +// // As with `const`, it is possible to place the annotation on either side of +// // a named type not ending in `*`, but placing it before the type it +// // describes is preferred, unless inconsistent with surrounding code. +// absl_nonnull std::unique_ptr employee; +// +// // Invalid annotation usage – this attempts to declare a pointer to a +// // nullable `Employee`, which is meaningless. +// absl_nullable Employee* e; +// +// ----------------------------------------------------------------------------- // Using Nullability Annotations // ----------------------------------------------------------------------------- // -// It is important to note that these annotations are not distinct strong -// *types*. They are alias templates defined to be equal to the underlying -// pointer type. A pointer annotated `Nonnull`, for example, is simply a -// pointer of type `T*`. Each annotation acts as a form of documentation about -// the contract for the given pointer. Each annotation requires providers or -// consumers of these pointers across API boundaries to take appropriate steps -// when setting or using these pointers: +// Each annotation acts as a form of documentation about the contract for the +// given pointer. Each annotation requires providers or consumers of these +// pointers across API boundaries to take appropriate steps when setting or +// using these pointers: // // * "Non-null" pointers should never be null. It is the responsibility of the // provider of this pointer to ensure that the pointer may never be set to @@ -91,20 +121,20 @@ // Example: // // // PaySalary() requires the passed pointer to an `Employee` to be non-null. -// void PaySalary(absl::Nonnull e) { +// void PaySalary(Employee* absl_nonnull e) { // pay(e->salary); // OK to dereference // } // // // CompleteTransaction() guarantees the returned pointer to an `Account` to // // be non-null. -// absl::Nonnull balance CompleteTransaction(double fee) { +// Account* absl_nonnull balance CompleteTransaction(double fee) { // ... // } // // // Note that specifying a nullability annotation does not prevent someone // // from violating the contract: // -// Nullable find(Map& employees, std::string_view name); +// Employee* absl_nullable find(Map& employees, std::string_view name); // // void g(Map& employees) { // Employee *e = find(employees, "Pat"); @@ -144,8 +174,8 @@ // These nullability annotations are primarily a human readable signal about the // intended contract of the pointer. They are not *types* and do not currently // provide any correctness guarantees. For example, a pointer annotated as -// `Nonnull` is *not guaranteed* to be non-null, and the compiler won't -// alert or prevent assignment of a `Nullable` to a `Nonnull`. +// `absl_nonnull` is *not guaranteed* to be non-null, and the compiler won't +// alert or prevent assignment of a `T* absl_nullable` to a `T* absl_nonnull`. // =========================================================================== #ifndef ABSL_BASE_NULLABILITY_H_ #define ABSL_BASE_NULLABILITY_H_ @@ -168,14 +198,14 @@ // ABSL_POINTERS_DEFAULT_NONNULL // // void FillMessage(Message *m); // implicitly non-null -// absl::Nullable GetNullablePtr(); // explicitly nullable -// absl::NullabilityUnknown GetUnknownPtr(); // explicitly unknown +// T* absl_nullable GetNullablePtr(); // explicitly nullable +// T* absl_nullability_unknown GetUnknownPtr(); // explicitly unknown // -// The macro can be safely used in header files -- it will not affect any files +// The macro can be safely used in header files – it will not affect any files // that include it. // -// In files with the macro, plain `T*` syntax means `absl::Nonnull`, and the -// exceptions (`Nullable` and `NullabilityUnknown`) must be marked +// In files with the macro, plain `T*` syntax means `T* absl_nonnull`, and the +// exceptions (`absl_nullable` and `absl_nullability_unknown`) must be marked // explicitly. The same holds, correspondingly, for smart pointer types. // // For comparison, without the macro, all unannotated pointers would default to @@ -183,17 +213,15 @@ // // #include "absl/base/nullability.h" // -// void FillMessage(absl::Nonnull m); // explicitly non-null -// absl::Nullable GetNullablePtr(); // explicitly nullable +// void FillMessage(Message* absl_nonnull m); // explicitly non-null +// T* absl_nullable GetNullablePtr(); // explicitly nullable // T* GetUnknownPtr(); // implicitly unknown // // No-op except for being a human readable signal. #define ABSL_POINTERS_DEFAULT_NONNULL -namespace absl { -ABSL_NAMESPACE_BEGIN - -// absl::Nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`) +#if defined(__clang__) && !defined(__OBJC__) +// absl_nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`) // // The indicated pointer is never null. It is the responsibility of the provider // of this pointer across an API boundary to ensure that the pointer is never @@ -203,13 +231,12 @@ ABSL_NAMESPACE_BEGIN // Example: // // // `employee` is designated as not null. -// void PaySalary(absl::Nonnull employee) { +// void PaySalary(Employee* absl_nonnull employee) { // pay(*employee); // OK to dereference // } -template -using Nonnull = nullability_internal::NonnullImpl; +#define absl_nonnull _Nonnull -// absl::Nullable +// absl_nullable // // The indicated pointer may, by design, be either null or non-null. Consumers // of this pointer across an API boundary should perform a `nullptr` check @@ -218,15 +245,14 @@ using Nonnull = nullability_internal::NonnullImpl; // Example: // // // `employee` may be null. -// void PaySalary(absl::Nullable employee) { +// void PaySalary(Employee* absl_nullable employee) { // if (employee != nullptr) { // Pay(*employee); // OK to dereference // } // } -template -using Nullable = nullability_internal::NullableImpl; +#define absl_nullable _Nullable -// absl::NullabilityUnknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`) +// absl_nullability_unknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`) // // The indicated pointer has not yet been determined to be definitively // "non-null" or "nullable." Providers of such pointers across API boundaries @@ -234,8 +260,8 @@ using Nullable = nullability_internal::NullableImpl; // Consumers of these pointers across an API boundary should treat such pointers // with the same caution they treat currently unannotated pointers. Most // existing code will have "unknown" pointers, which should eventually be -// migrated into one of the above two nullability states: `Nonnull` or -// `Nullable`. +// migrated into one of the above two nullability states: `absl_nonnull` or +// `absl_nullable`. // // NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`, // because this annotation is the global default state, unannotated pointers are @@ -245,7 +271,7 @@ using Nullable = nullability_internal::NullableImpl; // Example: // // // `employee`s nullability state is unknown. -// void PaySalary(absl::NullabilityUnknown employee) { +// void PaySalary(Employee* absl_nullability_unknown employee) { // Pay(*employee); // Potentially dangerous. API provider should investigate. // } // @@ -256,11 +282,15 @@ using Nullable = nullability_internal::NullableImpl; // void PaySalary(Employee* employee) { // Pay(*employee); // Potentially dangerous. API provider should investigate. // } -template -using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl; - -ABSL_NAMESPACE_END -} // namespace absl +#define absl_nullability_unknown _Null_unspecified +#else +// No-op for non-Clang compilers or Objective-C. +#define absl_nonnull +// No-op for non-Clang compilers or Objective-C. +#define absl_nullable +// No-op for non-Clang compilers or Objective-C. +#define absl_nullability_unknown +#endif // ABSL_NULLABILITY_COMPATIBLE // @@ -281,26 +311,46 @@ ABSL_NAMESPACE_END #define ABSL_NULLABILITY_COMPATIBLE #endif -// absl_nonnull -// absl_nullable -// absl_nullability_unknown +namespace absl { +ABSL_NAMESPACE_BEGIN + +// The following template aliases are alternate forms of the macro annotations +// above. They have some limitations, for example, an incompatibility with +// `auto*` pointers, as `auto` cannot be used in a template argument. // -// These macros are analogues of the alias template nullability annotations -// above. +// It is important to note that these annotations are not distinct strong +// *types*. They are alias templates defined to be equal to the underlying +// pointer type. A pointer annotated `Nonnull`, for example, is simply a +// pointer of type `T*`. + +// absl::Nonnull, analogous to absl_nonnull // // Example: -// int* absl_nullable foo; +// absl::Nonnull foo; // Is equivalent to: +// int* absl_nonnull foo; +template +using Nonnull = nullability_internal::NonnullImpl; + +// absl::Nullable, analogous to absl_nullable +// +// Example: // absl::Nullable foo; -#if defined(__clang__) && !defined(__OBJC__) && \ - ABSL_HAVE_FEATURE(nullability_on_classes) -#define absl_nonnull _Nonnull -#define absl_nullable _Nullable -#define absl_nullability_unknown _Null_unspecified -#else -#define absl_nonnull -#define absl_nullable -#define absl_nullability_unknown -#endif +// Is equivalent to: +// int* absl_nullable foo; +template +using Nullable = nullability_internal::NullableImpl; + +// absl::NullabilityUnknown, analogous to absl_nullability_unknown +// +// Example: +// absl::NullabilityUnknown foo; +// Is equivalent to: +// int* absl_nullability_unknown foo; +template +using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl; + +ABSL_NAMESPACE_END +} // namespace absl #endif // ABSL_BASE_NULLABILITY_H_