-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add retain function #59
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have questions. Also, needs tests. Thanks!
lib.rs
Outdated
} | ||
} | ||
Heap { ptr, capacity } => unsafe { | ||
Vec::from_raw_parts(ptr, len, capacity).retain(f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this drop the vector afterwards, causing a use after free the next time it's accessed? Also, I see nothing updating the ptr
field, which may change I suppose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it would be dropped afterwards. I think you should get the new pointer, len and capacity from the vec and mem::forget
it afterwards.
lib.rs
Outdated
if !f(&*array.ptr().offset(i as isize)) { | ||
del += 1; | ||
} else if del > 0 { | ||
swap(&mut array.ptr().offset((i - del) as isize), &mut array.ptr().offset(i as isize)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the item has a destructor, what calls it?
@emilio I've addressed your comments and added tests, thanks for the help! |
Travis only failed on nightly. Probably a regression in nightly. EDIT: woops nevermind, looks like I accidentally broke nostd support. I just added a commit that should fix this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib.rs
Outdated
} | ||
} | ||
if del > 0 { | ||
self.len = len - del; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This can just be self.len -= del;
, since del
cannot be less than zero.
Squished and addressed your nit. |
lib.rs
Outdated
} | ||
} | ||
} | ||
if del > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no need for the if
, that's what I wanted to avoid in the first place :)
lib.rs
Outdated
read(array.ptr().offset(i as isize)); | ||
del += 1; | ||
} else if del > 0 { | ||
swap((array.ptr().offset((i - del) as isize) as *mut A::Item).as_mut().unwrap(), (array.ptr().offset(i as isize) as *mut A::Item).as_mut().unwrap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Can't we just do self.swap(i - del, i)
? We implement DerefMut<[A::Item]>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed if we do that and avoid the ptr::read
, calling truncate()
at the end, we can write this just with safe code, right?
@emilio Thanks for the review! The code has been greatly simplified and is no longer unsafe. |
@bors-servo: r=emilio,jdm |
📌 Commit 5879b5e has been approved by |
Add retain function <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/59) <!-- Reviewable:end -->
☀️ Test successful - status-travis |
More out of curiosity than any kind of dire need, does this project have any kind of regular release cycle? |
It is released whenever someone makes a PR that updated the Cargo.toml version. |
This didn't occur to me until just now, but we might want to change the |
Why would you want to mutate in a retain? It seems like you'd be better off doing for thing in things {
// Mutate thing
}
things.retain(/*closure*/); I like this approach better as it's more clear that there is a side effect happening. |
Putting the mutation into a separate loop might require allocating additional memory to save intermediate state, while just using
This can't be done in two separate loops like the code above, without saving additional state. Even in cases that can be easily separated, iterating over the collection twice instead can be a significant performance penalty. And since the |
Alright that all makes sense. The current retain got released in 0.4.3 which still has 0 downloads so if we hurry and yank it we can still fix this. |
It might be less hassle to just fix this next time we make a release with breaking changes. |
This change is