-
Notifications
You must be signed in to change notification settings - Fork 21
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
GenericDetour doesn't work with unsafe fns #13
Comments
I can get it to compile (on 1.69.0 and nightly) by commenting out this line: Line 204 in 9624176
That part of the macro expands to something like this: unsafe impl<Ret: 'static, A: 'static> HookableWith<extern "system" fn(A) -> Ret>
for unsafe extern "system" fn(A) -> Ret
{
} Somehow it's preventing the compiler from seeing the blanket implementation: Line 25 in 9624176
|
After doing some more research, I realized why this trait is needed in the first place. pub unsafe fn new<F: Function>(target: F, detour: F) -> Result<Self> ...but that fails to compile because rustc sees different function pointers (with identical signatures) as distinct types: unsafe fn a() {}
unsafe fn b() {}
GenericDetour::<unsafe fn()>::new(a, b)
This change was introduced in this PR: rust-lang/rust#19891 It's possible to work around it like this (not particularly pretty, but could be easily improved with a macro): unsafe fn a() {}
unsafe fn b() {}
GenericDetour::<unsafe fn()>::new(a as unsafe fn(), b) |
Thanks for doing so much research into this. I would like to improve some of the ergonomics of unsafe impl<Ret: 'static, A: 'static> HookableWith<extern "system" fn(A) -> Ret>
for unsafe extern "system" fn(A) -> Ret
{ /* ... */} actually serves a specific purpose. It allows you to detour an unsafe function with a safe function, such as a closure. Rust doesn't support unsafe closures. Could be useful for use of I'm not 100% sure why the extra impl messes with the blanket impl. Maybe Rust can't choose the how to coerce |
I thought the same thing, but turns out that still works even without the trait impl. Here's a minimal reproduction of the issue: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8c469a109720b1fb7a270374986fa358 You'll notice all 3 blocks compile just fine until you uncomment the trait impl. |
Interesting that it works, but sounds good. I'll merge your PR when I get home tonight and I'll bump the crate to 0.2.0 because it does seem to break some syntax. |
I didn't notice anything like that. Do you have an example? |
Sorry, I meant to put it into my earlier comment. This syntax only seems to work with the macro impl: unsafe fn add5(val: i32) -> i32 {
val + 5
}
GenericDetour::<unsafe fn(i32) -> i32>::new::<fn(i32) -> i32>(add5, |val: i32| val + 10) It's a more verbose way to solve the problem. Your PR reduces some of the verbosity, coercing the second parameter. |
I'll wait until this discussion is done before I push 0.2.0, just so there's not any additional changes. |
Oh I see. That's interesting. Personally I think a patch bump would suffice (0.1.1) because 0.x crates aren't required to be fully backward-compatible. I'll leave it to your discretion. |
From my understanding, 0.1.z and 0.2.z don't have to be backwards compatible, but 0.1.0 and 0.1.1 do. The distinction between 0.y and 1.y is that once a crate's version hits 1.y, all 1.y versions need to be backwards compatible. So no breaking changes, unless you bump to 2.y. I'll go ahead and publish your changes to crates.io under 0.2.0 and close this issue. If there's anything more you want to discuss about the issue, don't be afraid to reopen it or create a new issue |
On Rust stable (1.69.0),
GenericDetour
fails to compile forunsafe fn
detours.It compiles if you either:
a) remove
unsafe
from the signatures; orb) re-enable the
nigthly
feature and switch to a nightly toolchainThe text was updated successfully, but these errors were encountered: