// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details #pragma once #include "Luau/Common.h" #include <functional> namespace Luau { /** A non-owning, non-null pointer to a T. * * A NotNull<T> is notionally identical to a T* with the added restriction that * it can never store nullptr. * * The sole conversion rule from T* to NotNull<T> is the single-argument * constructor, which is intentionally marked explicit. This constructor * performs a runtime test to verify that the passed pointer is never nullptr. * * Pointer arithmetic, increment, decrement, and array indexing are all * forbidden. * * An implicit coersion from NotNull<T> to T* is afforded, as are the pointer * indirection and member access operators. (*p and p->prop) * * The explicit delete statement is permitted (but not recommended) on a * NotNull<T> through this implicit conversion. */ template<typename T> struct NotNull { explicit NotNull(T* t) : ptr(t) { LUAU_ASSERT(t); } explicit NotNull(std::nullptr_t) = delete; void operator=(std::nullptr_t) = delete; template<typename U> NotNull(NotNull<U> other) : ptr(other.get()) { } operator T*() const noexcept { return ptr; } T& operator*() const noexcept { return *ptr; } T* operator->() const noexcept { return ptr; } template<typename U> bool operator==(NotNull<U> other) const noexcept { return get() == other.get(); } template<typename U> bool operator!=(NotNull<U> other) const noexcept { return get() != other.get(); } operator bool() const noexcept = delete; T& operator[](int) = delete; T& operator+(int) = delete; T& operator-(int) = delete; T* get() const noexcept { return ptr; } private: T* ptr; }; } // namespace Luau namespace std { template<typename T> struct hash<Luau::NotNull<T>> { size_t operator()(const Luau::NotNull<T>& p) const { return std::hash<T*>()(p.get()); } }; } // namespace std