8 ms·
C2Rust: translate C into Rust code
- m0meni 8y agoHow’s this compare to https://github.com/jameysharp/corrode https://github.com/jameysharp/corrode
- sitkack 8y agoHe doesn't appear to be a direct contributor, probably more of an inspiration. The only overlap I know of is that he also works/worked at Galois. c2rust is written mostly in Rust, Python and C where as corrode was written in Haskell. The output of c2rust looks more like a literal projection from C into Rust, Corrode tried to limit the use of unsafe. $ tokei ------------------------------------------------------------------------------- Language Files Lines Code Comments Blanks ------------------------------------------------------------------------------- Autoconf 4 199 85 56 58 C 88 6989 5175 754 1060 C Header 21 2949 1497 1073 379 CMake 5 84 60 10 14 C++ 5 3015 2320 295 400 C++ Header 1 132 101 7 24 Dockerfile 1 62 50 6 6 HTML 2 84 78 0 6 Makefile 3 88 63 3 22 Markdown 23 1482 1482 0 0 Python 26 6597 4988 319 1290 Rust 250 45111 35949 2893 6269 Shell 44 697 429 141 127 Plain Text 15 555 555 0 0 TOML 11 197 148 24 25 Vim Script 1 233 195 4 34 ------------------------------------------------------------------------------- Total 500 68474 53175 5585 9714 -------------------------------------------------------------------------------
- masklinn 8y ago> The output of c2rust looks more like a literal projection from C into Rust, Corrode tried to limit the use of unsafe. I don't think either statement is true. Both projects bill themselves as semantics-preserving translators, as in they try to generate Rust code which compiles and works the same way the original C code did (in fact corrode has a cc script which first compiles C to Rust then Rust to native). Citrus is the literal projection: it's not semantics-preserving and usually doesn't generate compilable code.
- glguy 8y ago(I'm one of the authors of this tool) Our original plan was to simply work to improve Corrode. We eventually decided to to implement a new tool that uses Clang as the frontend in order to get more reliable parsing, preprocessing, and type checking of the input C code. The result is that we are able to support more code and C extensions than we thought we'd be able to building on top of the good work of the Corrode project.
- phkahler 8y agoIs there any hope of going after even a subset of C++? I know the difference is enormous, I'm just asking the question.
- glguy 8y agoWe've only started pondering what subset of C++ we might be able to support in future work for the project. Currently only C is in scope. That's an obvious next goal but it seems quite a bit more daunting!
- deleted 8y ago[deleted]
- craftyguy 8y agoMissed opportunity to name it 'crust'
- skolemtotem 8y agoI don't remember what, but there is already something fairly popular in the Rust ecosystem with the name crust. Edit: I think it was https://github.com/maidsafe/crust https://github.com/maidsafe/crust .
- kps 8y ago‘C-water’, because it makes things rust.
- projektfu 8y agoOr maybe c-salt
- grok2 8y agoThe insertion sort conversion example makes Rust look intimidating and verbose as compared to C :-).
- smt88 8y agoI personally like more verbosity than one usually sees in C code. Explicitness is mostly a feature for me, though there needs to be a balance.
- glguy 8y agoFortunately, once you start refactoring the Rust to take advantage of the functionality that doesn't exist in C (like slices, iterators, etc), things start to look much cleaner. Translating the code into ugly, unsafe Rust is intended to only be the first step. We're working on tools to help with that refactoring process, too.
- taneq 8y agoSounds like a case of "writing C in Rust" compared with "writing Rust". You're not really writing in a language until you're thinking in its idioms.
- FreeFull 8y agoA translator like this is still really useful as the first step of transforming a C codebase into a Rust codebase. The important thing is to get working code first, and then you can modify the code to be more idiomatic.
- masklinn 8y ago> Sounds like a case of "writing C in Rust" compared with "writing Rust". Duh? It's literally taking C code and generating Rust code which behaves the same. > You're not really writing in a language until you're thinking in its idioms. The entire point is to get your foot in the door. This gives you a pile of Rust code which (bugs aside) should behave the exact same way C code does. From there on you're living in the Rust world and can improve that as you see fit. If you can afford doing the initial transition in one short, later improvements are much simpler than having to maintain an internal (moving) front between remaining C code and new Rust code as e.g. librsvg does.
- csomar 8y agoSo the demo does actually translate C into unsafe Rust. I'm guessing this translator is, thus, unaware of Rust borrowing/ownership system?
- glguy 8y agoThat's right. The translator just tries to preserve the original code. Refactoring things into proper, idiomatic Rust is the next step. The hope is that it will be easier to get the translation correct transforming unsafe Rust to safe Rust than having to go from C to safe Rust.
- masklinn 8y ago> So the demo does actually translate C into unsafe Rust. It's semantics-preserving, and C constructs are not expected to match safe Rust, so that makes sense, Corrode does more or less the same. Citrus generates "safe rust", it also doesn't generate working code.
- sitkack 8y agoThe compilation target could be a Rust slab [0], much like Emscripten uses Typed Arrays [1]. In doing so, it would retain much of the safety properties of Rust, but it pushes the problem into maintaining "the heap" for the C code. [0] https://github.com/carllerche/slab https://github.com/carllerche/slab [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays https://developer.mozilla.org/en-US/docs/Web/JavaScript/Type...
- masklinn 8y agoThat would be significantly less useful if the intent is to move the code from C to Rust.
- sitkack 8y agoHow so? It allows unsafe C to be incorporated into safe Rust while maintaining the same level of safety. A similar less ergonomic solution would be to load C via WASM modules. I'd take slab or wasm over whole lib translation into unsafe Rust.
- mankash666 8y agoWhat's the use case for this? Are native C binaries/libraries not invokable in rust?
- civilitty 8y agoYes, you can call any C using the Rust FFI but then you need to create a safe wrapper around the unsafe Rust calls to C. This tool looks like it's for generating a first pass at porting existing C code to Rust. Once you have that C-to-Rust conversion, it becomes much easier because you can incrementally port select types instead of incrementally porting the API and dealing with the impedance mismatch between the Rust api and C api (you can work on function arguments instead of function calls).
- devit 8y agoI think the next step would be to have a tool that can convert C into safe Rust with a combination of static analysis and framework/program-specific user-written rules to translate specific C framework constructs into Rust equivalents. An eventual goal could be for instance to automatically translate the Linux kernel with the aid of a lot of custom rules to handle its constructs.
- hyperpape 8y agoThere's a real sense in which, if this were true, we might not need Rust. If we could mechanically translate the Linux kernel to safe Rust, we could prove the Linux kernel safe. If we could prove the Linux kernel safe, that would be a strong argument against a need to translate it to Rust. Note that this point is independent of the question of whether rewriting the Linux kernel in Rust is actually good/feasible idea. I also think that Rust has other advantages over C that aren't just safety, so it's not a complete comparison--safety is just the biggest one.
- bluejekyll 8y agoThe major difference would be that future versions would be in safe Rust as well. All code written after that point would be safe. What you say is true for a single point in time, not for the long-term future. But, I would say this is probably infeasible, so theorizing too much about it seems a little wasteful. If the Linux maintainers, Linus et al, suddennly decided to convert to Rust, it would probably done incrementally, module by module. But it’s unlikely to happen given past statements.
- hyperpape 8y agoIf we had a standard for safe C that the linux kernel could feasibly meet, then it could be a condition of future changes that it continue to be safe. As you say, it's pretty hypothetical on both fronts--we're not gonna be able to prove that about a C project like the kernel, and they're not gonna rewrite in Rust any time soon.
- Animats 8y agoThis is compiling C into very unsafe Rust as a target language: pub unsafe extern "C" fn insertion_sort(n: libc::c_int, p: *mut libc::c_int) -> () { let mut i: libc::c_int = 1i32; while i < n { let tmp: libc::c_int = *p.offset(i as isize); let mut j: libc::c_int = i; while j > 0i32 && *p.offset((j - 1i32) as isize) > tmp { *p.offset(j as isize) = *p.offset((j - 1i32) as isize); j -= 1 } *p.offset(j as isize) = tmp; i += 1 }; } The output is unmaintainable, like the output from a compiler. This isn't translation into usable Rust. A C++ to Rust translator would be a good thing, but it has to be much smarter than this. This doesn't even comprehend arrays in C. A good translator might need some human help to deal with C's ambiguities. Like "Is this an array? (Y or N)" How big is it? (Enter expression). Then you get a program that's real Rust. If the user is wrong about the size, safe Rust will either allocate too much space or get a subscript error.
- civilitty 8y agoThe problem is the type noise, which may or may not be avoidable. Most of the mess you see there is probably better expressed as std::mem::* function calls which give proper names to the operations (you can see one of them, .offset, used here but it's a very general function). I don't think it's a good idea to try to convert C code like this to more complex std::mem calls automatically but once you have the ugly Rust code, it becomes relatively easy to start porting it to be more Rustic. The bigger issue I see here is that this should be implemented as an iterator. I don't think there's any hope of automatically converting to those though - there's just no C equivalent except pointer arithmetic.
- wtetzner 8y agoEven though it's translating to unsafe Rust, it does still have some value. In particular, C libraries can be converted into Rust libraries that can be managed via Cargo, avoiding the need to deal with C tooling.
- smt88 8y agoIs that benefit worth the potential for inaccurate translation? Or is it possible to be 100% certain that the Rust functions identically to the C?
- brian_herman 8y ago#define a "xxxxxxxxxxx" #define b a a a a a a a #define c b b b b b b b #define d c c c c c c c #define e d d d d d d d #define f e e e e e e e #define g f f f f f f f #define h g g g g g g g #define i h h h h h h h #define j i i i i i i i main(){char*z=j;} This fails. The error is entity not found.
- glguy 8y agoThere are definitely ways to overwhelm the translator web demo. I know I'm not clever enough to block all of them. I put the page up to give people a way to try out the translator without having to build it. Please don't kill it :-)
- brian_herman 8y agoOh sorry
- sometimesijust 8y agoThis either does not work well OR there is no need for rust to exist. Is there a pressing need for rust code that is as unsafe as c?
- oconnor663 8y agoThe goal is to assist the human in translating C code to safe Rust code. Getting to unsafe Rust code as an automated first step saves a lot of work.
- Animats 8y agoIf you try making p a local array of length 10, ordinary Rust subscripting comes out. So the translator knows what to do with arrays; it just makes very C-ish assumptions about them. It just needs to know when a pointer is really an array to treat it as an array. This has potential. If you had some way to annotate or advise the translator, it could do a much better job, and turn out safe, usable Rust. Some of that can be done automatically by looking at calls to functions. If it's always an array going in, the formal parameter can become an array. Any C that doesn't have explicit pointer arithmetic should be translated into Rust that doesn't have explicit pointer arithmetic.
- bumblebritches5 8y agoHow about no. Fuck rust.