util: Add util::NotNull<SmartPtrType> #34844

pull maflcko wants to merge 5 commits into bitcoin:master from maflcko:2603-not-null changing 8 files +541 −12
  1. maflcko commented at 7:42 PM on March 17, 2026: member

    The C++ standard library lacks a type to denote a smart pointer is not null. For raw pointer there is std::reference_wrapper, or a plain reference.

    Other third-party libraries provide such a type, such as gsl::strict_not_null. However, GSL's not_null requires copies and disallows moves of the underlying smart pointer, which is expensive and makes is impossible to use on a std::unique_ptr in real code.

    Fix all issues by adding util::NotNull<SmartPtrType>, which documents (and checks) that the inner pointer is never null. Only when the inner pointer was moved, it becomes null, even inside NotNull. However, this is fine, because with clang-tidy use-after-free is forbidden, so it will never be possible to observe the silent inner nullptr.

    This type can be used when passing never-null smart pointers between functions. It removes the need to Assert() the pointer before dereference. For example, in a getter function:

    util::NotNull<std::unique_ptr<Stats>> GetStats()
    {
        return util::NotNull{std::make_unique<Stats>()};
    }
    
    int main()
    {
        auto stats{GetStats()};
        stats->foo; // This can never lead to a nullptr deref
        // Assert(stats)->foo; // This is redundant and won't compile
    }
    

    Fixes https://github.com/bitcoin/bitcoin/issues/24423

  2. DrahtBot added the label Utils/log/libs on Mar 17, 2026
  3. DrahtBot commented at 7:43 PM on March 17, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK stickies-v

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    No conflicts as of last run.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  4. maflcko force-pushed on Mar 17, 2026
  5. DrahtBot added the label CI failed on Mar 17, 2026
  6. DrahtBot commented at 8:03 PM on March 17, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task test ancestor commits: https://github.com/bitcoin/bitcoin/actions/runs/23213194537/job/67467180922</sub> <sub>LLM reason (✨ experimental): Build failed during the cmake build, due to a compilation error in src/test/util_pointers_tests.cpp.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  7. stickies-v commented at 8:08 PM on March 17, 2026: contributor

    Concept ACK

  8. maflcko force-pushed on Mar 17, 2026
  9. maflcko commented at 9:41 PM on March 17, 2026: member

    Looks like C++20 CTAD alias templates are not supported with clang-18, so I replaced this one-liner with a more verbose alternative in the last force push.

     template <class T> using NotNull = gsl_detail::strict_not_null<T>;
    
  10. DrahtBot removed the label CI failed on Mar 17, 2026
  11. maflcko force-pushed on Mar 24, 2026
  12. maflcko force-pushed on Mar 24, 2026
  13. DrahtBot added the label CI failed on Mar 24, 2026
  14. DrahtBot removed the label CI failed on Mar 24, 2026
  15. util: Add util::NotNull<AnyPtrType>
    Based on gsl::strict_not_null, with minimal modifications.
    
    It can be reviewed by calling
    
    curl -fL 'https://raw.githubusercontent.com/microsoft/GSL/688ffcde9018910bef22dae9da9de974803dc982/include/gsl/pointers' -o ./src/util/pointers.h
    
    and then confirming that the difference is documented and correct.
    fa7e2360a2
  16. util: Allow util::NotNull to be moved faff7d210a
  17. refactor: Use util::NotNull<std::unique_ptr<LevelDBContext>> m_db_context
    This allows to drop the runtime Assert every time the context is
    accessed, because the type is known to be not null at compile-time.
    
    Note there is still the runtime Assert inside the util::NotNull
    constructor itself. However, this is called at most once, with the
    possibility of the compiler being able to optimize it away.
    fa57e8ff85
  18. refactor: In CNode use util::NotNull<std::unique_ptr<Transport>> m_transport
    This documents (and checks) that the transport pointer is never null.
    fad716891f
  19. refactor: Return util::NotNull<std::unique_ptr<ChangeSet>> from CTxMemPool::GetChangeSet()
    This documents (and checks) that the change set is never null.
    fa877daaef
  20. maflcko force-pushed on Apr 3, 2026
  21. DrahtBot added the label CI failed on Apr 3, 2026
  22. DrahtBot removed the label CI failed on Apr 3, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me