4 ms·
In what way are you more limited by the compiler in Rust than with C? Just write "unsafe" and you're off to the races. Writing correct C is very hard and most
by kryptiskt 5y ago
In what way are you more limited by the compiler in Rust than with C? Just write "unsafe" and you're off to the races.
Writing correct C is very hard and most definitely not fun. It's like juggling with with 7 balls and if you drop one you'll be shot. C is defined for a weirdo abstract machine that doesn't match what computers really do, and when people apply their intuition and knowledge about computers to their C programs "because C is low-level", it's a crapshoot whether they will trigger undefined behavior and the compiler goes off the rails with wild optimizations.
If I designed a low-level language I would enable such optimizations by making it easy to communicate your precise intent to the compiler. Not by making the standard a minefield of undefined behaviors.
- tialaramex 5y ago> Just write "unsafe" and you're off to the races. I'm pretty sure I mention this in the LWN comments, but, since it gets repeated so often the contradiction might as well be repeated as well: No. Unsafe Rust only gets to do three things that aren't related to the "unsafe" keyword itself. It can dereference raw pointers, it can access C-style unions, it can mutate global static variables. That's everything. Your C program is free to define x as an array with four elements and then access x[6] anyway - but Rust deliberately cannot do that. Not in Safe Rust, but also not in Unsafe Rust either. Writing "unsafe" doesn't mean "Do this anyway" it only unlocks those three specific things I mentioned, and so sure enough x[6] is still not allowed because that's a buffer overflow. In fact by default the Rust compiler would warn you, if you write unsafe { foo[z] = 0; } that unsafe isn't doing anything useful here and you should remove it. That array dereference either is or, if z is small enough, is not, an overflow, and either way unsafe makes no difference.
- geofft 5y agoSince the conversation is claiming that you can do everything in Rust that you can do in C, I want to provide some counter-nuance. :) I am guessing what people actually mean is that all the operations you want to do can be done via unsafe Rust somehow, and yes, you can do that. But also yes, it is not literally "just write 'unsafe'". You do need to use raw pointers. For instance, if you want to overflow a buffer intentionally, fn main() { let mut a = [1, 2, 3, 4]; let b = [5, 6, 7, 8]; let ptr: *mut i32 = &mut a[0]; unsafe { ptr.add(5).write(999); } println!("{:?}", b); } produces [5, 999, 7, 8] https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=10faea2012496ff7313715827739b3b3 https://play.rust-lang.org/?version=stable&mode=debug&editio... (Note that this is not just extremely platform-specific and compiler-specific about whether a is in front of b or vice-versa, it is straight-up Undefined Behavior because you write past the end of an object... but the equivalent C code is also Undefined Behavior, and subject to the same LLVM optimizations. So if you were happy with the corresponding C code, this is the equivalent Rust.) If you really, really want, you can write your own UnsafeSlice type that does the unsafe stuff internally and exposes the standard indexing operator, which would make foo[z] actually accept arbitrary indices just like in C. But you shouldn't. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c920971c9c8f2d0d5c9324a96b3d03e3 https://play.rust-lang.org/?version=stable&mode=debug&editio... (Among other things, a code reviewer should be suspicious of your use of "unsafe" in the internals of a thing without stating why the higher-level abstraction is safe, and in fact the abstraction is wildly unsafe here, so it's bad style to write code that launders the unsafety, so to speak. In the Rust for Linux patches, there are "SAFETY" comments above each use of "unsafe" defending their logical safety.)
- tialaramex 5y agoThis is a little tidier: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=188b76bc7e79c233cc0e25d525c75985 https://play.rust-lang.org/?version=stable&mode=debug&editio... UnsafeSlice is a terrible idea, but let us at least give it the normal ergonomics of a wrapper type so we can say UnsafeSlice(&mut a) rather than needing curly braces to make one :)
- kryptiskt 5y agoYou don't need anymore than that to match what C offers, C as in standard C, not in the folklore of C as a portable assembler. In fact you're freer in Rust than in C, because there is a simple, defined way to type-pun memory in Rust. > Your C program is free to define x as an array with four elements and then access x[6] anyway It's free to do anything, but you can't be sure that it will do that, because of the utterly weak specification.
- drran 5y ago> Your C program is free to define x as an array with four elements and then access x[6] anyway - but Rust deliberately cannot do that. Not in Safe Rust, but also not in Unsafe Rust either. Woot? fn main() { let a = [0, 1, 2]; let _b = [42, 42, 42]; println!("{}", unsafe{a.get_unchecked(6)}); } https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=250da57d35baaed223d43c73dced8b0c https://play.rust-lang.org/?version=stable&mode=debug&editio...
- deleted 5y ago[deleted]
- Arnavion 5y agoThe claim was about `x[6]`, which does not appear in your program. The point is that `[]` is always bounds-checked, and the bounds-checking cannot be opted out of even with `unsafe`.
- fnord123 5y ago> The claim was about `x[6]`, which does not appear in your program. That was C code. The rust code for that was provided by drran. > The point is that `[]` is always bounds-checked, and the bounds-checking cannot be opted out of even with `unsafe`. I don't think anyone is hung up on whether you use std::ops::Index or not. You can access arrays without bounds checks.
- Arnavion 5y agohttps://news.ycombinator.com/item?id=27941675 https://news.ycombinator.com/item?id=27941675 >No. Unsafe Rust only gets to do three things that aren't related to the "unsafe" keyword itself. >[...] >Your C program is free to define x as an array with four elements and then access x[6] anyway - but Rust deliberately cannot do that. Not in Safe Rust, but also not in Unsafe Rust either. >[...] >In fact by default the Rust compiler would warn you, if you write unsafe { foo[z] = 0; } that unsafe isn't doing anything useful here and you should remove it. That array dereference either is or, if z is small enough, is not, an overflow, and either way unsafe makes no difference.
- tinus_hn 5y agoNote that the C version of this might compile but the result is undefined, so it could be what you intuitively thought what would happen, or anything else. Not what you want in a kernel.