-
Notifications
You must be signed in to change notification settings - Fork 107
CastKind::ClosureFnPointer implemented wrong #413
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
Comments
I just don't understand how cg_llvm managed to implement it correctly. I copied the code to get the shim straight from cg_llvm. |
^ cc @est31 as seem to have implemented it in rust-lang/rust@1b9b322. I hope you can help me. |
Hi @bjorn3 thanks for doing the cranelift work. Really looking forward to trying it out one day in the future!
I'll try to give a full explanation. Consider this code snippet: let v = 32;
let c = |n| {
v - n
};
let w = c(1);
println!("I am est{}", w); Closures are lowered the following way: let v = 32;
struct ClosureC {
v: i16,
}
fn c_closure(this: ClosureC, n: i16) -> i16 {
this.v - n
}
let c = ClosureC {
v
};
let w = c_closure(c, 1);
println!("I am est{}", w); All the captured get put into a custom made struct that get's passed to the function via a When you have a non capturing closure, the struct is empty. let c = |n| {
32 - n
};
let w = c(1);
println!("I am est{}", w); gets lowered to struct ClosureC {
// Nothing here, the closure is non-capturing
}
fn c_closure(_this: ClosureC, n: i16) -> i16 {
32 - n
}
let c = ClosureC {
// Nothing here either
};
let w = c_closure(c, 1);
println!("I am est{}", w); But what does this mean on an ABI level? If you comment out the println because it creates so much irrelevant noise and open debug mode LLVM IR in the playground, you will find the following signature:
Note the single i16 param. In comparison, the same signature for the capturing closure example above:
Basically, the empty struct is just a newtype of Thus, at the ABI level it looks like: fn c_closure(n: i16) -> i16 {
32 - n
}
let w = c_closure(1);
println!("I am est{}", w); You can verify that it indeed has size zero: struct ClosureC {
// Nothing here, the closure is non-capturing
}
assert_eq!(std::mem::size_of::<ClosureC>(), 0); Now, we can actually coerce the closure to a function pointer: fn c_closure(n: i16) -> i16 {
32 - n
}
let ptr: fn(i16)->i16 = c_closure;
let w = ptr(1);
println!("I am est{}", w); That's all there is to it. TLDR: In the type system there is a I hope I could help. |
Thanks! That explains it. Will update cg_clif soon. |
The signature of
fn0
doesn't match the expected signature. Somehowfn0
has a signature with aself
param, while it shouldn't.The text was updated successfully, but these errors were encountered: