A few code paths use rvalue references or std::move() for types where moving provides no benefit.
EmplaceCoinInternalDANGER took COutPoint&&, forcing callers to pass trivially copyable outpoints as rvalues even though the cache stores its own key. LogPrintFormatInternal, LogPrintStr, and LogPrintStr_ similarly took SourceLocation&& and moved from it when constructing log entries, even though SourceLocation is trivially copyable.
Some call sites also use std::move() on enum and primitive values, where it only adds noise.
[!NOTE]
CheckTriviallyCopyableMove remains false since std::move() on trivially copyable types can still be useful as intent documentation, for example to signal that a value should not be reused after a call.
Fix
Take trivially copyable arguments by const reference where the callee only needs to store its own copy, and pass existing values directly at the call sites.
Also remove std::move() from enum and primitive assignments where it has no semantic effect.
DrahtBot
commented at 1:28 PM on February 5, 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.
If your review is incorrectly listed, please copy-paste <code><!--meta-tag:bot-skip--></code> into the comment that the bot should ignore.
<!--174a7506f384e20aa4161008e828411d-->
Conflicts
Reviewers, this pull request conflicts with the following ones:
#34806 (refactor: logging: Various API improvements by ajtowns)
#34778 (logging: rewrite macros to add ratelimit option, avoid unused strprintf, clarify confusing errors by ryanofsky)
#29256 (log, refactor: Allow log macros to accept context arguments by ryanofsky)
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.
<!--5faf32d7da4f0f540f40219e4f7537a3-->
fanquake renamed this: L0rinc/move const arg trivcopy refactor: enable `move-const-arg` for trivially-copyable types on Feb 5, 2026
DrahtBot added the label Refactoring on Feb 5, 2026
Thanks, added a static_assert in logging_LogPrintStr for SourceLocation triviality to document why we're not using std::move for these types
hodlinator
commented at 7:27 PM on March 19, 2026:
Cheers, but I think the static_assert is stating something about the the implementation and so should be located in it, instead of in a test. Maybe put it in the body of BCLog::Logger::LogPrintStr_(), or possibly in logging.h/log.h.
I don't like spreading around tests, I can make it a regular assert if that helps
hodlinator
commented at 2:02 PM on March 24, 2026:
I don't see this static assertion as an external test. It is verifying a constraint of the implementation and helping to document why we prefer const ref over r-value ref right next to it rather than far away in a test file.
See static_assert usage in /src/util/bitset.h for example.
Taking by const-ref should be slightly more optimal, but it's not important to me. Maybe the 2 fields of the struct can be passed in 2 registers, I'm not too familiar with calling conventions.
purpleKarrot
commented at 3:50 PM on February 5, 2026:
contributor
Using std::move on a const-qualified object has no observable effect in code generation, and it harms readability. The reader may assume that it causes a movable type to move, when it is actually copied.
Using std::move on trivially copyable types also has no observable effect in code generation, but it may improve readability to use it, because it signals intent, as @maflcko wrote above ("mark a symbol used").
I would consider setting CheckTriviallyCopyableMove to false in move-const-arg. Also, make sure not to introduce regressions for pass-by-value.
maflcko
commented at 3:54 PM on February 5, 2026:
member
Using std::move on a const-qualified object has no observable effect in code generation, and it harms readability. The reader may assume that it causes a movable type to move, when it is actually copied.
Using std::move on trivially copyable types also has no observable effect in code generation, but it may improve readability to use it, because it signals intent, as @maflcko wrote above ("mark a symbol used").
I would consider setting CheckTriviallyCopyableMove to false in move-const-arg. Also, make sure not to introduce regressions for pass-by-value.
I think all of your points are already implemented since faad673716c (zirka 2022)
hodlinator
commented at 7:32 PM on February 5, 2026:
contributor
I'm ~0 on this:
It's nice to clear away what can be seen as noise.
It's nice to document intent ("mark a symbol used") as 2 prior commenters have pointed out.
maflcko
commented at 7:50 AM on February 6, 2026:
member
l0rinc
commented at 10:25 AM on February 6, 2026:
contributor
Thanks for the comments, while I think signaling that a value should not be reused after a call via std::move is kinda' hacky and arbitrary, I have dropped the CSHA512 signature change in random.cpp, the CTxMemPool::Options, cherry-picked the CheckTriviallyCopyableMove move changes and most mechanical clang-tidy fix-its.
Let me know what you think, I hope I have addressed all concerns.
l0rinc renamed this: refactor: enable `move-const-arg` for trivially-copyable types refactor: remove unnecessary std::move for trivially copyable types on Feb 6, 2026
l0rinc requested review from purpleKarrot on Feb 6, 2026
l0rinc requested review from andrewtoth on Feb 6, 2026
l0rinc requested review from maflcko on Feb 6, 2026
l0rinc requested review from hodlinator on Feb 6, 2026
maflcko
commented at 1:56 PM on February 6, 2026:
member
lgtm, but there are a few conflicts let's get those in earlier.
Feel free to ping me for review after a week of inactivity or so, but i don't think there is need to ping reviewers on the second day of a refactor pull request.
DrahtBot added the label Needs rebase on Feb 7, 2026
l0rinc force-pushed on Feb 8, 2026
bvbfan
commented at 8:08 AM on February 8, 2026:
contributor
Why not introduce function move_if_not_trivially_copyable so you will have docs inside the code.
DrahtBot removed the label Needs rebase on Feb 8, 2026
fanquake referenced this in commit 6ca7782db9 on Feb 9, 2026
l0rinc force-pushed on Feb 9, 2026
l0rinc
commented at 2:03 PM on February 9, 2026:
contributor
there are a few conflicts let's get those in earlier
Rebased after #34523, the conflict list only contains my own change now.
Why not introduce function move_if_not_trivially_copyable so you will have docs inside the code.
maflcko
commented at 9:13 AM on February 10, 2026:
member
I think it would be easier to enforce this with clang-tidy via:
Also, make sure not to introduce regressions for pass-by-value.
instead of move_if_not_trivialy_copyable.
However, the storage of ipv6 in CNetAddr::m_addr is meant to be trivially copyable. However prevector isn't, even if only used with direct storage. So it could make sense to fix that first, by introducing a (let's say) ArrayVec, which is backed by a fixed-size array and a variable size counter (up to the fixed-size array len)
l0rinc
commented at 10:18 AM on February 10, 2026:
contributor
So it could make sense to fix that first
CNetAddr::m_addr/prevector sounds like a larger design cleanup, I don't mind doing that in a separate PR.
make sure not to introduce regressions for pass-by-value.
running it locally and grepping for [modernize-pass-by-value] shows the exact same list before and after (cc: @purpleKarrot):
src/httpserver.cpp:131:21: warning: pass by value and use std::move [modernize-pass-by-value]
src/httpserver.cpp:131:60: warning: pass by value and use std::move [modernize-pass-by-value]
src/i2p.cpp:122:18: warning: pass by value and use std::move [modernize-pass-by-value]
src/i2p.cpp:130:45: warning: pass by value and use std::move [modernize-pass-by-value]
src/net.cpp:3374:20: warning: pass by value and use std::move [modernize-pass-by-value]
src/net.cpp:3968:14: warning: pass by value and use std::move [modernize-pass-by-value]
src/test/bip32_tests.cpp:29:25: warning: pass by value and use std::move [modernize-pass-by-value]
src/test/blockfilter_index_tests.cpp:317:72: warning: pass by value and use std::move [modernize-pass-by-value]
src/test/util/net.cpp:341:18: warning: pass by value and use std::move [modernize-pass-by-value]
src/test/util/net.cpp:341:48: warning: pass by value and use std::move [modernize-pass-by-value]
src/wallet/test/db_tests.cpp:218:19: warning: pass by value and use std::move [modernize-pass-by-value]
maflcko
commented at 4:59 PM on February 10, 2026:
member
CNetAddr::m_addr/prevector sounds like a larger design cleanup, I don't mind doing that in a separate PR.
DrahtBot added the label Needs rebase on Feb 19, 2026
l0rinc force-pushed on Feb 19, 2026
l0rinc force-pushed on Feb 19, 2026
DrahtBot added the label CI failed on Feb 19, 2026
DrahtBot removed the label CI failed on Feb 20, 2026
DrahtBot removed the label Needs rebase on Feb 20, 2026
DrahtBot added the label Needs rebase on Mar 18, 2026
l0rinc force-pushed on Mar 18, 2026
DrahtBot removed the label Needs rebase on Mar 18, 2026
hodlinator
commented at 7:36 PM on March 19, 2026:
contributor
Reviewed 1b7fc8c3b49a8ba7fe87fa8042aff87006ef31cf
Curious to see feedback on my inline comment. Looks fine otherwise.
DrahtBot added the label Needs rebase on Mar 24, 2026
l0rinc force-pushed on Mar 25, 2026
DrahtBot removed the label Needs rebase on Mar 25, 2026
hodlinator approved
hodlinator
commented at 12:02 PM on March 25, 2026:
contributor
ACK10f4d933e605709b4fd4c92e9ec2860c60acd823
std::move() wasn't really doing anything for these types, and we don't increase cognitive complexity by adding that much alive scope after the no longer moved variables.
DrahtBot added the label Needs rebase on Apr 23, 2026
coins: avoid moving `COutPoint` values
`EmplaceCoinInternalDANGER` took `COutPoint&&`, forcing callers to pass trivially copyable outpoints as rvalues even though the cache stores its own key.
Take `outpoint` by const reference and pass existing outpoints directly at all call sites.
Co-authored-by: Andrew Toth <andrewstoth@gmail.com>
b6afb940bf
logging: avoid moving `SourceLocation`
`LogPrintFormatInternal` took `SourceLocation&&` and moved from it when constructing log entries even though `SourceLocation` is trivially copyable.
The direct logging test mirrored that obsolete interface by moving its local `SourceLocation` value.
Document the invariant with a `static_assert`, accept `const SourceLocation&`, and copy source locations into log entries and tests.
f5e92d79cc
rpc: avoid moving RPC enum types
`RPCArg::Type` and `RPCResult::Type` are enum values, so moving them in constructors is no different from copying them.
Initialize the stored type fields directly.
68ee68c637
txgraph: avoid moving primitive members
`CommitStaging()` moved primitive staging members into the main cluster set even though moving them only copies the values.
Assign the primitive members directly and keep moves for the owning containers.
90cf74e5f4
l0rinc force-pushed on Apr 23, 2026
l0rinc
commented at 2:29 PM on April 23, 2026:
contributor
Rebased after #34865, the diff is even simpler now.
l0rinc renamed this: refactor: remove unnecessary std::move for trivially copyable types refactor: remove unnecessary `std::move` for a few trivially copyable types on Apr 23, 2026
DrahtBot removed the label Needs rebase on Apr 23, 2026
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-05-12 15:12 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me