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

Library support for go-like deferred function #1523

Closed
brson opened this issue Jan 14, 2012 · 7 comments
Closed

Library support for go-like deferred function #1523

brson opened this issue Jan 14, 2012 · 7 comments
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@brson
Copy link
Contributor

brson commented Jan 14, 2012

I recently wrote the following to get some behavior like a 'finally' block:

        resource finally(ch: comm::chan<monitor_msg>) {                                                                                            
            comm::send(ch, done);                                                                                                                  
        }                                                                                                                                          

        let _finally = finally(ch);

What I really wanted to write was:

defer {||
    comm::send(ch, done);
}

Or something structured like try/finally.

I tried to devise some way to write a defer library function but there doesn't seem to be any safe way to do it since blocks can't be put into resources.

@brson
Copy link
Contributor Author

brson commented Jan 14, 2012

Maybe there's some way to build something that looks like try finally. It's not safe to put a block into a resource, but we could do it unsafely if we can guarantee the resource doesn't escape. Something that looks vaguely like:

try {||
  ... something
} finally {||
  ... always run this
}

Could be implemented.

@brson
Copy link
Contributor Author

brson commented Jan 14, 2012

So this works:

impl finally for fn@() {                                                                                                                           
    fn finally(f: block()) {                                                                                                                       
        resource r(f: fn@()) {                                                                                                                     
            f();                                                                                                                                   
        }                                                                                                                                          
        unsafe {                                                                                                                                   
            let _r = r(unsafe::reinterpret_cast(f));                                                                                               
            self();                                                                                                                                
        }                                                                                                                                          
    }                                                                                                                                              
}                                                                                                                                                  

fn main() {                                                                                                                                        
    let a = @"toast";                                                                                                                              
    fn@() {                                                                                                                                        
        log(error, "test");                                                                                                                        
    }.finally {||                                                                                                                                  
        log(error, a);                                                                                                                             
    }                                                                                                                                              
}  

The only problem is that the try block is a fn@ not a fn& because of limitations on where you can write fn&.

@nikomatsakis
Copy link
Contributor

It seems to me that we should just define an inline resource syntax. Admittedly, the "finally" code then appears at the top---but that kind of makes sense to me. D has something similar: a way to say, "this code will run on all exits"

@brson
Copy link
Contributor Author

brson commented Mar 13, 2012

I took another stab at it:

fn main() {
    let a = @"toast";
    {|finally| try(finally) {||
        log(error, "test");
    } } {||
        log(error, a);
    }
}

fn try(finally: fn(), try: fn()) {
    resource r(finally: fn@()) {
        finally();
    }
    unsafe {
        let finally: *u8 = unsafe::reinterpret_cast(ptr::addr_of(finally));
        let wrapper = fn@() {
            (*unsafe::reinterpret_cast::<*u8, *fn()>(finally))();
        };
        let _r = r(wrapper);
        try();
    }
}

It's hideous, but it's all stack closures.

@catamorphism
Copy link
Contributor

If resources are going away, to be replaced with classes, how does that affect this issue? Currently it doesn't seem possible to have "anonymous" classes, since classes are inherently nominal.

@ghost ghost assigned brson Apr 12, 2012
@brson
Copy link
Contributor Author

brson commented Apr 14, 2012

I'm hoping that classes with region fields can be used to build defer, but I don't know how.

@catamorphism
Copy link
Contributor

Closing this because the last activity was 10 months ago and I'm going to assume that was @brson was hoping for is true. Reopen if necessary.

celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
* Remove `Invariant` from stdlib example

* Remove `Invariant` from Firecracker example

* Format

* Use `Self` and remove trivial `is_valid` methods

* Remove leftover semicolon
bjorn3 added a commit to bjorn3/rust that referenced this issue Aug 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

3 participants