I’m surprised by this being an important story while “easier integrations into existing FFI solutions” is not. I expect calling into Rust code to be very important in a short run. Rust has a high chance of being used for things C is a classic for: one of them being shared libraries. Considering that ARM support is a another story listed here, if you think about mobile devices, smooth calling into Rust seems very important for me. Something with a similar statement - calling into simple Rust traits - might be very interesting here.
It’s not the same as having an ABI, emitting symbols in a certain format for the C-ABI should be enough.
Borrow checker improvements - this is one of the key selling points of Rust, (memory safety), therefore we should make sure that it works correctly in most situations, including ifs.
Faster compilation times - Besides being memory unsafe, one of the biggest drawbacks of C++ is compilation times, (in fact that’s at least half of the reason why a whole new language (Go) was invented), improving this would definitely be another major selling point on Rust’s “specsheet”.
Why would this be a useful goal? There’s the philosophical matter of GCC being an Open Source toolchain, which I appreciate some may not care for, but pragmatically the MinGW-w64 toolchain brings C runtime compatibility that MSVC doesn’t. What benefits are you looking to achieve here?
I would love to see keyword arguments for functions sooner rather than later, as it will dramatically change the way some APIs are designed. Using the builder pattern is a workaround for now, but it adds a lot of boilerplate for no real benefit.
Shortly, I would like to link with MSVC binaries.
More broadly, there is more than one C++ compiler in the world, different compilers have different advantages, it is not great to depend on one solution, especially when it is not the default one on the platform.
That’s not what I meant. You can define a new type which does what your anonymous closure does (and holds any neccessary state). For instance iter.map(|n| n + x) becomes http://is.gd/xrXbon . Due to inlining this a zero-overhead workaround for lack of impl Trait. This is how all the std iter adapters are implemented.
Also in cases with no state, like your |x| x, example, you can also use fn(T) -> T as the function type i.e. type Identity<I: Iterator> = iter::Map<I, fn(I::Item) -> I::Item>
To be honest, I really meant that as a placeholder for “improved FFI story” in many dimensions, one of which is calling out, but I agree that calling is equally important. I’m curious, what precisely are you looking for? We do have the ability to define Rust fns that use the C abi and so forth. (Best would probably be to open an RFC issue describing what it is you would like to do.)
You’re right, you can simply create your own struct and implement Iterator on it (but let me say that this is very very verbose and inconvenient – e.g. nobody would use closures if you’d need to jump through hoops and create a custom struct each time you want to pass a closure).
The other example with “no state” isn’t the same, fn(T) -> T has a performance impact as it is a function pointer which isn’t necessarily optimized away by the optimizer.
I’d add “support for the C preprocessor when writing C wrappers” to the list.
You touched the most important ones for me (integers at the type level, variadics, HKTs, memory allocators, …).
About await/yield/async: there is a current theme in C++ about “avoiding future islands”. I really like the latests Kohlhoff proposal “Resumable expressions” which unifies stackless and stackfull coroutines and allows things like implementing constexpr stack allocated futures: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4453.pdf
I completely agree, it’s a pain and I was hoping for it to be higher priority too—though I sympathize with all the arguments given by other people. I only meant to point out that in the meantime, when perf matters, you can avoid boxing it; I end up doing that a lot in my code.
Re: First I also don’t like over relying on an optmizing compiler—I want my perf to be predictable.
But for the sake of the conversation for an fn pointer, if it’s in the same crate, LLVM seems to do a decent job: http://is.gd/hthlFG . Check out the LLVM IR, it gets expanded directly into 11, 12, 13, 14, inline-ing through the fn ptr.
If you make the iterator returning function inline/generic (which it probably should be), then it should work cross crate too. contain-rs relies on this a lot.
To me, a stable way of doing async I/O would be very important. Right now, there doesn’t seem to be any good way to select() from multiple Readers in an event-driven way. Also, I’m wondering what happened to the Deadlines design that was brought up during std::io redesign. Currently, not being able to cleany stop listing on or reading from e.g. a socket is a complete deal-breaker when writing server applications.
I’d like to see some more minor features with already-accepted RFCs to be implemented; in particular, the box operator and the new array patterns would be nice to have soon after 1.0.
Non-lexical lifetimes and impl Trait are also pretty important in my opinion for newcomers to the language. A lot of lifetime problems that people learning Rust have are because of lexical lifetimes, and I’ve seen quite a few questions on Reddit and IRC about how to return closures. Also, being forced to use trait objects is really not cool, whereas impl Trait gives you the choice to use a trait object but doesn’t force you. Returning closures is definitely one of the messiest parts of the language at the moment in my opinion.
On the other hand, I think that HKT should probably not be prioritised very much. It’s a large expansion of the Rust type system that I personally haven’t needed very often.
Oddly enough, Rust already has HKTs. * → * is basically just a trait with a type parameter and an associated type. You just have to coach the type system through the relationships involved and tell it that the HKT can be applied to a given type on a case-by-case basis, which makes it hackish and inconvenient, and thus probably shouldn’t be used in real code. Fixing that last problem just means being able to write T : for<U> Trait<U>. The rest could probably be handled by rewrite rules. It would still be non-trivial to specify it, though, and it might be better to design it as a completely separate feature rather than as sugar.
I suggest spending some time writing a spec – grammar, type system, static and dynamic semantics – and an accompanying conformance testsuite that checks the assumptions in the spec. And then correcting the inevitable set of underspecified, surprising, backwards or incoherent aspects of the language discovered along the way.
That and compiler performance / general compiler technical-debt repayment. Including dynamic drop. And exposing a stable syntax-extension interface: lean on token trees as much as possible, with an interface for building opaque AST-nodes and AST-matchers in TT-patterns. Don’t try to stabilize the AST representations themselves. Spliced ASTs are not multi-stage typesafe anyways, so even if they “fit together” at the AST level, they won’t necessarily parse or typecheck any more reliably than if they were built from token trees.
Personally I wouldn’t add any new language-language features for … a few years at this point. It’s got plenty.
(Sorry of saying so is too intrusive; I know this isn’t my project anymore, but you’re asking for observer-input)