
Announcing Rust 1.19 - steveklabnik
https://blog.rust-lang.org/2017/07/20/Rust-1.19.html
======
Cieplak
Great running into you at Shizen @steveklabnik!

Just started using Rust in a serious capacity this month to secure some C++
functions that are called by our Erlang apps, with great assistance from
Rustler [1]. Several people have complained to me about the decision to remove
async IO from Rust, but I'm really grateful that it happened, because it lets
Rust focus on being the best at what it is. Erlang's concurrency primitives
and Rust's performance & security are a match made in heaven.

[1] [https://github.com/hansihe/rustler](https://github.com/hansihe/rustler)

~~~
steveklabnik
Hey hey! You too. Sorry I had to skip town before we could grab a drink, it
was a hectic trip!

> the decision to remove async IO from Rust

I'd be interested in hearing more about this, did they maybe mean green
threads? [https://tokio.rs/](https://tokio.rs/) is the big async-io project,
it's certainly not removed in any sense!

~~~
Cieplak
I should clarify the "remove async IO" as the decision to not include an
event-loop primitive in the core language or stdlib, which is tantamount to
complaining about GC not being part of Rust core :)

Metal IO is an awesome library as well:

[https://github.com/carllerche/mio](https://github.com/carllerche/mio)

~~~
steveklabnik
Ah yes, I forgot that we had libuv at some point, duh! Thanks :)

------
JoshTriplett
Incredibly excited to see unions available in stable Rust now!

The release notes mention my RFC, but a huge thanks also to Vadim Petrochenkov
for the implementation, and all the myriad RFC contributors.

~~~
GolDDranks
Now that unions have stabilised, is there any significant un-expressable
things in C APIs left? Bitfields?

~~~
JoshTriplett
Yes, to the best of my knowledge, bitfields are the last thing in C APIs you
can't express conveniently in Rust; you can handle them with careful macros,
but that's annoying, just as it was for unions.

In terms of things you _can_ express now but that could still use some work:
anonymous structs and unions. You currently still have to name all the
intermediate aggregates, even when the C API doesn't. See
[https://internals.rust-lang.org/t/pre-rfc-anonymous-
struct-a...](https://internals.rust-lang.org/t/pre-rfc-anonymous-struct-and-
union-types/3894) .

~~~
digikata
The tough thing about bitfields in C are their poor portability as they can
get laid out differently in memory by platform and compiler. They're often
avoided even in C when you're looking for a good degree of interoperation
(e.g. structs used in networking or on-disk-formats, etc.).

~~~
JoshTriplett
Right. And we can't just say "we need bitfields", we need 100% C-compatible
bitfields, for FFI.

~~~
adrianratnapala
But not very important for FFI, since bitfields rarely seem to show up in C
APIs (presumably for exactly the reasons mentioned above).

A kind of similar issue appears even with enums, because it is hard to guess
the size of the integer that a given enum is implemented with. This is why it
some not to use C enums in public interfaces to libraries.

~~~
Manishearth
Gecko (and many other large C++ programs that care about memory usage of
certain heap allocated types) uses bitfields often enough, and we've had to
teach bindgen how to generate bitfields so that we can access them from Rust.

~~~
adrianratnapala
Were these intended as part of an external interface for Gecko? In which case
I would say using bitfields (as opposed to explicit masks) was a mistake.

But yes, I can imagine that for Mozilla there is a need to mix Rust and C++
right inside an application at boundaries that are not usually considered
external, in which case all kinds of non-portable C constructs are acceptable.

------
static_noise
One thing that recently surprised me is that Rust lacks default values and
named arguments for functions.

Some consider it a counterpattern or bad memory to be able to not fill out all
parameters or reference them by name. However some interfaces easily require
like 50 different function parameters that cannot be removed in a simple way
and they all make sense in different configurations. Without default values
and named parameters you're lost there. I don't get this design decision on
Rust side at all.

~~~
kibwen
Coming from Python I agree that the lack of keyword/default arguments is
initially conspicuous, though in practice it seems that library authors seem
content to implement builder patterns to work around their absence. While
ideally I do think that the builder pattern is less elegant than supporting
keyword arguments, in practice it does avoid the unfortunate pattern I've seen
in some Python APIs to just cry #yolo and cram a hundred parameters into a
single function call. I've _never_ seen a good interface that requires "like
50 different function parameters"; call me zealous, but if I were to design my
own programming language, I'd make it a hard compiler error to have more than
four parameters to a function. :P

~~~
static_noise
While you can misuse a feature, you don't have to. My example is extreme and
you probably don't run into something like that often depending on what you
do. There could be other solutions. There surely are other solutions that are
neither more clear nor better in any way. Sometimes you just got to do what
you got to do. What surprised me about Rust is that it has all those cool
features but lacks a very basic one that most programming languages have.

~~~
steveklabnik
> a very basic one

With my language-nerd hat on...

While they may _seem_ basic as a user, designing a language means you need to
think about edge-cases. Methods in Rust have some special rules around
dispatch, and in order to implement one or both of these features, all of that
stuff needs to be considered and designed.

In other words, a _lot_ of work goes into new features, even ones that are
easy to use.

In Rust's case, we haven't ruled out adding these features completely, but
nobody has put in that work to come up with a proposal. Part of that is that
while people tend to see the lack of these features as a mild annoyance, it's
not enough to prioritize over other work. We'll see how it all shakes out.

~~~
tatterdemalion
Want to echo this part:

> nobody has put in that work to come up with a proposal.

Features like this mainly need a champion who really cares about getting it
into the language & can work with the language & compiler teams to complete
that process.

------
jmull
Hm. I'm not sure about the addition of unions. Why add something that is
unsafe to read or write? You need an additional mechanism to let you know
which type it is OK to access.

They mention the case where the type can be distinguished by the lest
significant bit, but wouldn't it be better to handle that case as an enum?
That is, the least significant bits define the enum tag, while the remaining
bits define the associated value.

(By the way, I really mean this as a straight question, _not_ a criticism in
the form of a rhetorical question. I really don't know enough about it to be
criticizing it.)

~~~
kibwen
As other commenters have mentioned, the demand here is almost all due to the
desire for smoother interoperation with C code. What's gone unsaid so far is
that, despite still requiring the `unsafe` keyword for many operations, this
feature helps make Rust code _more_ safe when calling into C, because it
simplifies the interface and eliminates the need for hacked-up handwritten
workarounds. IOW, a little bit of standardized unsafety to replace a larger
amount of bespoke unsafety.

~~~
Manishearth
FWIW the hacked up workaround that bindgen uses is _beautiful_

[https://github.com/servo/rust-
bindgen/blob/master/tests/expe...](https://github.com/servo/rust-
bindgen/blob/master/tests/expectations/tests/union_fields.rs)

Basically, if you have a union of A, B, C, you create a struct with three
zero-sized fields using BindgenUnionField<A>, and then add a field after that
containing enough bits to actually fill out the size. Because the
BindgenUnionField is zero sized, a pointer to it is a pointer to the beginning
of the struct, and it has an accessor that treats the pointer as the contained
type.

This makes the API for field access `union.field.as_ref()` instead of
`union.field`, but that's still pretty clean.

It's still a hack, and I'll be happy to see it go, but it's a really fun hack.

~~~
kibwen
If only English already had a word for "beautiful, yet reprehensible". :)

~~~
tomsthumb
You know this word in another language?

~~~
andrewflnr
There must be one in German. :)

~~~
euyyn
Probably just the concatenation, like beautifulyetreprehensible.

------
ofek
Wow, a break yielding a value from within a loop is awesome! Do any other
langs have that?

~~~
joshmarlow
If you're using the loop macro, you can do it from Common Lisp (see [0]).

    
    
      (block outer
        (loop for i from 0 return 100) ; 100 returned from LOOP
        (print "This will print")
        200) ==> 200
    
      (block outer
        (loop for i from 0 do (return-from outer 100)) ; 100 returned from BLOCK
        (print "This won't print")
        200) ==> 100
    

[0] - [http://www.gigamonkeys.com/book/loop-for-black-
belts.html](http://www.gigamonkeys.com/book/loop-for-black-belts.html)

EDIT: I always do formatting wrong on here.

~~~
pdw
Not just with LOOP, RETURN works with every standard iteration construct.

