-
Notifications
You must be signed in to change notification settings - Fork 38.7k
refactor: unify container presence checks #33094
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33094. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
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. LLM Linter (✨ experimental)Possible typos and grammar issues:
drahtbot_id_4_m |
pablomartin4btc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
This refactor replaces explicit .count(x) checks with .contains(x), which only verifies that at least one instance exists (or none when == 0). Please double-check whether .contains() preserves the original behavior in some contexts where exactness matters ( !=1, ==1, etc). Also where the logic enforces that exactly one item is/ is not present — useful even in containers that don't allow duplicates (like std::map or std::set) because it clearly expresses the expected logic — replacing it with .contains() weakens the check and may mask issues where the assumption of uniqueness is violated.
35e2719 to
71911a5
Compare
l0rinc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, split up the PR into 3 commits to simplify assessing the risks - hope this clarifies it, see the commit messages for further details.
|
Nit; Missed?: if (proxy_networks.find(proxy) == proxy_networks.end()) ordered_proxies.push_back(proxy);=> if (!proxy_networks.contains(proxy)) ordered_proxies.push_back(proxy); |
71911a5 to
53461dc
Compare
|
Thanks, rebased to solve conflict in |
janb84
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 53461dc5cedf5f7080c09246ef76ba8a6c38a103
This PR refactors the code to use the more modern contains() method. In my opinion this PR increased the readability of the code and removes the ambiguity of the intention of the count() methods used. With this change, the intent to enforce that exactly one item is/ is not present or just a presence check will be more obvious. (count() vs contains()).
The argument NOT to change the code because of the risk losing the original behaviour is an indication to me that the refactor is needed to remove the ambiguity and more clearly communicate the intent of the code.
(thanks for including my suggestion/nit)
|
if this is done, it should be added to [379/677][7.2s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/zmq/zmqrpc.cpp
775 warnings generated.
[380/677][10.0s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/test/coins_tests.cpp
/ci_container_base/src/test/coins_tests.cpp:397:48: error: use 'contains' to check for membership [readability-container-contains,-warnings-as-errors]
397 | assert(duplicate_coins.count(utxod->first));
| ^
1128 warnings generated.
[381/677][10.2s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/test/txrequest_tests.cpp
--
[443/677][0.8s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/crypto/sha3.cpp
33 warnings generated.
[444/677][16.6s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/wallet/test/fuzz/scriptpubkeyman.cpp
/ci_container_base/src/wallet/test/fuzz/scriptpubkeyman.cpp:129:60: error: use 'contains' to check for membership [readability-container-contains,-warnings-as-errors]
129 | assert(spk_manager->GetScriptPubKeys().count(script));
| ^
2416 warnings generated.
[445/677][17.4s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/wallet/rpc/transactions.cpp
--
[653/677][12.1s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/test/fuzz/miniscript.cpp
1071 warnings generated.
[654/677][14.3s] clang-tidy-20 -p=/ci_container_base/ci/scratch/build-x86_64-pc-linux-gnu -quiet -load=/tidy-build/libbitcoin-tidy.so /ci_container_base/src/qt/walletframe.cpp
/ci_container_base/src/qt/walletframe.cpp:73:24: error: use 'contains' to check for membership [readability-container-contains,-warnings-as-errors]
73 | if (mapWalletViews.count(walletView->getWalletModel()) > 0) return false;
| ^~~~~ ~~~
| contains
/ci_container_base/src/qt/walletframe.cpp:93:24: error: use 'contains' to check for membership [readability-container-contains,-warnings-as-errors]
93 | if (mapWalletViews.count(wallet_model) == 0) return;
| ^~~~~ ~~~~
| ! contains
/ci_container_base/src/qt/walletframe.cpp:119:24: error: use 'contains' to check for membership [readability-container-contains,-warnings-as-errors]
119 | if (mapWalletViews.count(wallet_model) == 0) return;
| ^~~~~ ~~~~
| ! contains
1370 warnings generated.
^^^ ⚠️ Failure generated from clang-tidy |
53461dc to
d397f0b
Compare
|
Thanks @fanquake, I wanted to leave out |
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
d397f0b to
0515360
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re ACK 05153600af10c322e40d107b8cf0c8e69b8b0aeb
changes since last ACK:
- clang-tidy related changes
Details
New result of clang-tidy :$ ( cd ./src/ && run-clang-tidy -p ../build -j $(nproc) ) | grep walletframe.cpp
<< no warnings>>
I understand the Update: AFAICS the |
|
Yes, applies to any kind of map, but I had to find and change those manually - clang-tidy doesn't detect or fix those. |
optout21
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 05153600af10c322e40d107b8cf0c8e69b8b0aeb
- The changes increase code readability, as 'contains' expresses the code logic / intent more specifically
- It also results in higher performance, due to potential early exit. The improvement is probably negligible though.
- Changes are localized (each to a single line), local impact only
(I've reviewed the proposed changed, but didn't look for other potential changes)
|
Rebased after #33116, ready for review again:
I have added a few more |
0515360 to
995d3a9
Compare
|
Concept -1: this doesn't seem valuable enough to warrant rebasing all the PRs it conflicts with. Can this be added as a linter of some sort to encourage the changes to be made when the code is touched? |
|
Not sure what to do about the conflicts, but to enable the linter, I had to fix the existing problems first. Maybe there is a way in clang-tidy to only check new code, but it's definitely cleaner enabling it for all code, as done in this PR. |
Perhaps an approach like this would work (for this and other cleanups)?
|
The changes made here were: | From | To | |------------------------|------------------| | `m.find(k) == m.end()` | `!m.contains(k)` | | `m.find(k) != m.end()` | `m.contains(k)` |
The changes made here were: | From | To | |-------------------|------------------| | `m.count(k)` | `m.contains(k)` | | `!m.count(k)` | `!m.contains(k)` | | `m.count(k) == 0` | `!m.contains(k)` | | `m.count(k) != 0` | `m.contains(k)` | | `m.count(k) > 0` | `m.contains(k)` | The commit contains the trivial, mechanical refactors where it doesn't matter if the container can have multiple elements or not Co-authored-by: Jan B <608446+janb84@users.noreply.github.com>
The changes made here were: | From | To | |-------------------|------------------| | `m.count(k) == 1` | `m.contains(k)` | | `m.count(k) != 1` | `!m.contains(k)` | | `m.count(k) < 1` | `!m.contains(k)` | * `mapInfo` is instance of `std::unordered_map` and can only contain 0 or 1 value for a given key; * similarly, `g_enabled_filter_types` and `setClientRules` are both `std::set` instances; * lastly, while `mapTxSpends` is `std::unordered_multimap` that could potentially hold multiple values, having a size less than 1 means that the value is missing. `QMap<WalletModel*, WalletView*> mapWalletViews` values were also migrated manually. Co-authored-by: pablomartin4btc <pablomartin4btc@gmail.com> Co-authored-by: fanquake <fanquake@gmail.com>
995d3a9 to
f70d2c7
Compare
|
Removed all conflicts with other PR that I found and opened a new PR at #33192 to give @DrahtBot a chance to recalculate the conflicts section. |
|
It is already possible to run clang tidy on a diff. See
|
d9319b0 refactor: unify container presence checks - non-trivial counts (Lőrinc) 0393075 refactor: unify container presence checks - trivial counts (Lőrinc) 8bb9219 refactor: unify container presence checks - find (Lőrinc) Pull request description: ### Summary Instead of counting occurrences in sets and maps, the C++20 `::contains` method expresses the intent unambiguously and can return early on first encounter. ### Context Applied clang‑tidy's [readability‑container‑contains](https://clang.llvm.org/extra/clang-tidy/checks/readability/container-contains.html) check, though many cases required manual changes since tidy couldn't fix them automatically. ### Changes The changes made here were: | From | To | |------------------------|------------------| | `m.find(k) == m.end()` | `!m.contains(k)` | | `m.find(k) != m.end()` | `m.contains(k)` | | `m.count(k)` | `m.contains(k)` | | `!m.count(k)` | `!m.contains(k)` | | `m.count(k) == 0` | `!m.contains(k)` | | `m.count(k) != 1` | `!m.contains(k)` | | `m.count(k) == 1` | `m.contains(k)` | | `m.count(k) < 1` | `!m.contains(k)` | | `m.count(k) > 0` | `m.contains(k)` | | `m.count(k) != 0` | `m.contains(k)` | > Note that `== 1`/`!= 1`/`< 1` only apply to simple [maps](https://en.cppreference.com/w/cpp/container/map/contains)/[sets](https://en.cppreference.com/w/cpp/container/set/contains) and had to be changed manually. There are many other cases that could have been changed, but we've reverted most of those to reduce conflict with other open PRs. ----- <details> <summary>clang-tidy command on Mac</summary> ```bash rm -rfd build && \ cmake -B build \ -DCMAKE_C_COMPILER="$(brew --prefix llvm)/bin/clang" \ -DCMAKE_CXX_COMPILER="$(brew --prefix llvm)/bin/clang++" \ -DCMAKE_OSX_SYSROOT="$(xcrun --show-sdk-path)" \ -DCMAKE_C_FLAGS="-target arm64-apple-macos11" \ -DCMAKE_CXX_FLAGS="-target arm64-apple-macos11" \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON -DBUILD_FOR_FUZZING=ON "$(brew --prefix llvm)/bin/run-clang-tidy" -quiet -p build -j$(nproc) -checks='-*,readability-container-contains' | grep -v 'clang-tidy' ``` </details> Note: this is a take 2 of #33094 with fewer contentious changes. ACKs for top commit: optout21: reACK d9319b0 sedited: ACK d9319b0 janb84: re ACK d9319b0 pablomartin4btc: re-ACK d9319b0 ryanofsky: Code review ACK d9319b0. I manually reviewed the full change, and it seems there are a lot of positive comments about this and no more very significant conflicts, so I will merge it shortly. Tree-SHA512: e4415221676cfb88413ccc446e5f4369df7a55b6642347277667b973f515c3c8ee5bfa9ee0022479c8de945c89fbc9ff61bd8ba086e70f30298cbc1762610fe1
Summary
Instead of counting occurrences in sets and maps, the C++20
::containsmethod expresses the intent unambiguously and can return early on first encounter.Context
Applied clang‑tidy's readability‑container‑contains check, though many cases required manual changes since tidy couldn't fix them automatically.
Changes
The changes made here were:
m.find(k) == m.end()!m.contains(k)m.find(k) != m.end()m.contains(k)m.count(k)m.contains(k)!m.count(k)!m.contains(k)m.count(k) == 0!m.contains(k)m.count(k) != 1!m.contains(k)m.count(k) == 1m.contains(k)m.count(k) < 1!m.contains(k)m.count(k) > 0m.contains(k)m.count(k) != 0m.contains(k)There are many other cases that could be changed, but we've reverted most of those to reduce conflict with other open PRs.
clang-tidy command on Mac