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

Missing drop in FnOnce adapter for closures #29946

Closed
eefriedman opened this Issue Nov 20, 2015 · 12 comments

Comments

Projects
None yet
10 participants
@eefriedman
Copy link
Contributor

eefriedman commented Nov 20, 2015

struct Foo(i32);
impl Foo {
    pub fn dowork(&self) {
        println!("foo: doing work {}", self.0);
    }
}

impl Drop for Foo {
    fn drop(&mut self) {
        println!("foo: drop {}", self.0);
    }
}

fn f<T: FnOnce()>(t: T) {
    t()
}

fn main() {
    let x = Foo(1);
    let x = move || x.dowork();
    f(x);
}

playpen

Somehow, the Foo object leaks: my guess is that it has something to do with the way we generate code for the FnOnce() trait for closures which also implement Fn().

Originally reported at #28796 (comment) .

@Manishearth

This comment has been minimized.

Copy link
Member

Manishearth commented Nov 22, 2015

cc @pnkfelix

I think I've seen this before, happens with other traits as well.

@Gankro Gankro added the I-nominated label Nov 22, 2015

@eddyb eddyb added the T-compiler label Nov 22, 2015

@pnkfelix pnkfelix self-assigned this Dec 3, 2015

@arielb1 arielb1 added the I-wrong label Dec 3, 2015

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Dec 3, 2015

triage: P-medium

1 similar comment
@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Dec 17, 2015

triage: P-medium

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

This appears to only happen if 1. the closure is called via a generic function, and 2. the captured variable is not explicitly moved into the closure body.

If "let a = x;" is used in place of calling a borrowing method, the destructor is called.

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

Preliminary investigation - The cause is from the closure not being treated as FnOnce when destructor calls are added to the "body" (in rustc_trans/trans/closure.rs load_closure_environment)

This is exposed when the closure is explicitly called as FnOnce (leading to ownership transfer into the closure, and hence no destructor being called).

Routes to fixing:

  1. Alter ClosureKind determining to take into account usage
  2. Insert a checked destructor invocation after calling a FnOnce closure (and let the drop flags prevent double-drop for working cases)
  3. (Unknown if possible) When a Fn/FnMut closure is called as a FnOnce, explicitly drop after calling (in the call_once "method").
@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

::rustc_trans::trans::closure::trans_fn_once_adapter_shim exists, and is possibly the culprit.

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Feb 7, 2016

I don't think the shim is used here.

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

I'm reasonably sure it is. It is being run, and registers self to be dropped, but cleans up the scope without generating destructor calls

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

src/librustc_trans/trans/closure.rs#L424 appears to be the culprit, changing that line from

fcx.pop_custom_cleanup_scope(self_scope);

to

fcx.pop_and_trans_custom_cleanup_scope(bcx, self_scope);

Leads to my test case passing.

I'm running the full test suite now in preparation for a PR.

@arielb1

This comment has been minimized.

Copy link
Contributor

arielb1 commented Feb 7, 2016

trans::meth is such a hack

thepowersgang added a commit to thepowersgang/rust that referenced this issue Feb 7, 2016

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

@arielb1

trans::meth is such a hack

What do you mean by that?

thepowersgang added a commit to thepowersgang/rust that referenced this issue Feb 7, 2016

thepowersgang added a commit to thepowersgang/rust that referenced this issue Feb 7, 2016

@thepowersgang

This comment has been minimized.

Copy link
Contributor

thepowersgang commented Feb 7, 2016

PR with fix filed #31462 - Running full local tests at the moment, stage1 passed

thepowersgang added a commit to thepowersgang/rust that referenced this issue Feb 7, 2016

bors added a commit that referenced this issue Feb 8, 2016

Auto merge of #31462 - thepowersgang:fix_29946, r=dotdash
Generates drop calls at the end of the Fn/FnMut -> FnOnce closure shim

Fix #29946

bors added a commit that referenced this issue Feb 8, 2016

Auto merge of #31462 - thepowersgang:fix_29946, r=dotdash
Generates drop calls at the end of the Fn/FnMut -> FnOnce closure shim

Fix #29946

@bors bors closed this in #31462 Feb 8, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.