-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Improve unsafe ergonomics #433
Comments
#399 is also related. |
We also need better (or maybe just more prominent) documentation on what makes safe unsafe code, for instance what are the exact guarantees that rustc makes to LLVM that we have to uphold, what is UB, what is exception safe, etc. |
@reem: http://doc.rust-lang.org/reference.html#behavior-considered-unsafe (the header should really say undefined) |
It doesn't have a complete list of UB possible via intrinsics, but other than that it covers nearly everything. |
Added possibly relevant: #556 |
@dtolnay you said in #44932 that we might want to support To argue the other way: without it, Rust can guarantee that a One is that we can have object-safe, safe trait methods that take a raw pointer as the trait TypeName {
fn type_name(self: *const Self) -> &'static str;
}
impl TypeName for i32 {
fn type_name(self: *const Self) -> &'static str { "i32" }
}
println!((ptr::null::<()>() as *const TypeName).type_name()); // prints `i32` Without this guarantee, the above wouldn't be possible because calling a method on a trait object with an invalid vtable would segfault (like in Go) or cause undefined behaviour. Similarly, the Another nice thing about guaranteeing that vtable pointers will always be valid is that it would enable the null-pointer optimization for 1 If you want to test this out, you can check out my raw_pointer_self branch. Just make sure you |
We already mark the vtable as As far as I'm concerned, we already guarantee it anyway, as nothing in the language distinguishes between safe vs raw pointers in terms of DST metadata (e.g. generic conversions between between different kinds of pointers/references with the same unsized "tail" are allowed, even if it's a type parameter, and we guarantee identical sizes and metadata types) and so that makes it the only path forward to custom DSTs to me. |
Thanks for the explanation @mikeyhew! I'm glad it is that clear-cut. I found it helps to understand an interface in Go as equivalent to |
@dtonlay Yeah, that's probably a good way to think about it. You could go a bit farther, though: as far as I understand it, pointers in Go are guaranteed to point to a valid value, unless they are nil. So they are like I was trying to wrap my brain around why Go allows interface values to be nil outright. Then I remembered, you need some way to have a value that "isn't there", and since there's no |
Remove `T: Sized` on `ptr::is_null()` Originally from #44932 -- this is purely a revert of the last commit of that PR, which was removing some changes from the previous commits in the PR. So a revert of a revert means this is code written by @cuviper! @mikeyhew makes a compelling case in rust-lang/rfcs#433 (comment) for why this is the right way to implement `is_null` for trait objects. And the behavior for slices makes sense to me as well. ```diff impl<T: ?Sized> *const T { - pub fn is_null(self) -> bool where T: Sized; + pub fn is_null(self) -> bool; } impl<T: ?Sized> *mut T { - pub fn is_null(self) -> bool where T: Sized; + pub fn is_null(self) -> bool; }
Right now, it can be a bit unwieldy to write unsafe code -- whether skipping bounds checks or working with raw pointers. To some degree this can and will be mitigated through API design, but new language features may help as well. For example, we could consider offering unsafe indexing notation, or allow indexing onto raw pointers, etc.
There are at least two closed RFCs on this topic presenting some good ideas that we were not ready to commit to for 1.0:
Raw reform
Unsafe indexing
The text was updated successfully, but these errors were encountered: