refactor: Remove confusing P1008R1 violation in ATMPArgs #24404

pull MarcoFalke wants to merge 1 commits into bitcoin:master from MarcoFalke:2202-cpp🥲 changing 1 files +19 −2
  1. MarcoFalke commented at 11:29 AM on February 21, 2022: member

    The = delete doesn't achieve the stated goal and it is also redundant, since it is not possible to default construct the ATMPArgs type.

    This can be tested with:

    diff --git a/src/validation.cpp b/src/validation.cpp
    index 2813b62462..1c939c0b8a 100644
    --- a/src/validation.cpp
    +++ b/src/validation.cpp
    @@ -519,6 +519,7 @@ public:
             /** Parameters for child-with-unconfirmed-parents package validation. */
             static ATMPArgs PackageChildWithParents(const CChainParams& chainparams, int64_t accept_time,
                                                     std::vector<COutPoint>& coins_to_uncache) {
    +            ATMPArgs{};
                 return ATMPArgs{/* m_chainparams */ chainparams,
                                 /* m_accept_time */ accept_time,
                                 /* m_bypass_limits */ false,
    

    Which fails on current master and this pull with the following error:

    validation.cpp:525:22: error: reference member of type 'const CChainParams &' uninitialized
                ATMPArgs{};
                        ~^
    validation.cpp:470:29: note: uninitialized reference member is here
            const CChainParams& m_chainparams;
                                ^
    1 error generated.
    

    Further reading (optional):

  2. MarcoFalke added the label Refactoring on Feb 21, 2022
  3. MarcoFalke commented at 11:33 AM on February 21, 2022: member

    I believe an alternative (and larger) fix would be to provide an explicit constructor that takes all members as arguments. Happy to switch to that, but for now I prefer the smaller patch.

  4. glozow commented at 12:11 PM on February 21, 2022: member

    ACK facbbecc80166dc8b9a023ba7322915623bb0c29

    image

    I believe an alternative (and larger) fix would be to provide an explicit constructor that takes all members as arguments.

    I prefer this as well, for other places where there's no uninitialized reference to take the bullet for us.

  5. glozow commented at 1:10 PM on February 21, 2022: member

    CI error is the assert_fee_amount thing, unrelated

  6. DrahtBot commented at 7:48 PM on February 21, 2022: member

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #24169 (build: Add --enable-c++20 option by MarcoFalke)
    • #24152 (policy / validation: CPFP fee bumping within packages by glozow)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  7. JeremyRubin commented at 7:52 PM on February 21, 2022: contributor

    NACK.

    The point of a deleted constructor is to make the type stable to future modifications that might e.g. turn m_chainparams into p_chainparams. It's essentially an assertion.

  8. MarcoFalke commented at 7:43 AM on February 22, 2022: member

    It's essentially an assertion.

    No, it is not. Even if no member was const, aggregate initialization is possible. On current master and this branch. This patch isn't changing what it possible.

  9. MarcoFalke commented at 8:20 AM on February 22, 2022: member

    If you don't believe me, nor the paper P1008R1. You can try it yourself with a C++11 compiler of you choice. The following compiles fine with or without the delete.

    struct ATMPArgs {
      int a;
      bool b;
      ATMPArgs() = delete;
    };
    int main() { (void)ATMPArgs{}; } // compiles
    
  10. glozow commented at 8:52 AM on February 22, 2022: member

    The point of a deleted constructor is to make the type stable to future modifications that might e.g. turn m_chainparams into p_chainparams. It's essentially an assertion.

    No that was not the point when writing this code. The intention was to prevent callers from specifying their own ATMPArgs, e.g. using ATMPArgs args(); args.m_bypass_limits = true;. I wanted them to only be able to initialize arguments using the static constructors (ATMPArgs::SingleAccept, ATMPArgs::TestPackageAccept).

    But as shown in the paper (and any compiler), deleting the default constructor doesn't prevent something like this. What does prevent this is that there's a reference in the struct so you can't create a default version of it. So deletion of the default constructor does nothing. This PR is essentially removing code that doesn't do anything and misleading/confusing documentation.

  11. hebasto commented at 9:05 AM on February 22, 2022: member

    This example looks scary:

    struct ATMPArgs {
      int a = 42;
      bool b;
      ATMPArgs() = delete;
      ATMPArgs(int) = delete;
    };
    
    int main()
    {
        constexpr ATMPArgs atm{0};
        static_assert(atm.a == 0);
    }
    
  12. achow101 commented at 5:39 PM on February 22, 2022: member

    I think it's also important to point out that P1008R1 was accepted into C++20 so keeping the delete would also remove the aggregate initialization that the static functions make use of to construct ATMPArgs. However, I think that it is not immediately obvious that the default constructor is deleted by having a reference as a member. I think it would still be useful to comment out the delete and include some additional comments as to why that is.

  13. JeremyRubin commented at 6:39 PM on February 22, 2022: contributor

    The workaround in P1008R1 is to add an explicit modifier to the deletions? Why is that not a workable option here?

  14. MarcoFalke commented at 9:01 AM on February 23, 2022: member

    Why is that not a workable option here?

    It wouldn't compile:

    validation.cpp:522:20: error: no matching constructor for initialization of '(anonymous namespace)::MemPoolAccept::ATMPArgs'
                return ATMPArgs{/* m_chainparams */ chainparams,
                       ^       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    validation.cpp:469:12: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 7 were provided
        struct ATMPArgs {
               ^
    validation.cpp:469:12: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 7 were provided
    validation.cpp:533:18: note: candidate constructor not viable: requires 0 arguments, but 7 were provided
            explicit ATMPArgs() = delete;
                     ^
    3 errors generated.
    

    with diff on master:

    diff --git a/src/validation.cpp b/src/validation.cpp
    index 035b5783c3..c714bfe575 100644
    --- a/src/validation.cpp
    +++ b/src/validation.cpp
    @@ -530,7 +530,7 @@ public:
             }
             // No default ctor to avoid exposing details to clients and allowing the possibility of
             // mixing up the order of the arguments. Use static functions above instead.
    -        ATMPArgs() = delete;
    +        explicit ATMPArgs() = delete;
         };
     
         // Single transaction acceptance
    
  15. Remove confusing P1008R1 violation in ATMPArgs faa1aec26b
  16. MarcoFalke force-pushed on Feb 23, 2022
  17. MarcoFalke commented at 9:20 AM on February 23, 2022: member

    I've pushed the alternative fix I mentioned in comment 2 #24404 (comment)

  18. MarcoFalke commented at 9:23 AM on February 23, 2022: member

    Suggested diff for testing:

    diff --git a/src/validation.cpp b/src/validation.cpp
    index 3f64fcc067..900f85fc54 100644
    --- a/src/validation.cpp
    +++ b/src/validation.cpp
    @@ -707,6 +707,14 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
         if (tx.IsCoinBase())
             return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");
     
    +            ATMPArgs{       args.m_chainparams,
    +                            args.m_accept_time,
    +                            args.m_bypass_limits,
    +                            args.m_coins_to_uncache,
    +                            args.m_test_accept,
    +                            args.m_allow_bip125_replacement,
    +                            args.m_package_submission
    +            };
         // Rather not work on nonstandard transactions (unless -testnet/-regtest)
         std::string reason;
         if (fRequireStandard && !IsStandardTx(tx, reason))
    
  19. JeremyRubin commented at 4:40 PM on February 23, 2022: contributor

    should you not also retain the explicit delete with a new explicit ctor?

  20. MarcoFalke commented at 4:51 PM on February 23, 2022: member

    Happy to do so if there is any benefit?

  21. fanquake deleted a comment on Feb 25, 2022
  22. MarcoFalke commented at 1:24 PM on March 2, 2022: member

    Tend toward leaving as-is. explicit isn't used in current master and it isn't used in this pull. If there is any reason to use it, it might be best to do it in a separate pull request (as a follow-up or conflicting pull), with proper motivation.

  23. MarcoFalke requested review from glozow on Mar 10, 2022
  24. glozow commented at 12:39 PM on March 10, 2022: member

    code review ACK faa1aec26b3f354c832e6b995323c9429b178931

  25. achow101 commented at 1:37 PM on March 10, 2022: member

    ACK faa1aec26b3f354c832e6b995323c9429b178931

  26. fanquake merged this on Mar 10, 2022
  27. fanquake closed this on Mar 10, 2022

  28. MarcoFalke deleted the branch on Mar 10, 2022
  29. sidhujag referenced this in commit 58bc7b780d on Mar 11, 2022
  30. DrahtBot locked this on Mar 10, 2023

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-17 06:14 UTC

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