[PATCH] D57618: [ADT] Add a fallible_iterator wrapper.
Lang Hames via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 4 14:42:50 PST 2019
lhames marked 7 inline comments as done.
lhames added inline comments.
================
Comment at: include/llvm/ADT/fallible_iterator.h:76
+public:
+ using this_fallible_iterator = fallible_iterator<Underlying>;
+
----------------
dblaikie wrote:
> I think you can use "fallible_iterator" without template parameters throughout the class (this would ues the injected class name), probably means you don't need this alias here?
Yep. This is a hangover from when the type name was longer. It can be removed.
================
Comment at: include/llvm/ADT/fallible_iterator.h:100
+ /// Forward const dereference to the underlying iterator.
+ auto operator*() const -> decltype(*std::declval<const Underlying>()) {
+ return *I;
----------------
dblaikie wrote:
> Not sure if the "const Underlying" is correct here.
>
> Iterator const tends not to be deep, I think? So, for instance a "const std::vector<int>::iterator" is not the same as a "std::vector<int>::const_iterator" - the former cannot be assigned to, but its dereference probably still returns non-const reference. Whereas the latter can be assigned, incremented, etc, but still has a const reference return from op*. Does that make sense?
>
> All in all, I think you only need the member-const op* (because op* doesn't modify the iterator, only the thing it is iterating over). And it should probably use const in the declval, I think?
You're approaching this from a very different angle to me. I just think of these operators as forwarding: There's a const and a non-const version, and they do whatever the const and non-const version of the underlying iterator do. The wrapper is being as minimalist as possible in the assumptions it places on the Underlying type.
================
Comment at: include/llvm/ADT/fallible_iterator.h:126
+ this_fallible_iterator &operator++() {
+ assert(getErrPtr() && "Can not increment end iterator");
+ if (auto Err = I.inc())
----------------
dblaikie wrote:
> 'Cannot'?
/s/can not/cannot/. :)
================
Comment at: include/llvm/ADT/fallible_iterator.h:211-212
+ void resetCheckedFlag() {
+ (void)!!*getErrPtr();
+ assert(!*getErrPtr() && "Incrementing failure value");
+ *getErrPtr() = Error::success();
----------------
dblaikie wrote:
> Should/could this be replaced with "cantFail"?
I don't think Error's move constructor ever guaranteed that a moved-from error was assignable. It *probably* is, but I'd have to check and formalize this.
Instead here I have forced a check and then written to the error.
================
Comment at: unittests/ADT/FallibleIteratorTest.cpp:22-23
+public:
+ using ObjectValid = enum { ValidObject, InvalidObject };
+ using LinkValid = enum { ValidLink, InvalidLink };
+
----------------
dblaikie wrote:
> I'm a bit surprised to find linker terminology in this test case that's orthogonal to linkers, object files, etc. Do you find they improve readability/framing?
I may be biased, but they definitely do for me. Archive iteration was the original motivating use case for the fallible_iterator pattern, and has the advantage of including both kinds of iterator fail: increment/decrement failures (if the archive header is bad), and dereference failures (if an archive member is malformed). Only the former is tested so far in this test case, but I plan to add a dereference failure test too, to verify the forwarding nature of the dereference operators.
================
Comment at: unittests/ADT/FallibleIteratorTest.cpp:194
+ ++I;
+ (void)!!Err; // Manualy reset the checked flag.
+ ++I;
----------------
dblaikie wrote:
> Might be better as an explicit EXPECT_THAT_ERROR(Succeeded) - if there was a bug that caused this Error to be in a fail state, the test would fail rather indirectly later on inside the fallible iterator implementationg where it does "cantFail' (or the moral equivalent)?
Yep. This is another instance of moved-from-Errors-aren't-assignable/reusable. I could use two errors though.
================
Comment at: unittests/ADT/FallibleIteratorTest.cpp:197
+ EXPECT_THAT_ERROR(std::move(Err), Failed()) << "Expected failure value";
+ cantFail(std::move(Err));
+ }
----------------
dblaikie wrote:
> What's this line for? (it looks to me like the EXPECT_THAT_ERROR on the previous line should have validated the Error state & so there should be no other need to do any Error handling after that?)
Yep -- this is redundant. Good catch. I'll remove it.
Repository:
rL LLVM
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D57618/new/
https://reviews.llvm.org/D57618
More information about the llvm-commits
mailing list