You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jul 3, 2024. It is now read-only.
I think that line15 means that the iterator does not dangle (that is why line 15 is there).
But I think that -Wlifetime cannot follow the loop logic? Although I thought I saw in one of your talks that it does "1st iteration" and "all other iterations", which would mean it could hypothetically work this out?
Or it is that -Wlifetime disagrees with my interpretation of which iterators get invalidated:
No iterators or references become invalidated, the iterators to moved elements remain valid, but now refer into *this, not into other.
My code assumes that iterators to elements not moved remain valid. Only one element (*iter) is splice moved to destination on each iteration. ie line 15 iter_next = std::next(iter) should provide (via line 17) a non dangling value of iter for the 2nd and subsequent loop iterations?
Am I being Unrealistic? Needs annotating? How?
Code (same as on godbolt above).
#include<algorithm>
#include<list>
#include<iostream>template <typename T, typename UnaryPredicate>
voidmove_append_if(
std::list<T>& origin,
std::list<T>& destination,
UnaryPredicate&& predicate) {
for (auto iter = std::find_if(origin.begin(), origin.end(), predicate);
iter != origin.end();
iter = std::find_if(iter, origin.end(), predicate)) {
auto iter_next = std::next(iter);
destination.splice(destination.end(), origin, iter);
iter = iter_next;
}
}
intmain() {
auto o = std::list<int>{1,3,11,12,13,4,5,15};
auto d = std::list<int>{};
move_append_if(
o, d, [&](constauto& e) { return e < 10; });
for (auto e: o) {
std::cout << e << "";
}
std::cout << '\n';
for (auto e: d) {
std::cout << e << "";
}
std::cout << '\n';
}
The text was updated successfully, but these errors were encountered:
There are actually multiple problems here. The lifetime analysis does not have knowledge about splice, so it has some really dumb heuristics and concludes that it must invalidate the owner. This part is easy to fix, we either need to annotate splice as lifetime_const or hardcode this knowledge into the check.
The other part is the moving. Unfortunately, we did not implement support for move operations yet. I think, currently, this is out of reach for the lifetime analysis, and you can use gsl::suppress annotation to suppress the analysis for the function. Hopefully, once we have move support in place, we can analyze this without any issues.
Thank you! But is this splice actually a move? I am trying to imagine what happens during a list.splice and it's just a that a bunch of pointers get moved around right? Is this semantically the same as a "move"? I guess it is, in the sense that the "owner of that element has now changed" without making a "copy".
Unfortunately, this specific issue is not solved by that commit.
I think the best way to describe what splice does on the more abstract level is to transfer ownership. In the implementation it is only about rewiring some pointers, right. But actually, when you move a vector, something very similar will happen. The implementation just rewires some pointers and the buffer will stay in place. So your description is quite accurate.
Modeling splice is quite a challenge though, as lifetime analysis has no knowledge which element does an iterator point to. So I am not sure if we will ever have a 100% solution to this problem. :(
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Thank you for your fantastic work on
-Wlifetime
!I have extracted and minimized an example from real code of what I think is a false positive.
Warning diagnostic shown by
experimental -Wlifetime
on godbolt:This is the example on godbolt.
Code also below.
I think that line15 means that the iterator does not dangle (that is why line 15 is there).
But I think that
-Wlifetime
cannot follow the loop logic? Although I thought I saw in one of your talks that it does "1st iteration" and "all other iterations", which would mean it could hypothetically work this out?Or it is that
-Wlifetime
disagrees with my interpretation of which iterators get invalidated:https://en.cppreference.com/w/cpp/container/list/splice
My code assumes that iterators to elements not moved remain valid. Only one element (
*iter
) is splice moved to destination on each iteration. ie line 15iter_next = std::next(iter)
should provide (via line 17) a non dangling value ofiter
for the 2nd and subsequent loop iterations?Am I being Unrealistic? Needs annotating? How?
Code (same as on godbolt above).
The text was updated successfully, but these errors were encountered: