Add Nullability annotations to Abseil.

PiperOrigin-RevId: 541915097
Change-Id: I7ebfbafc36db38b59b30ab5b312cd7e22082a805
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index b64f133..f8dea45 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -26,6 +26,7 @@
   "base/internal/low_level_alloc.cc"
   "base/internal/low_level_alloc.h"
   "base/internal/low_level_scheduling.h"
+  "base/internal/nullability_impl.h"
   "base/internal/per_thread_tls.h"
   "base/internal/prefetch.h"
   "base/prefetch.h"
@@ -56,6 +57,7 @@
   "base/log_severity.cc"
   "base/log_severity.h"
   "base/macros.h"
+  "base/nullability.h"
   "base/optimization.h"
   "base/options.h"
   "base/policy_checks.h"
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 28cbf28..fb008db 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -63,6 +63,18 @@
 )
 
 cc_library(
+    name = "nullability",
+    srcs = ["internal/nullability_impl.h"],
+    hdrs = ["nullability.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":core_headers",
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_library(
     name = "raw_logging_internal",
     srcs = ["internal/raw_logging.cc"],
     hdrs = ["internal/raw_logging.h"],
@@ -553,6 +565,16 @@
 )
 
 cc_test(
+    name = "nullability_test",
+    srcs = ["nullability_test.cc"],
+    deps = [
+        ":core_headers",
+        ":nullability",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "raw_logging_test",
     srcs = ["raw_logging_test.cc"],
     copts = ABSL_TEST_COPTS,
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 71b9379..76c4ff1 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -54,6 +54,33 @@
     ${ABSL_DEFAULT_COPTS}
 )
 
+absl_cc_library(
+  NAME
+    nullability
+  HDRS
+    "nullability.h"
+  SRCS
+    "internal/nullability_impl.h"
+  DEPS
+    absl::core_headers
+    absl::type_traits
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_test(
+  NAME
+    nullability_test
+  SRCS
+    "nullability_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::core_headers
+    absl::nullability
+    GTest::gtest_main
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
diff --git a/absl/base/internal/nullability_impl.h b/absl/base/internal/nullability_impl.h
new file mode 100644
index 0000000..74f4a41
--- /dev/null
+++ b/absl/base/internal/nullability_impl.h
@@ -0,0 +1,106 @@
+// Copyright 2023 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
+#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
+
+#include <memory>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+
+namespace nullability_internal {
+
+// `IsNullabilityCompatible` checks whether its first argument is a class
+// explicitly tagged as supporting nullability annotations. The tag is the type
+// declaration `absl_nullability_compatible`.
+template <typename, typename = void>
+struct IsNullabilityCompatible : std::false_type {};
+
+template <typename T>
+struct IsNullabilityCompatible<
+    T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
+};
+
+template <typename T>
+constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;
+
+template <typename T>
+constexpr bool IsSupportedType<T*> = true;
+
+template <typename T, typename U>
+constexpr bool IsSupportedType<T U::*> = true;
+
+template <typename T, typename... Deleter>
+constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;
+
+template <typename T>
+constexpr bool IsSupportedType<std::shared_ptr<T>> = true;
+
+template <typename T>
+struct EnableNullable {
+  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+                "Template argument must be a raw or supported smart pointer "
+                "type. See absl/base/nullability.h.");
+  using type = T;
+};
+
+template <typename T>
+struct EnableNonNull {
+  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+                "Template argument must be a raw or supported smart pointer "
+                "type. See absl/base/nullability.h.");
+  using type = T;
+};
+
+template <typename T>
+struct EnableNullabilityUnknown {
+  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
+                "Template argument must be a raw or supported smart pointer "
+                "type. See absl/base/nullability.h.");
+  using type = T;
+};
+
+// Note: we do not apply Clang nullability attributes (e.g. _Nullable).  These
+// only support raw pointers, and conditionally enabling them only for raw
+// pointers inhibits template arg deduction.  Ideally, they would support all
+// pointer-like types.
+template <typename T, typename = typename EnableNullable<T>::type>
+using NullableImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nullable")]]
+#endif
+    = T;
+
+template <typename T, typename = typename EnableNonNull<T>::type>
+using NonNullImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nonnull")]]
+#endif
+    = T;
+
+template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
+using NullabilityUnknownImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nullability_Unspecified")]]
+#endif
+    = T;
+
+}  // namespace nullability_internal
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
diff --git a/absl/base/nullability.h b/absl/base/nullability.h
new file mode 100644
index 0000000..42525dd
--- /dev/null
+++ b/absl/base/nullability.h
@@ -0,0 +1,224 @@
+// Copyright 2023 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// 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:
+//
+//  * "Non-null" (for pointers annotated `NonNull<T>`), indicating that it is
+//    invalid for the given pointer to ever be null.
+//  * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is
+//    valid for the given pointer to be null.
+//  * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating
+//    that the given pointer has not been yet classified as either nullable or
+//    non-null. This is the default state of unannotated pointers.
+//
+// NOTE: unannotated pointers implicitly bear the annotation
+// `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used
+// in the codebase explicitly.
+//
+// -----------------------------------------------------------------------------
+// Nullability and Contracts
+// -----------------------------------------------------------------------------
+//
+// These nullability annotations allow you to more clearly specify contracts on
+// software components by narrowing the *preconditions*, *postconditions*, and
+// *invariants* of pointer state(s) in any given interface. It then depends on
+// context who is responsible for fulfilling the annotation's requirements.
+//
+// For example, a function may receive a pointer argument. Designating that
+// pointer argument as "non-null" tightens the precondition of the contract of
+// that function. It is then the responsibility of anyone calling such a
+// function to ensure that the passed pointer is not null.
+//
+// Similarly, a function may have a pointer as a return value. Designating that
+// return value as "non-null" tightens the postcondition of the contract of that
+// function. In this case, however, it is the responsibility of the function
+// itself to ensure that the returned pointer is not null.
+//
+// Clearly defining these contracts allows providers (and consumers) of such
+// pointers to have more confidence in their null state. If a function declares
+// a return value as "non-null", for example, the caller should not need to
+// check whether the returned value is `nullptr`; it can simply assume the
+// pointer is valid.
+//
+// Of course most interfaces already have expectations on the nullability state
+// of pointers, and these expectations are, in effect, a contract; often,
+// however, those contracts are either poorly or partially specified, assumed,
+// or misunderstood. These nullability annotations are designed to allow you to
+// formalize those contracts within the codebase.
+//
+// -----------------------------------------------------------------------------
+// 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<T*>`, 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:
+//
+// * "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
+//   null. Consumers of such pointers can treat such pointers as non-null.
+// * "Nullable" pointers may or may not be null. Consumers of such pointers
+//   should precede any usage of that pointer (e.g. a dereference operation)
+//   with a a `nullptr` check.
+// * "Unknown" pointers may be either "non-null" or "nullable" but have not been
+//   definitively determined to be in either classification state. Providers of
+//   such pointers across API boundaries should determine --  over time -- to
+//   annotate the pointer in either of the above two states. Consumers of such
+//   pointers across an API boundary should continue to treat such pointers as
+//   they currently do.
+//
+// Example:
+//
+// // PaySalary() requires the passed pointer to an `Employee` to be non-null.
+// void PaySalary(absl::NonNull<Employee *> e) {
+//   pay(e->salary);  // OK to dereference
+// }
+//
+// // CompleteTransaction() guarantees the returned pointer to an `Account` to
+// // be non-null.
+// absl::NonNull<Account *> balance CompleteTransaction(double fee) {
+// ...
+// }
+//
+// // Note that specifying a nullability annotation does not prevent someone
+// // from violating the contract:
+//
+// Nullable<Employee *> find(Map& employees, std::string_view name);
+//
+// void g(Map& employees) {
+//   Employee *e = find(employees, "Pat");
+//   // `e` can now be null.
+//   PaySalary(e); // Violates contract, but compiles!
+// }
+//
+// Nullability annotations, in other words, are useful for defining and
+// narrowing contracts; *enforcement* of those contracts depends on use and any
+// additional (static or dynamic analysis) tooling.
+//
+// NOTE: The "unknown" annotation state indicates that a pointer's contract has
+// not yet been positively identified. The unknown state therefore acts as a
+// form of documentation of your technical debt, and a codebase that adopts
+// nullability annotations should aspire to annotate every pointer as either
+// "non-null" or "nullable".
+//
+// -----------------------------------------------------------------------------
+// Applicability of Nullability Annotations
+// -----------------------------------------------------------------------------
+//
+// By default, nullability annotations are applicable to raw and smart
+// pointers. User-defined types can indicate compatibility with nullability
+// annotations by providing an `absl_nullability_compatible` nested type. The
+// actual definition of this inner type is not relevant as it is used merely as
+// a marker. It is common to use a using declaration of
+// `absl_nullability_compatible` set to void.
+//
+// // Example:
+// struct MyPtr {
+//   using absl_nullability_compatible = void;
+//   ...
+// };
+//
+// DISCLAIMER:
+// ===========================================================================
+// 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<T*>` is *not guaranteed* to be non-null, and the compiler won't
+// alert or prevent assignment of a `Nullable<T*>` to a `NonNull<T*>`.
+// ===========================================================================
+#ifndef ABSL_BASE_NULLABILITY_H_
+#define ABSL_BASE_NULLABILITY_H_
+
+#include "absl/base/internal/nullability_impl.h"
+
+namespace absl {
+
+// absl::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 be
+// set to null. Consumers of this pointer across an API boundary may safely
+// dereference the pointer.
+//
+// Example:
+//
+// // `employee` is designated as not null.
+// void PaySalary(absl::NotNull<Employee *> employee) {
+//   pay(*employee);  // OK to dereference
+// }
+template <typename T>
+using NonNull = nullability_internal::NonNullImpl<T>;
+
+// 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
+// before performing any operation using the pointer.
+//
+// Example:
+//
+// // `employee` may  be null.
+// void PaySalary(absl::Nullable<Employee *> employee) {
+//   if (employee != nullptr) {
+//     Pay(*employee);  // OK to dereference
+//   }
+// }
+template <typename T>
+using Nullable = nullability_internal::NullableImpl<T>;
+
+// absl::NullabilityUnknown (default)
+//
+// The indicated pointer has not yet been determined to be definitively
+// "non-null" or "nullable." Providers of such pointers across API boundaries
+// should, over time, annotate such pointers as either "non-null" or "nullable."
+// 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<T>` or
+//  `Nullable<T>`.
+//
+// NOTE: Because this annotation is the global default state, pointers without
+// any annotation are assumed to have "unknown" semantics. This assumption is
+// designed to minimize churn and reduce clutter within the codebase.
+//
+// Example:
+//
+// // `employee`s nullability state is unknown.
+// void PaySalary(absl::NullabilityUnknown<Employee *> employee) {
+//   Pay(*employee); // Potentially dangerous. API provider should investigate.
+// }
+//
+// Note that a pointer without an annotation, by default, is assumed to have the
+// annotation `NullabilityUnknown`.
+//
+// // `employee`s nullability state is unknown.
+// void PaySalary(Employee* employee) {
+//   Pay(*employee); // Potentially dangerous. API provider should investigate.
+// }
+template <typename T>
+using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;
+
+}  // namespace absl
+
+#endif  // ABSL_BASE_NULLABILITY_H_
diff --git a/absl/base/nullability_test.cc b/absl/base/nullability_test.cc
new file mode 100644
index 0000000..6edd7cd
--- /dev/null
+++ b/absl/base/nullability_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2023 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/nullability.h"
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+
+namespace {
+using ::absl::NonNull;
+using ::absl::NullabilityUnknown;
+using ::absl::Nullable;
+
+void funcWithNonnullArg(NonNull<int*> /*arg*/) {}
+template <typename T>
+void funcWithDeducedNonnullArg(NonNull<T*> /*arg*/) {}
+
+TEST(NonNullTest, NonNullArgument) {
+  int var = 0;
+  funcWithNonnullArg(&var);
+  funcWithDeducedNonnullArg(&var);
+}
+
+NonNull<int*> funcWithNonnullReturn() {
+  static int var = 0;
+  return &var;
+}
+
+TEST(NonNullTest, NonNullReturn) {
+  auto var = funcWithNonnullReturn();
+  (void)var;
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToInt) {
+  EXPECT_TRUE((std::is_same<NonNull<int*>, int*>::value));
+  EXPECT_TRUE((std::is_same<Nullable<int*>, int*>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<int*>, int*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToVoid) {
+  EXPECT_TRUE((std::is_same<NonNull<void*>, void*>::value));
+  EXPECT_TRUE((std::is_same<Nullable<void*>, void*>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<void*>, void*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughUniquePointerToInt) {
+  using T = std::unique_ptr<int>;
+  EXPECT_TRUE((std::is_same<NonNull<T>, T>::value));
+  EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToInt) {
+  using T = std::shared_ptr<int>;
+  EXPECT_TRUE((std::is_same<NonNull<T>, T>::value));
+  EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToVoid) {
+  using T = std::shared_ptr<void>;
+  EXPECT_TRUE((std::is_same<NonNull<T>, T>::value));
+  EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberObject) {
+  using T = decltype(&std::pair<int, int>::first);
+  EXPECT_TRUE((std::is_same<NonNull<T>, T>::value));
+  EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberFunction) {
+  using T = decltype(&std::unique_ptr<int>::reset);
+  EXPECT_TRUE((std::is_same<NonNull<T>, T>::value));
+  EXPECT_TRUE((std::is_same<Nullable<T>, T>::value));
+  EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
+}
+
+}  // namespace
+
+// Nullable ADL lookup test
+namespace util {
+// Helper for NullableAdlTest.  Returns true, denoting that argument-dependent
+// lookup found this implementation of DidAdlWin.  Must be in namespace
+// util itself, not a nested anonymous namespace.
+template <typename T>
+bool DidAdlWin(T*) {
+  return true;
+}
+
+// Because this type is defined in namespace util, an unqualified call to
+// DidAdlWin with a pointer to MakeAdlWin will find the above implementation.
+struct MakeAdlWin {};
+}  // namespace util
+
+namespace {
+// Returns false, denoting that ADL did not inspect namespace util.  If it
+// had, the better match (T*) above would have won out over the (...) here.
+bool DidAdlWin(...) { return false; }
+
+TEST(NullableAdlTest, NullableAddsNothingToArgumentDependentLookup) {
+  // Treatment: util::Nullable<int*> contributes nothing to ADL because
+  // int* itself doesn't.
+  EXPECT_FALSE(DidAdlWin((int*)nullptr));
+  EXPECT_FALSE(DidAdlWin((Nullable<int*>)nullptr));
+
+  // Control: Argument-dependent lookup does find the implementation in
+  // namespace util when the underlying pointee type resides there.
+  EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr));
+  EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr));
+}
+}  // namespace