Edited to clarify that this discuss thread is the proper place to, well, discuss.
I’d like to ask that tail call optimization (rust-lang/rfcs#81) be considered for mid-priority. It’s not exactly time sensitive but I think it has the potential to have a large impact on how rust code is written.
Just a random idea, but it would be nice to have precompiled versions of Rust for ARM, Android, and others.
This would not only make it easier to get started, but also allow continuous integration on travis or other services for Rust libraries and programs that target these platforms.
I think I won’t necessarily write any code using HKP, but I’m using libraries that want it. I also think the standard library might benefit from implementing some higher kinded traits so that it’s easier to generalize over common features of the standard library types. Same for generic integers.
-> impl Trait will be something I will use in my own code, though.
impl Trait should have higher priority. Being able to hide implementation details w/o having to pay the boxing tax is something I’m really looking forward to.
I agree. There are a couple of questions about this from newcomers on reddit every week. Some limited form, restricted to return types at least would be very welcome.
You can already hide implementation details without paying the boxing tax. Look at
impl Trait syntax is mostly a convenience that saves you from creating a struct. I don’t think that’s a priority as there are other things that simply can’t be done with Rust today.
I would much rather have compilation performance and dynamic drop (which could improve compilation performance) than any language features (especially
impl Trait, implementation specialization, type-level numerics, HKT, etc.). In fact, I’d be quite happy for no new language features to be added for at least several months, because compilation performance is so important.
Laying the groundwork for incremental rebuilds, in particular, would be really awesome.
One of the most requested things in rust (at least that I have seen) is a standardized formatter. Coming from an eco system at my job where go is taking over, a large amount of the success is due to go fmt, go test, and the various go linters.
I think you really should - as a high priority - solve this part of the tooling asap.
I basically agree, and this is roughly the plan, but I also want to get started on planning language changes now, as those have a long ramp-up time in the design phase. (And the more time there is for designs to bake, the better.)
+1 - From my (very small) sample, the biggest barrier to contributing compiler improvements is build time. Bringing that down will make it easier to implement every other feature on this list.
Beyond parameterizing with integrals, parameterizing with values in general would be great.
For example, in C++ the absence of parameterizing with strings has been a long-standing issue, and there are crazy meta-template programming work-arounds based on spelling stuff character by character, leading to:
constant_string<'H', 'e', 'l', 'l', 'o'>::cat< constant_string<' ', 'w', 'o', 'r', 'l', 'd'> >::type
The huge push for
constexpr in C++11, and the various extensions brought by C++14 and C++17 clearly show the interest of programmers for more compile-time computation; mainly for two reasons:
- Free Performance: a constexpr
Regex::newwould have the performance of
regex!(without the hassle);
build.rssomewhat fulfills part of this gap, but
regex!exists because it is much more readable than defining all your Regexes in a file and referencing them throughout the project.
- Better Types: it has been brought on already that the branching factor of
BTreewas not configurable until integral parameterization existed; beyond that, though, it would be valuable to parameterize a “pin-handler” by the address/width/mode of its pin (0/1/2/3 is not as readable, so enums?). I believe today it can be somewhat approximated by using a dedicated type providing the necessary constants by implementing a dedicated trait. For single-value arguments, it’s quite heavy-handed.
Beyond C++, in Scala they actually went all the way down with something like Rust procedural macros… hard to detect whether you should rebuild or not when that depends on the content of a database though.
However, I must admit that in terms of implementation, it seems like a really tricky thing to do.
Specifically, the C++ way (constexpr) has led to specific “evaluation code” popping in compilers to allow evaluation of an ever-increasing range of expressions. It seems hardly tenable to be honest, it means implementing features twice (one for constexpr and one for IR) yet guaranteeing that both results match. It also seems quite difficult to “go down”: what of low-level code such as calls into C, arbitrary memory manipulations, syscalls and inline assembly? Some of those are the building bricks of most collections (starting with
Vec), and therefore most code remains inaccessible to this.
The other strategy could be quite similar to plugins: just compile and execute. LLVM can JIT code, the lowering to IR has to be implemented anyway, and since the compiler knows the in-memory representation of the result type, it should be able to “convert back” the raw memory of the result to an “AST value”. It solves all calls into C/memory/assembly issues, providing you can execute the code.
Unfortunately, executing the code gets hard in the case of cross-compilation. The result of
std::mem::size_of for example depends on the triplet; it means that you would need to JIT for the target’s triplet, and execute it on the target… which is quite at odds with cross-compiling.
Beyond, there is the issue of deciding whether function should be explicitly annotated (better backward compatibility, but annoying when authors forget, leading to re-implementations) or implicitly guessed (easy re-use, but potential backward compatibility trap).
Agreed, compilation speed definitely is one of the biggest problems in any non-hello-world project. Lang/lib problems can have a workaround and even if it is dirty - you’re doing it once and it’s hidden for a while. But slow compilation is always there, every single day.
cargo install would cause people to start uploading Rust applications to crates.io, then it would have the happy coincidence of expanding our automatic regression test suite of community code. Though it’s possible that application authors won’t care about being on the stable channel as much as library authors will.
I concur that compiler speed should be very high priority, but I don’t think that necessarily precludes feature development. Allow me to vote for issues that should be considered for high priority:
- Borrow checker improvements. First impressions matter, and “the borrow checker is too strict” is a meme with sticking power.
try. Feedback for this type of sugar seems almost universally positive, and the longer we put it off the more code that will exist using outdated error-handling idioms. Furthermore, adding
?to the grammar has the capability to break macros in the wild.
impl Trait. Of all the features that Rust “lacks” (e.g. placement new), this is the only one that really sticks out as feeling “half-implemented”. Even if we want to hold off on the implementation for a while, we should work towards accepting a preliminary design as soon as possible.
Maybe for the Rust compiler. Compilation times of under a minute don’t hurt as much as bad performance caused by not being able to return an
Following @bstrie’s example, my humble vote, ordered by importance to me:
- Borrow checker improvements. I am constantly burned by borrows in the if-condition lasting the entire if-scope. Although the workaround is simple, I agree that this would help first impressions and reduce frustration.
- Generic integer parameters. So I can serialize
[T; N]. And to see all those hard-coded trait impls in std go away.
- Virtual structs. I go back and forth on this, though, because I have found a few interesting ways to achieve pretty ergonomic single-inheritance using generic structs and traits.
- DST by value. Because I think it’s nifty
I’ve rebased eddyb’s const fn branch. I need to get that PR up. And I have to rebase again. I plan to take over quantheory’s associated constants branch as well.
Community feedback is very important but we also should remember what Ford said: “If I had asked people what they wanted, they would have said faster horses.”
Some things on the list above I wish will not happen even though they get a lot of community support such as the ? operator. This is just hard coding a specific pattern by popular demand in lieu of a more general and more orthogonal design that would be possible if for example we get HKTs (already on the list!) and get something similar to Haskell’s do notation in the future.
I also agree that it is better to improve the tooling as first priority and allow for such more general designs more time to mature.