This is an archive of the discontinued LLVM Phabricator instance.

[ADT] Make mapped_iterator copy assignable
ClosedPublic

Authored by jplayer-nv on Sep 26 2022, 2:21 PM.

Details

Summary

As mentioned in https://discourse.llvm.org/t/rfc-extend-ranges-infrastructure-to-better-match-c-20/65377

Lambda objects are not copy assignable, and therefore neither are iterator types which hold a lambda. STL code require iterators be copy assignable. Users may not use mapped_iterator with a std::deque for example: https://godbolt.org/z/4Px7odEEd

This blog post explains the problem and solution. We define a wrapper class to store callable objects with two specialization.

  1. Specialization for non-function types
    • Use a std::optional as storage for non-function callable.
    • Define operator=() implementation(s) which use std::optional::emplace() instead of the assignment operator.
  2. Specialization for function types
    • Store as a pointer (even if template argument is a function reference).
    • Default construct pointer to nullptr.

This Callable wrapper class is now default constructible (with invalid state) and copy/move assignable.

With these new properties available on the callable object, mapped_iterator can define a default constructor as well.

Diff Detail

Event Timeline

jplayer-nv created this revision.Sep 26 2022, 2:21 PM
Herald added a project: Restricted Project. · View Herald TranscriptSep 26 2022, 2:21 PM
jplayer-nv requested review of this revision.Sep 26 2022, 2:21 PM
jplayer-nv edited the summary of this revision. (Show Details)Sep 26 2022, 2:48 PM
kazu accepted this revision.Oct 7 2022, 9:59 AM
This revision is now accepted and ready to land.Oct 7 2022, 9:59 AM

Thanks for the review @kazu

I don't have commit access, would you please shepherd the change? I rebased locally and ran testing today (all pass). Thanks again!

Ping @kazu for commit. If you're not the right person to ask, could you kindly suggest someone else?

kazu added a comment.Oct 30 2022, 9:05 AM

Ping @kazu for commit. If you're not the right person to ask, could you kindly suggest someone else?

Sorry for the delay. I am working on committing this patch. What author name and email address should I use?

Thanks @kazu

Author name = James Player
Email = james.w.player@gmail.com

This revision was automatically updated to reflect the committed changes.
nickdesaulniers added inline comments.
llvm/unittests/ADT/MappedIteratorTest.cpp
177

When I configure with -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON, build this test with ninja ADTTests then run this, I get the following crash from this statement:

/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/debug/safe_iterator.h:472:
In function:
    bool gnu_debug::operator==(const _Self &, const _Self &)

Error: attempt to compare a singular iterator to a 
dereferenceable (start-of-sequence) iterator.

Objects involved in the operation:
    iterator "lhs" @ 0x7ffcc2f77420 {
      state = singular;
    }
    iterator "rhs" @ 0x7ffcc2f77450 {
      state = dereferenceable (start-of-sequence);
      references sequence @ 0x7ffcc2f772f0
    }

Any ideas how best to fix this?

jplayer-nv added inline comments.Jun 6 2023, 4:55 PM
llvm/unittests/ADT/MappedIteratorTest.cpp
177

I think this line is a mistake. It should be:

EXPECT_EQ(I3, I1);

The test is currently reading a moved-from object (I2).