This is an archive of the discontinued LLVM Phabricator instance.

Use zip_longest for iterator range comparisons. NFC.
ClosedPublic

Authored by Meinersbur on Dec 7 2018, 7:31 PM.

Details

Summary

Use zip_longest in two locations that compare iterator ranges. zip_longest allows the iteration using a range-based for-loop and to be symmetric over both ranges instead of prioritizing one over the other. In that latter case code have to handle the case that the first is longer than the second, the second is longer than the first, and both are of the same length, which must partially be checked after the loop.

With zip_longest, this becomes an element comparison within the loop like the comparison of the elements themselves. The symmetry makes it clearer that neither the first and second iterators are handled differently. The iterators are not event used directly anymore, just the ranges.

Diff Detail

Repository
rC Clang

Event Timeline

Meinersbur created this revision.Dec 7 2018, 7:31 PM
Meinersbur retitled this revision from Use zip_longest for list comparisons. to Use zip_longest for iterator range comparisons. NFC..Dec 7 2018, 7:48 PM
dblaikie added inline comments.Dec 9 2018, 1:06 PM
lib/Sema/SemaOverload.cpp
8987

I'd probably write this as "if (!std::get<0>(Pair))" - but I understand that opinions differ on such things easily enough.

lib/Serialization/ASTReaderDecl.cpp
2922

This might be more legible as "if (std::get<0>(Pair) || std::get<1>(Pair))", I think? (optionally using "hasValue", if preferred - but comparing the hasValues to each other, rather than testing if either is false, seems a bit opaque to me at least)

Meinersbur updated this revision to Diff 177444.Dec 9 2018, 1:26 PM
Meinersbur marked 4 inline comments as done.
Meinersbur added inline comments.Dec 9 2018, 1:27 PM
lib/Sema/SemaOverload.cpp
8987

Here I tried do be explicit that it's an llvm::Optional and not testing for null pointers (or whatever the payload of the llvm::Optional is, which might itself have an overload bool conversion operator). It seemed worthwhile especially because llvm::Optional itself does not appear itself around these lines.

lib/Serialization/ASTReaderDecl.cpp
2922

The idea was 'if the items are unequal, the list is unequal', where when either one is undefined, but not the the other, is considered unequal. The test for the elements themselves have the same structure (Cand1ID != Cand2ID).

dblaikie added inline comments.Dec 9 2018, 1:40 PM
lib/Sema/SemaOverload.cpp
8987

*nod* Up to you - though, given std::get<0> and std::get<1> appear twice in this loop, perhaps it makes sense to pull them out into named variables and then you can name the Optional too?

lib/Serialization/ASTReaderDecl.cpp
2922

Sorry, looks like I made a mistake in the suggested change - should be a ! before each of the gets (I wonder if the change as you have it now/as I originally suggested, is causing any test failures - one really hopes it does... because as written it looks like it'd cause this loop to always return false on the first iteration):

if (!std::get<0>(Pair) || !std::get<1>(Pair))

& thanks for the explanation about the approach you were using - I see where you're coming from. I'd personally still lean this ^ way, I think.

(maybe if we get super ridiculous one day, and have a monadic (not sure if that's the right word) sort of conditional accessor for Optional (where you pass in a lambda over T, returning U, and the result is Optional<U>) we could write this in terms of that & then the != would fit right in... though would be a bit verbose/quirky to be sure)

Meinersbur updated this revision to Diff 177447.Dec 9 2018, 3:20 PM
  • Fix xor
  • Store tuple elements in variables
dblaikie accepted this revision.Dec 9 2018, 3:26 PM

Overall I'm not sure this construct/pattern improves readability, but not too fussed either way.

This revision is now accepted and ready to land.Dec 9 2018, 3:26 PM
Meinersbur marked 3 inline comments as done.Dec 9 2018, 3:38 PM
Meinersbur added inline comments.
lib/Serialization/ASTReaderDecl.cpp
2922

I knew exactly what you suggested -- I considered before going with the != version -- it seems It also only saw what I wanted to see. I still just copy&pasted from your comment to save some keystrokes. Maybe the != is less error-prone, as just demonstrated? Test cases did not fail.

dblaikie added inline comments.Dec 9 2018, 4:30 PM
lib/Serialization/ASTReaderDecl.cpp
2922

I'd still probably go with the !A || !B form - and either encourage you to add the missing test coverage, or maybe go find who owns/contributed/reviewed the code to request/suggest some testing.

This revision was automatically updated to reflect the committed changes.
Meinersbur marked an inline comment as done.