-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Compiler isn't trusting programmer in unsafe code #14903
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
(Sorry) |
IRC: "okay then, then I think the core team needs to re-consider what they want with the language. in essence, things like this will send the message that "the compiler knows better", which will result in c/c++ people to not use the language." |
Reopening for discussion at a meeting, but I recommend wontfix/notabug. |
In particular, this just revolves around the new restriction on the |
A function which does the same thing as the old use std::{mem, ptr};
unsafe fn transmute_harder<T, U>(from: T) -> U {
let mut to: U = mem::uninitialized();
// copy_memory and forget can't trigger failure, so `from` and `to` won't have destructor run
// extraneously
ptr::copy_memory(&mut to as *mut U, &from as *_ as *U, 1);
mem::forget(from);
to
}
struct Plane<T> {
data: [T, ..4]
}
struct Vec4<T> {
data: [T, ..4]
}
fn main() {
let plane = Plane { data: [1i, 2, 3, 4] };
let vec: Vec4<int> = unsafe { transmute_harder(plane) };
println!("{}", vec.data.as_slice());
} |
(You can use |
This exposed a more important issue: we don't emphasize enough that Just to point out how bad transmuting can be, I've done a comparison, for this specific example. |
Here's another example that now fails, in gl-rs. It was fixed by this commit: brendanzab/gl-rs@b01df8e pub struct FnPtr<F> { f: F, is_loaded: bool }
impl<F> FnPtr<F> {
pub fn new(ptr: Option<extern "system" fn()>, failing_fn: F) -> FnPtr<F> {
use std::mem::transmute;
match ptr {
std::option::Some(p) => FnPtr { f: unsafe { transmute(p) }, is_loaded: true },
None => FnPtr { f: failing_fn, is_loaded: false },
}
}
} The idea here is to trampoline to the C-function if it exists, and to call the fail function if it doesn't. |
In that case, pub struct FnPtr<..A, R> {
f: extern "system" fn(..A) -> R,
is_loaded: bool
} A better (short term) solution would be to expand // now
pub fn load_with(loadfn: |symbol: &str| -> Option<extern "system" fn()>) {
unsafe { ::storage::$name = ::FnPtr::new(loadfn($sym), ::failing::$name) }
}
// after
pub fn load_with(loadfn: |symbol: &str| -> Option<extern "system" fn()>) {
match loadfn($sym) {
std::option::Some(f) => unsafe {
::storage::$name = ::FnPtr { f: std::mem::transmute(f), is_loaded: true }
},
None => {}
}
} |
I have to admit, the #12898 did explicitly say that the plan would be to only permit transmutes of generics "through pointers" (which I interpret to mean "TypeExpr can only be transmuted behind a |
If you are talking workarounds, |
Closing, as has been noted many times in this thread, this was an explicit decision and this is working as-is today. I believe it is too soon (this only landed 3 days ago) to start revisiting our initial decision. With this patch we have achieved the point where it is impossible to fail in codegen due to upstream crates. It is only possible to fail for a deterministically known issue in the local crate. It would be possible to extend the language with a compiler-defined trait that signifies that two type parameters If there is a legitimate bug in the new transmute restrictions, then that is definitely something that should be dealt with. I would recommend opening a separate issue about perhaps adding a case of transmuting between the same type parameter, which is guaranteed to have the same size. |
With the recent transmute changes, several safe cases are now reported as errors. The most trivial is:
Another is:
There are obviously workarounds, but these are examples that are safe where the type-checker gets in the way. It is also unfortunate that the code is marked as "unsafe", yet the compiler rejects the code.
The text was updated successfully, but these errors were encountered: