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

Have a way to disable Drop #523

Closed
canndrew opened this issue Dec 14, 2014 · 4 comments
Closed

Have a way to disable Drop #523

canndrew opened this issue Dec 14, 2014 · 4 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@canndrew
Copy link
Contributor

It would be great if there was a way to disable Drop for a type. What this would mean is that a value that can't dropped has to be moved or have data moved out of it to destroy it.

One use case for this is avoiding leaking threads by having threads that require a handle to the thread to be kept around. Basically, I'd like to write some code like this:

#[no_drop]
struct Thread<T> {
    rx: Receiver<T>,
}

impl<T> Thread<T> {
    fn spawn<F: FnOnce() -> T>(cls: F) {
        let (tx, rx) = channel::<T>();
        spawn(move |:| {
            tx.send(cls());
        });
        Thread {
            rx: rx,
        }
    }

    // Block until the thread exits.
    fn join(self) -> T {
        let rx = self.rx; // move out of self so that self.drop()
                          // is not called at the end of the method
        rx.recv()
    }
}

The problem with writing this is that, if Thread can be dropped it defeats the whole point of the type. But if I implement Drop manually it's not possible to write the join method because it moves self. In today's Rust the closest thing I can do is put rx.recv() in drop() which means that drop() blocks (ew!), and means it's not possible to return a value from the thread.

How I see #[no_drop] working is just that the following code becomes illegal:

fn foo() {
    let x = Thread::spawn(...);
    // x falls out of scope without being moved. Compile error!
}

This is just one example of an application of linear types but I'm sure there are others. For example, a type for serious errors that can't be ignored and which the programmer is forced to handle. Sort of like the lint we have now for Result values but which is enforced.

@Gankra
Copy link
Contributor

Gankra commented Dec 14, 2014

Unfortunately linear types don't play well with unwinding. That is, at any time something can panic and scoop up your no_drop type.

related-ish: #197

@aidancully
Copy link

If I understand correctly, it seems like no_drop as described doesn't necessarily prevent unwinding - it's rather just about causing the compile error when the code is written as described. In that case the drop behavior could only be invoked by panic, or by something like the join method. Is that right? I'd rather see a different name than no_drop in that case, but one isn't leaping to mind at the moment...

@l0calh05t
Copy link

Another application could be things such as files and database connections. Closing a file or database connection on drop is dangerous, because closing can fail (device may no longer be available but there might still be unwritten data in a buffer). The only way for drop to report a failure would be a panic, which complicates handling.

@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Feb 23, 2018
@Centril
Copy link
Contributor

Centril commented Feb 23, 2018

Since this essentially requests linear types, I'm closing in favor of #814.

@Centril Centril closed this as completed Feb 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

5 participants