3 ms·
I know and agree that unsafe Rust is problematic, but that criticism of this is missing the forest for the trees. The original code is just as unsafe. Refactor
by dbaupp 8y ago
I know and agree that unsafe Rust is problematic, but that criticism of this is missing the forest for the trees. The original code is just as unsafe.
Refactoring from unsafe Rust into safe Rust manually is likely to be easier than directly from C into Rust: one is only trying to deal with one small delta (like changing length/pointer arguments into a slice) rather than also having to deal with syntax changes and tooling issues.
As others have said, it is essentially impossible to automatically translate to safe Rust without non-trivial annotation effort, since C the language and C in practice is very different to how Rust guarantees safety. It seems to me that that "annotation" effort is probably better spent going unsafe to safe Rust (where, subjectively, the language is nicer to use, like better enums and less error prone control flow) rather than annotating the original C.
- stefan_ 8y agoI think it is you missing the forest for the trees. The majority of C code does not in fact have unsafe memory accesses. So clearly we have a problem here with the translator being too stupid or the language; neither is something I look for in a tool I use.
- dbaupp 8y agoNo, all memory accesses in C are unsafe in the keyword-in-Rust sense: `unsafe` indicates that an API can be misused to cause undefined behaviour, contrasting to non-`unsafe` code where any potential undefined behaviours will be caught at compile time or runtime, no matter how incorrect the program/use of the API is. Just like C, it is an incorrect Rust program if undefined behaviour actually happens, meaning all uses of `unsafe` have to actually be safe, but it's up to the programmer to ensure this, with less compiler assistance than in normal Rust. Every single pointer access `*p` or `p[i]` in C has potential for undefined behaviour (e.g. p is NULL, points to an invalid object, or i is out of bounds), and thus the Rust equivalent is surfacing this risk in a more obvious way.
- dbaupp 8y ago(It would have been clearer if my original comment said: "The C and the Rust both risk undefined behaviour in the same ways", instead of using an overloaded meaning of unsafe in saying that the C is unsafe.)
- gue5t 8y agoIn the context of Rust, unsafe does not mean incorrect or vulnerable to memory unsafety. Unsafe refers to code whose memory safety has not been proven (by the compiler's static analysis based on ownership and lifetimes, given the assumption of correctness of other unsafe code (so you can look at the proof of memory safety of a program as a whole as an inductive tree of proofs, with the leaves being unsafe code like in `std::Vec`, which is subject to formal and practical scrutiny outside of rustc's static analysis). By this definition, all C code has unsafe memory accesses. However, it is possible to define static analyses that can prove memory safety of some portions of C programs, and incorporating such a thing into C2Rust would allow it to generate more safe Rust and less unsafe Rust.
- amelius 8y ago> The original code is just as unsafe. But the translated code being unreadable to humans adds a whole new layer of "unsafe".
- Laaas 8y agoI wouldn't call that unreadable at all
- dbaupp 8y agoWhile the translated code is harder to read, it's much easier to refactor into compiler-checked safe code than the original C. I think doing the translation as part of a larger migration from C to safe Rust is essentially the only defensible reason to do it, as it doesn't seem like other reasons can justify the risk of (as one of the sibling comments points out) bugs in the translator and the code being unreadable, aka, in an "unnatural" representation of trying to express C idioms in Rust. That is to say, I don't think humans should be reading or maintaining this code for more than it takes to refactor to be safe(r). (Whether this is how this sort of tool is used in practice is a different question, and one that definitely needs to be considered.)
- platinumrad 8y ago>The original code is just as unsafe. That assumes zero translation errors as well as the original C code not relying on a particular compiler's specific implementation of unspecified behavior.
- dbaupp 8y agoYour first point is of course true, but most statements about the behaviour of code needs to have "assuming no bugs" appended to it, so I'm not sure that it's a particularly interesting point. A more precise interpretation might be that the translator is likely to have more bugs than other components in the pipeline (the compilers and linkers etc.), since it is unlikely to be used nearly as much as them; I wonder if one could do things like compile with rustc and clang and somehow compare the LLVM IR for equivalence (but... I suspect that the code generation patterns for each aren't similar enough). As for unspecified behaviour... that's true! Again I wonder if clang is a useful component here: I suspect if C code behaves correctly with clang, then the translation to Rust compiled with rustc probably works too, both because the translator uses clang, and because both compilers use LLVM. The point (in contrast to the usual complaint of Animats) I was trying to convey, but was nitpicked was: a correct translation from fully-specified C to unsafe Rust doesn't add any unsafety. Whether this applies in practice is slightly different, but there's questions about whether pretty much any statement about C code applies in practice: since undefined behaviour is so rife and easy to trigger, many/most programs are outside the specification (fuzzing C programs often results in segfaults---undefined behaviour---and so the program is outside the bounds of C). Wrapping up, I'll emphasise that the value in this sort of translation is as a stepping stone towards safe Rust, not as a final `unsafe` product.
- dataking 8y ago> I wonder if one could do things like compile with rustc and clang and somehow compare the LLVM IR for equivalence The approach we've taken so far with C2Rust is to build compiler plugins that instrument C and Rust code so we can dynamically check their behavior when fed the same input. https://github.com/immunant/c2rust/tree/master/cross-checks https://github.com/immunant/c2rust/tree/master/cross-checks