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

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)
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

No branches or pull requests

3 participants