HomeWildfire Games

Silence warnings about unused result.
AuditedrP24261

Description

Silence warnings about unused result.

Introduce a DISCARD macro to ignore the warn_unused_result attribute used by Spidermonkey, and reuse it elsewhere.

Differential Revision: https://code.wildfiregames.com/D3147

Event Timeline

The idea is good but the implementation is controversial. We already have a macro called UNUSED2 for that cases, so the change introduces a code duplication. I think the name DISCARD is too broad, because it's not clear what to discard: the whole call or the only result. In my opinion the good implementation and naming is in chromium. Also the usage might be unsafe because it requires space and hence all related to macros issues.

vladislavbelov raised a concern with this commit.Nov 27 2020, 1:04 PM

I raise a concern to not forget to fix it before release. It's not a real concern, but pretty important for a code health.

This commit now has outstanding concerns.Nov 27 2020, 1:04 PM

The idea is good but the implementation is controversial.

On that you're certainly correct ;)

We already have a macro called UNUSED2 for that cases, so the change introduces a code duplication.

I'd disagree. UNUSED2 is necessary for unused local variables and such. In this instance, (void) ought to be enough, and we were already using it, so there was already a duplication of usage. Further,I dislike having to wrap the entire function call in UNUSED2, since that makes it seem like the whole function is unused.

unused_result at least has an explicit name, though I still think the wrapping of everything is annoying...
I'm going to check if I can find a better way, elsewise do the renaming later.

I'd disagree. UNUSED2 is necessary for unused local variables and such. In this instance, (void) ought to be enough, and we were already using it, so there was already a duplication of usage.

In the current implementation - yes, they're slightly different. But in fact we use the UNUSED2 macro for 2 reasons: 1) unused function result 2) hiding unused argument. 1) is solved by UNUSED_RESULT 2) is more a design problem - because it's adds implicit dependency with additional code changes, hence should be avoided.

Also chromium`s implementation fits into both cases.

Further,I dislike having to wrap the entire function call in UNUSED2, since that makes it seem like the whole function is unused. unused_result at least has an explicit name, though I still think the wrapping of everything is annoying...

I understand that it might be annoying, but you have to. In example, it's pretty unclear what are you discarding and might lead to errors (pretty synthetic, but anyway):

DISCARD expr1, expr2;
DISCARD expr ? val1 : val2;
// ...

Also (void)! doesn't work for most complex results (that can't be casted to bool).

Would you maybe be OK with something like this (not necessarily that name or operator)

[[nodiscard]] int toto()
{
    return 5;
}

struct with_unused_result {};
template <typename T>
void operator>>(with_unused_result, const T& ref) {}

int main()
{
    with_unused_result{} >> toto();
    return 0;
}

I'd rather not have to wrap the whole function, but I do take your point that it could be vaguely ambiguous (with admittedly weird code).

Elsewise, I'll change for something like your unused_result template indeed.

Would you maybe be OK with something like this (not necessarily that name or operator)

[[nodiscard]] int toto()
{
    return 5;
}

struct with_unused_result {};
template <typename T>
void operator>>(with_unused_result, const T& ref) {}

int main()
{
    with_unused_result{} >> toto();
    return 0;
}

I'd rather not have to wrap the whole function, but I do take your point that it could be vaguely ambiguous (with admittedly weird code).

Looks ok but still doesn't work for some cases, like with_unused_result{} >> func1() && func2_if_func1_succeeded.

You know that people do mistake. And we shouldn't rely on that people won't forget about operator priorities (in most cases they forget until have a compilation error).

So yes, wrapping looks like the most suitable thing for me.

Looks ok but still doesn't work for some cases, like with_unused_result{} >> func1() && func2_if_func1_succeeded.

Would work with the comma operator I suppose, but that seemed dirty...

Welp, will change.

wraitii requested verification of this commit.Dec 15 2020, 10:10 AM
This commit now requires verification by auditors.Dec 15 2020, 10:10 AM
All concerns with this commit have now been addressed.Dec 15 2020, 12:12 PM