Hacker News new | past | comments | ask | show | jobs | submit login

As someone that writes a lot in Rust, I have a longstanding dream to make a compiler for a subset of the language, since I don’t use all features of Rust and my hope is that this way I could have fast debug builds (in terms of compilation time) while I develop, with simplified borrow checker and so on. So then I can iterate faster. That’s one of my dreams. But I have not had time to even look at it yet, as the other code I work on takes precedence at the moment.



I'd like a GC (no borrow checker) version of Rust. There's so many cool concepts in the language that I'd like to know how useful it is in different contexts. (Compiled without a VM, option types, no nulls, easy error handling without exceptions...)


I think a scripting version of rust with a GC and gradual typing would be really nice. Especially one that allows incrementally converting a script into a compiled rust program.


You could try OCaml (it does have exception but they're usually "opt in"), it's a really nice language and probably one of the closest to GC'd Rust. There's also Swift that inspired some features.


OCaml is often dropped due to its unpredictable performance


Interesting. I’ve actually seen OCaml being chosen because of its predictable performance. But that was by people coming from Haskell.


Well, almost everything has more predicable performance than Haskell. And I love Haskell.


Huh? OCaml is pretty obvious in its semantics and compilation strategy. Maybe flambda changed something, but before that I'd used the compiler source code as a reference on how one would compile an ML.


I've heard the opposite about it, that its predictable performance is one of its strength. Do you have any sources?


Darklang is being rewritten in .Net

Flowtype has horrible performance, which in my opinion partially explains why it has lost so many users to Typescript, which has much more predicable and fast performance even though it's written in JS. The project is basically dead


Here is the article about Darklang leaving OCaml, nothing here is about performance https://blog.darklang.com/leaving-ocaml/. It's about ecosystem and dev experience.

About Flow, I've never used it so I can't say, but Rescript (which is written in OCaml) compiles 10 to 100 times faster than Typescript.


I've never used neither Flow nor TypeScript, but there's an essential difference between the two - Flow is type inference engine, whereas TypeScript is a type checking engine. The latter is a fundamentally a much simpler problem (both semantically, and algorithmically) than the former. In addition, Flow picks a particularly nasty niche for type inference - OCaml itself uses type inference, it's fast (with quadratic blowup in edge cases) because OCaml's types are simple, whereas Flow IIRC tries to support both subtyping and some of JS's dynamicity, so I'm not surprised if it's slower.


None of this seems related to OCaml performance?

Darklang is being rewritten to .Net because they were unsatisfied with the OCaml ecosystem.

Horrible performance is generally more a question of algorithms and software architecture than a problem with a language, which only account for a flat percentage of performance.


I don't think I've ever heard that. Ocaml performance is surprisingly very predictable.


You might want to check out Scala Native. It’s conceptually similar to Rust without borrow checking. The only issue is that it’s way less mature and community is much smaller.


We use D a lot at work, we genuinely can only laugh at people who refuse to entertain the idea of a GC. The GC allows our code to exist without extensive memory book-keeping.

When we want to avoid the GC we know how, when we want the productivity we use the GC and fuggedaboutit


> we genuinely can only laugh at people

That's perhaps not the best wording.

Nonetheless, I do agree with you. D can be very flexible in that regard.


I don't know how else to word it. Every thread about D has people going on and on and on and on about the GC, and they aren't always wrong (there is always good information here) but fundamentally it doesn't matter. Many D programmers come from PHP rather than C++ - D isn't attractive to them because of systems programming but rather high level programming e.g. metaprogramming.


There seems to be at least one reason to have a non-GC option: You want to write code that integrates with an environment that already has its own GC and you want that to decide things. For example you want to integrate existing libraries in C/C++/D/Go/Rust/whatever with a Lisp process, since there's lots of those libraries and they do useful things, and you don't have a Lisp library for that (yet). In that case having one point of deciding when to deallocate things seems to be better than having two of them.


Using GC basically locks you into a particular memory model or framework.

Having spent 20 years mostly working in GC languages, it's totally worth it! However, writing portable libraries like SQLite or libpng are very difficult to do without bringing in unacceptable overhead for your consumers.


You just essentially described Swift


I feel much at home with Swift, and it is my other favorite language to use besides Rust. I use Rust for server-side things and command-line utilities and Swift for iOS and macOS apps. I know that server-side Swift is a thing that some people do. But I don't feel that Swift would be what I am personally looking for server-side, so I maintain my dream of faster development in Rust with a subset of Rust and a custom compiler :)

In fact I would like to be able to integrate Swift and Rust so that I could also use Rust in my iOS and macOS apps directly. But for now and for the types of applications that I am currently working on it is not worth going down that particular route. But in the future I wish to write some games where I want to write all of the game logic in Rust and use Swift + Metal for the rendering.


Swift is more like C# or Java than Rust. It's more like adapting C# to the objective C runtime than Rust.

It's also not memory safe. It's very easy to crash the process.


I just totally disagree. Swift might look a bit more like C#, but in terms of features it's way more similar to Rust for all the ADT-related features mentioned in the grandparent comment.

Also, regarding memory safety, it's not as safe as Rust - it's basically only memory-safe in the single-threaded context, but it's still relatively safe compared to other languages.

I don't really find it easier to crash than Rust - thanks to optionals you get the same guarantees against NPE's. You can choose not to take advantage of it, but you can also force-unwrap in Rust if you want.


Absolutely not. Both Swift and Rust are actively taking inspiration from each other.


Whether or not Swift succeeds at being memory-safe, in theory, it's supposed to be.


It's memory-safe in a single-threaded context. The actor model would theoretically bring multi-threaded memory safety (with a different set of tradeoffs than Rust).


Thanks for clarifying.


I don't think borrow checking plays a significant roles in most projects compiling performance. Running `cargo check` generally runs a lot faster (after the first run) than `cargo build`, even if it runs borrow checking, etc. AFAIR macro expansion, LLVM code generation and linking takes a lot of time, but it depends on the project.

In the perf site you can see some examples: https://perf.rust-lang.org/


I think you would be better served by a simplified, less optimized code generation, as from what I understand LLVM is the thing that takes a lot of time. You can see this pattern in Crystal and Swift for example, that also use LLVM and are also relatively slow to compile, compared to OCaml or Go which have their own backend.


There's a Cranelift backend, which is apparently faster at creating debug builds than LLVM: https://github.com/bjorn3/rustc_codegen_cranelift


The D compiler has Walters last compilers backend. It is very useful to have a really fast debug build. It's also potentially remarkable how slow LLVM is given that the D compilers backend is actually pretty inefficient in places yet still munches LLVM on debug builds.


Or Haskell, which also has multiple backends to choose from.


That is definitely not the case. Compiling C with LLVM is very fast.

In Swift, type inference is one thing that can be extremely slow.


That's fair, Crystal seems to also take a lot of time with type inference. However the LLVM codegen is almost constantly slower than the alternatives. For example, Haskell has a non-LLVM backend and a LLVM backend, and the LLVM backend is slower. Zig uses LLVM, and they are working on a non-LLVM backend to speed up development builds. A sibling comment mentioned that the situation is the same for D too. For C, I'm almost certain that TCC is faster than Clang with LLVM.

There seems to be a pattern here. I'm not saying that LLVM is bad, in fact if it's used by so many projects it's for a reason. But it does have a cost.




Why would someone write a bootstrapping rust compiler in C++ when you can just compile the rust to C using a proper llvm backend?


LLVM doesn't support everything. If you want to see what is not supported, the story about Python cryptography migrating from C to Rust is a good start https://lwn.net/Articles/845535/.


Bootstrapping on platforms where llvm isn't supported?


I don't see why you would want to do that as you can always ssh into a system where llvm is supported, then compile to C, copy the C sources back to your system and compile rustc using a C compiler.


How are you compiling to C? With the LLVM IR to C backend that was (is?) maintained by the Julia folks? My experience from a couple years ago was that it didn't produce output which would compile with baroque C toolchains for platforms that LLVM doesn't support... I'm giving very unsubtle side eye to you TriCore.


Well, in any case, writing a backend for rust or llvm that generates C is probably still less work than writing an entire rust compiler. Maintaining it is even orders of magnitude less work than maintaining a C++ "shadow" version of the rust compiler.


Perhaps the generated C isn't as portable (endianess, byte alignment, etc).


Any ideas on how one can simplify the borrow checker?


Use a garbage collected language instead.

Eventually as optimization point, for the few use cases where the ultimate performance is needed, provide a subset of borrow checker capabilities.

Examples of current efforts into this direction, D, Swift, Haskell, Chapel, some .NET ongoing research.


Niko Matsakis, of Rust's lang and compiler teams, has a talk[1] on how the machinery behind borrow checker is being rethought. The idea is that in the future, the compiler won't really "check borrows" but will instead "track origins."

Reframing the system in this way will (hopefully) make things be flexible enough to Just Work™ without surprises, while providing the same guarantees as the current borrow checker. The video itself has a motivating example or two that shows where this stuff would be helpful.

[1]: https://youtu.be/_agDeiWek8w


For those who don't want to sit through a video there is also the book[1].

[1]: https://rust-lang.github.io/polonius/


You could implement it as a runtime check


Why not just use GC at that point? I thought the whole USP is the zero runtime cost


It would be a garbage collector. I assumed that the person asking the question was primarily looking for a simpler implementation option, not to re-create rustc exactly.


Haven’t looked at the rust compiler code base, but often with languages you can hack together subsets via deletions and comments and flags of existing compilers.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: