Skip to content
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

Use phantomdata in CopyOnDrop #1032

Merged
merged 1 commit into from
Mar 9, 2023
Merged

Use phantomdata in CopyOnDrop #1032

merged 1 commit into from
Mar 9, 2023

Conversation

Manishearth
Copy link
Contributor

@Manishearth Manishearth commented Mar 8, 2023

There is a struct with a destructor borrowing from a local, it would be good to have some lifetimes protecting it from doing the wrong thing.

mergesort.rs also has this type but it's constructing it from raw pointers and I didn't want to infect everything with lifetimes. It's less of a problem there since it's not borrowing from locals.

@Manishearth
Copy link
Contributor Author

Also it might be worth unifying CopyOnDrop with the ManuallyDrops

use std::mem::{self, MaybeUninit};
use std::ptr;

/// When dropped, copies from `src` into `dest`.
struct CopyOnDrop<T> {
struct CopyOnDrop<'src, 'dest, T> {
Copy link
Member

@cuviper cuviper Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it useful to have two lifetimes? They're both covariant, while we're overall invariant in T itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to go for full accuracy in the phantomdata, but we could technically have just one here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess in a few places you're specifying explicit lifetimes parameters, otherwise NLL would probably tighten it to the life of CopyOnDrop itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you like me to change it or leave it as is?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change to one for simplicity, thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I just realized that the first lifetime is unbound anyway. Going to fix this with a constructor, but annoyingly there's no easy way to pass down lifetimes for raw pointers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this look? I could accept a third &mut ptr that ensures that dest is also factored in to the lifetime calculation but for now this seems to work.

Really wish there were a "raw pointer with a lifetime" type that had all the right methods but also the lifetime (but none of the validity constraints)

use std::mem::{self, MaybeUninit};
use std::ptr;

/// When dropped, copies from `src` into `dest`.
struct CopyOnDrop<T> {
struct CopyOnDrop<'a, T> {
src: *const T,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at where we create CopyOnDrop, I think this could just be &'a T?
(But the marker is still useful for invariance in T.)

Or I guess this is where you were suggesting unifying ManuallyDrop... TBH it feels a little uncomfortable that we're even creating a live T copy for ManuallyDrop::new in the first place. We could avoid that with src: MaybeUninit<T>, initialized by copy from a source pointer. The lifetime would just become 'dest, turbofish-constrained as 'v when we create it. What do you think?

Copy link
Member

@cuviper cuviper Mar 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, we're making T copies within v: &mut [T] all over the place, so maybe that MaybeUninit idea doesn't get much closer to real caution here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think it's definitely cleaner to unify it with ManuallyDrop but it's not safer or anything. I don't want to do the broader refactor here though, I was trying to get a small defense in depth win.

src/slice/quicksort.rs Outdated Show resolved Hide resolved
src/slice/quicksort.rs Outdated Show resolved Hide resolved
src/slice/quicksort.rs Outdated Show resolved Hide resolved
@cuviper
Copy link
Member

cuviper commented Mar 9, 2023

bors r+

@bors bors bot merged commit e6186ea into rayon-rs:master Mar 9, 2023
@Manishearth Manishearth deleted the 👻 branch March 9, 2023 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants