Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Unboxed closures with mutable reference parameter #16652

Closed
cgaebel opened this issue Aug 21, 2014 · 2 comments
Closed

Unboxed closures with mutable reference parameter #16652

cgaebel opened this issue Aug 21, 2014 · 2 comments

Comments

@cgaebel
Copy link
Contributor

cgaebel commented Aug 21, 2014

It is either very hard (I don't know how to do it) or impossible to create an unboxed closure that takes a mutable reference. Here are my attempts, with the resulting error messages inline:

#![feature(unboxed_closures)]
#![feature(overloaded_calls)]

// test.rs:4:23: 4:31 error: missing lifetime specifier [E0106]
// test.rs:4 fn doit<T, F: FnOnce<(&mut int,), T>>(f: F) -> T {
//                                 ^~~~~~~~
// error: aborting due to previous error
fn doit<T, F: FnOnce<(&mut int,), T>>(f: F) -> T {
  let x = 4;
  f(&mut x,)
}

fn main() {
  let r: int = doit(|: i: &mut int| i + 1);
  println!("x = {}", r);
}

/////////////////////////////////////////////////////////////////////////

#![feature(unboxed_closures)]
#![feature(overloaded_calls)]

fn doit<'a, T, F: FnOnce<(&'a mut int,), T>>(f: F) -> T {
  let x = 4;
// test.rs:26:10: 26:11 error: `x` does not live long enough
// test.rs:26   f(&mut x,)
//                     ^
// test.rs:24:57: 27:2 note: reference must be valid for the lifetime 'a as defined on the block at 24:56...
// test.rs:24 fn doit<'a, T, F: FnOnce<(&'a mut int,), T>>(f: F) -> T {
// test.rs:25   let x = 4;
// test.rs:26   f(&mut x,)
// test.rs:27 }
// test.rs:24:57: 27:2 note: ...but borrowed value is only valid for the block at 24:56
// test.rs:24 fn doit<'a, T, F: FnOnce<(&'a mut int,), T>>(f: F) -> T {
// test.rs:25   let x = 4;
// test.rs:26   f(&mut x,)
// test.rs:27 }
// error: aborting due to previous error
  f(&mut x,)
}

fn main() {
  let r: int = doit(|: i: &mut int| *i + 1);
  println!("x = {}", r);
}
@japaric
Copy link
Member

japaric commented Aug 21, 2014

AIUI, this kind of usage requires higher-rank lifetimes, once we get that, doit would have this signature: fn doit<T, F: <'a>|: &'a mut int| -> T>(f: F), and your first attempt will work.

If you (desperately) need this code to work right now, you can throw a mem::transmute around the &mut x in your second attempt. But that's very hacky [1], so I recommend waiting for higher-rank lifetimes.

[1] Because 'a shouldn't appear in the generic parameter list of the doit function.

@aturon
Copy link
Member

aturon commented Oct 16, 2014

I'm going to close this as a duplicate of #17661

Thanks for reporting it!

@aturon aturon closed this as completed Oct 16, 2014
bors added a commit to rust-lang-ci/rust that referenced this issue Feb 25, 2024
…643, r=Veykril

internal: fix deadlock introduced by rust-lang#16643

This fixes a deadlock introduced by rust-lang#16643 ([backtrace](https://gist.github.com/davidbarsky/00f17598f5496a9c41aff31fec1c42d6)). `maybe_changed_after` calls back into other queries, so the cloning here is unfortunately inevitable.

(Zulip conversation: https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Fixing.20proc-macro.20dirtying.20with.20unindexed.20projects)
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants