-
Notifications
You must be signed in to change notification settings - Fork 37.7k
util: Add Assert identity function #19277
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
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. Two questions:
Assert
can be confusing because ofassert
? (but I don't have a better name)- maybe it should be a macro so that error shows the call site?
Why would they be confusing? Replacing Changed to a macro, thx for the suggestion. |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
Either way, might as well replace the remaining two |
This used to be called I am happy to pick either version, as long as reviewers are happy. |
Done in the last force push. |
The utility is primarily useful to dereference pointer types, which are known to be not null at that time. For example, the ArgsManager is known to exist when the wallets are started. Instead of silently relying on that assumption, Assert can be used to abort the program and avoid UB should the assumption ever be violated.
-BEGIN VERIFY SCRIPT- sed --regexp-extended -i -e 's/EnsureChainman\((m?_?node)\)\./Assert(\1.chainman)->/g' $(git grep -l EnsureChainman) -END VERIFY SCRIPT-
For reviewers who think assert is "weird" and "confusing" and wouldn't "expect it to return a value," I don't see what point you are making. If you saw I like the name As long as this is aborting the program on failure, I think calling this I think the name |
I mean confusing not because of return value but because now it's valid to use |
Yes, it is valid and should compile to the same binary. (Just like it is fine to replace |
:) no downside. So we could just recommend the new macro for new code? Or add a note for when |
I think we can leave it to code authors to pick whatever version they like more. There really shouldn't be any difference as long as the code compiles. |
I think it's important to keep scrutiny on the changes, not on the people. "Tough on the changes, easy on the people." I've deleted my review. |
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.
Code review ACK fab80fe
I mean confusing not because of return value but because now it's valid to use
ASSERT()
instead ofassert()
.
Oh, thanks for explaining. I wouldn't be too worried about which assert someone picks when writing code, but the macro documentation could be updated to say something about when it should be used, if there are opinions about that. I think it's basically fine to use or not to not use, as long as it's reasonably clear what it does when it is used.
} | ||
|
||
/** Identity function. Abort if the value compares equal to zero */ | ||
#define Assert(val) [&]() -> decltype(get_pure_r_value(val))& { auto& check = (val); assert(#val && check); return check; }() |
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.
In commit "util: Add Assert identity function" (fa6ef70)
Note: decltype(get_pure_r_value(val))
is needed here in case the val
expression is const, because just decltype(val)
drops the const and results in an error trying to return a const reference from a lambda effectively declared to return a non-const reference. I think returning decltype(auto) would be another way to work around this once we update past c++11
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 for the hint. Whoever plays code-golf after we switch to C++17 should consider this.
I found the review useful and I adjusted the commit based on the review to include motivation for the change (and fix the typo). Sometimes my commit messages are too short (i.e. empty) when they instead could include further background information and motivation for the changes, so at least I found the review helpful. |
re: @jonatack #19277 (comment)
I'm confused. What did your review say? In my email it was a concept ACK with some suggestions not related to this. Did I phrase my comment badly? I don't think I was scrutinizing anything, just asking a literal, non-rhetorical question to reviewers expressing an opinion I didn't understand. It turned one reviewer clarified and didn't actually have that opinion, so I'm glad I asked. But if I should have asked differently, I'd like to know. |
Concept ACK: this will help guide static analyzers and thus increase signal-to-noise in reports. And more generally: explicit guarantees are better than implicit guarantees :) |
Sorry for deleting. I was having an "I suck" moment. |
Tested ACK fab80fe. Indeed it's better with macro and templating ninjatsus. Applying --- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -44,6 +44,7 @@ static void WaitForShutdown(NodeContext& node)
static bool AppInit(int argc, char* argv[])
{
NodeContext node;
+ Assert(node.chain);
node.chain = interfaces::MakeChain(node);
bool fRet = false; Gives
|
Why would you ever have to guess? I'd think "ugh, what's going on, assert doesn't work like that" and look at the source, and conclude "oh, they're just doing some weird local convention where assert in all caps is slightly different than regular assert". That's not a showstopper, it's just confusing. If I saw +1 on having Anything along the lines of |
Thanks, that's kind of my point. You don't have to guess. If you have any question, you can look at the Re suggestions:
Any case, I'm glad we seem to agree there's no readability problem here. I think current PR is fine. My favorite name would probably be ASSERT, followed by one of the names that contains ABORT or FATAL, because REQUIRE doesn't sound scary enough, and doesn't make me think that world may end if the pointer is null. But Marco's the guy putting in the work here, and whatever name he likes I am happy with. |
Another reason I like the name The thread also mentions the danger of building with NDEBUG, which is forbidden since 9b59e3b. Given that it is impossible to build with NDEBUG, no one is testing this configuration and it is effectively unsupported. However, the check is only in one place (main.cpp, or current master: validation and net_processing, or now: check.h). So certainly it is impossible to build Yet another reason I like tfm::format(std::cerr, "%s:%d (%s)\n" \
"Internal bug detected: '%s'\n" \
"Aborting!\n" \
"You may report this issue here: %s\n", \
__FILE__, __LINE__, __func__, \
(#condition), \
PACKAGE_BUGREPORT); \ Example taken from #17408. So using the name Unrelated, but the discussion about |
Summary: ``` The utility function is primarily useful to dereference pointer types, which are known to be not null at that time. For example, the ArgsManager is known to exist when the wallets are started: https://github.com/bitcoin/bitcoin/pull/18923/files#diff-fdb2a1a1d8bc790fcddeb6cf5a42ac55R503 . Instead of silently relying on that assumption, Assert can be used to abort the program and avoid UB should the assumption ever be violated. ``` Backport of core [[bitcoin/bitcoin#19277 | PR19277]]. Depends on D8565. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D8566
The utility function is primarily useful to dereference pointer types, which are known to be not null at that time.
For example, the ArgsManager is known to exist when the wallets are started: https://github.com/bitcoin/bitcoin/pull/18923/files#diff-fdb2a1a1d8bc790fcddeb6cf5a42ac55R503 . Instead of silently relying on that assumption,
Assert
can be used to abort the program and avoid UB should the assumption ever be violated.