Repository navigation
fix(cpp): a -> call on a declared container iterator calls the element's method - #2576
Merged
Merged
Conversation
…ent's method `std::deque<Slice>::const_iterator it; it->data()` was matched by the method's name alone, so it could reach any class with a `data`, and `itr->c_str()` on a `std::vector<std::string>::const_iterator` reached gtest's `FilePath::c_str`. A `->` on a value of an iterator type now reaches the container's element, as `->` on a smart pointer reaches what it holds: the element is read from the container's template arguments (cppRangeElementOf), before the container's own `iterator` alias would lose them (protobuf's `RepeatedPtrField<T>::iterator`), and looked up as C++ does. A library element (`std::string`) or the caller's template parameter calls no project method. An element only a class template's own `begin()`/`operator*` writes with its parameter (googletest's `ParamGenerator<T>::iterator`) goes on as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
colbymchenry
added a commit
that referenced
this pull request
Oct 15, 2026
…s the element's method through `->` (#2579) `auto it = logs_.begin(); it->IsSyncing()` had no type for `it`: a call on a library container (`std::deque<LogWriterNumber>`) returned nothing the auto-local reader could use, so `->` calls on it were matched by the method's name. A standard or abseil container's `begin`/`end`/`find`/ `lower_bound`/`rbegin`/… now types as `<container>::iterator`, and a standard search (`std::lower_bound`, `std::find_if`, `std::next`, …) as the iterator it is given first; #2576's cppArrowTarget then reaches the container's element. The element is looked up where the container's type is written (the `auto` local's declared site, a data member's class), not where the call is: an element nested in another class (`vs->obsolete_files_.begin()`) finds that class's type, not a namesake visible at the call. A holder's type stays looked up at the call: from a pimpl member's header the lookup finds a namesake (protobuf's other `DescriptorIndex`) or nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This is the follow-up left after #2573.
A
->call on a C++ receiver declared as a container's iterator was matched by the method's name alone. Examples:std::deque<Slice>::const_iterator it; it->data(), andstd::vector<std::string>::const_iterator itr; itr->c_str(). Such a call could reach any class with a method of that name: in rocksdb,itr->c_str()reached gtest'sFilePath::c_str.A
->on an iterator now reaches the container's element, the same way->on a smart pointer already reaches what it holds (matchCppHeldTypeCall):cppArrowTargetreads the element from the container's template arguments (cppRangeElementOf). It does this before the container's owniteratoralias is followed, because following it would lose those arguments: protobuf'sRepeatedPtrField<T>::iteratoris a typedef ofinternal::RepeatedPtrIterator<Element>.->branch now also takes declarations read through an alias. Holders are unaffected, sincecppHeldTypeonly matches the literalstd::unique_ptr<…>-style spellings.std::string) or the caller's own template parameter calls no project method, as withstd::unique_ptr<T>.begin()/operator*, using its parameter (googletest'sParamGenerator<T>::iterator). Only the specialization decides those, so their calls go on as before.Validation
__tests__/cpp-iterator-arrow.test.ts(5 tests): 4 fail on main and pass here. TheParamGeneratorguard passes on both.stringappend2.cc'sit->data()andit->size()on astd::deque<Slice>::const_iteratornow reachSlice;data_structure.honauto it = findPosition(i)reachInterval::start,endandhas_end.findPositionreturnsstd::vector<Interval<Slice, Comparator>>::iterator. They land on the primary template's methods, the same targets main already gives.calls on that type in the same function.itr->c_str()on astd::vector<std::string>::const_iteratorhad linked to gtest'sFilePath::c_str. It now links to nothing, which is correct for astd::stringelement.property_with_matching_key->SetValueon astd::vector<TestProperty>::iteratorkeeps its target, with confidence up from 0.7/0.65 to 0.9.descriptor.pb.h, which is 1.04 MB, just over the 1 MiB source-file cap. So it's indexed with no nodes, and those calls go on as before.daemon-pid-reuse.test.ts(MCP daemon takeover after SIGKILL), a process-timing test unrelated to resolution; it passed twice when rerun alone.Remaining, out of scope: iterators that are
autolocals initialized by a library container'sbegin()/find()(about 80it->m()sites across rocksdb and protobuf), and(*it)->m()/(*it).m()dereferences (about 30). Each needs its own typing step.🤖 Generated with Claude Code