What's new in Rust 1.38Back to Episode Page
Ben Striegel: Welcome once again, ladies and gentlemen, to Rustacean Station. I am Ben Striegel.
Jon Gjengset: And I am Jon Gjengset, and we are excited to tell you about the 1.38 release of Rust.
Ben: It’s been a while. Don’t need to rush right into it. I don’t think this is going to be a super long episode this time.
Jon: Are you saying 1.38 is not as exciting as 1.39 will be?
Ben: No, no no no. They’re all exciting. They’re all— every Rust release is precious in its own way.
Jon: Are they all equally exciting?
Ben: Not really. I don’t know, I guess, But still, there’s, like, it shouldn’t be a—
Ben: A big momentous thing. We don’t want to try to, like, rank our children here.
Jon: That’s true. I mean, it is, like we discussed a little bit last episode, it is also— this is one of the nice things about the Rust release cycle, is that you can have releases that are really exciting, and some that are smaller ones. But at least you’re always making progress.
Ben: I think in this one, the biggest, the most exciting feature for most folks is going to be, like, potential compilation time improvements, for projects with large crate graphs. They’re calling this one “pipelined compilation,” and it is a new feature. It is on by default, I believe. So if you’re using the newest stable release, you should be using it already. Do you want to go into what this means, Jon, or what you know about this?
Jon: Yeah, so this is pretty cool. I mean, this is a complaint that we hear a lot in the Rust world, of the compiler takes forever to compile my thing. And one way to at least help with this problem is to compile more things in parallel. Now previously, the Rust compiler would, or Cargo would compile each crate sort of separately. So if you had some crate C that depends on both A and B, it would fully compile A than fully compile— or fully compile A and B, and then it would fully compile C. But it’s not— it turns out that’s not really necessary. Instead, you can compile the metadata for A and B, and then you can compile C straightaway after, in parallel with compiling the sort of contents of A and B.
Ben: But what is metadata? You can’t just gloss over that.
Jon: So metadata is stuff like figuring out the types, figuring out what the functions are without necessarily compiling the body of them, like, without running things like optimizations.
Ben: So kind of like header files, almost.
Jon: Almost sort of like header files, yeah. All you really need is, you need to know all of the external parts of the crate, because those are the things that the other crates are going to use. And then, you only really need the final optimized compiled artifacts at the end, when you need to link them together.
Ben: Yeah, so previously, any Rust crate is its own compilation unit, and anything that depends on it has to wait for it to be done before it can start. But I mean, again, like, you don’t need to know everything about a compiled crate to actually begin compiling. And so this, kind of, just lets us kind of shortcut the process.
Jon: Yeah, you can think of this as, you don’t need the assembly code for all of the crates you’re depending on, in order to compile your crate. Because much of it will be function calls into some part of the code that is external to the current crate. And then this is where link time optimization comes in. Where at link time, you can then try to do optimization across crate boundaries.
The other thing, that’s a little neat, as we talked about back in 1.36, the “mem
uninit” type landed. (editor’s note: should be
And this was to try to deal with some issues around
incorrect use of
Ben: And if you haven’t listened to our episode on that, feel free to do that right now, our very first episode.
Jon: It’s okay, we’ll wait.
Ben: We’ll wait. It’s about an hour long.
All right, you’ve listened to it now, and now you’re back. So thanks.
Jon: Yeah, exactly. Good job. I’m impressed. By the listener. Not you, Ben.
Ben: Yeah, I’m not impressive.
Jon: Well, sometimes.
Ben: Go on. So, “mem uninit”.
Jon: Yeah. So it turns out that
uninitialized is broken, and it’s very
easy to do things that are incorrect with
Ben: In fact, it’s almost— it’s hard to do things that aren’t incorrect. Which is even worse.
Jon: And part of the reason for this is, for any given Rust type, there may
be bit patterns that are not permitted. The simplest of these is for— if you
have a reference type in Rust, then references in Rust are not allowed to be
null. So that is, their bits are not allowed to be all zeros. So if you have a
type that contains a reference and you use
mem::uninitialized to create it,
then that creates something that might have a reference whose bits are all zero,
which is undefined behavior in Rust and so is not okay. Similarly, if you have a
boolean whose bit value is not 0 or 1, that is also not okay, and might cause
undefined behavior. And so what’s happened with the 1.38 release is that now,
the compiler will tell you if you try to use
mem::uninitialized to create one
of these types. Even deep down in nested structs. The same is the case for a
Box, right, so a
Box has to be a non-null pointer. So if you have
a type that contains a
Box, and you try to create it with
mem::uninitialized, the compiler will now warn you that this is not okay, and
is undefined behavior.
Ben: So it is kind of on the path to actual deprecation,
Not just yet, because it’s kind of a case where you want to give people time to
actually update their code. And so in this kind of interim period, people should
begin migrating to
MaybeUninit, which is the new replacement for it. But in
the meantime, you can still be using this, cause it’s not like it’s impossible
to use correctly,
mem::uninitialized. But it is just highly likely. And so
this new lint is, kind of, things that obviously wrong. We can’t lint against
everything that could be, like, potentially wrong. Obviously, if we could, we
could just not have this be unsafe at all, in the slightest. There’s not really
any timeline for deprecation for this right now. So I think it’s just kind of
like, seeing how quickly people update their code, and that kind of thing. So,
but look forward to that being actually fully deprecated at some point in the
Jon: And speaking of deprecation, there’s also a new use of the deprecation macro attribute that just landed. Do you want to talk a little bit about that?
Ben: Yeah, sure. So Rust, actually, if you’ve ever, for example, like, I
mentioned deprecation, the way that the standard library deprecates things is
actually quite simple. You just put an attribute on the function. And so if
you’ve ever used, like,
derive, that’s an attribute, you just, like, plop it
on there. And now you have things happening for free. The
on functions, essentially, all it does is, any time anyone uses this function in
their code, the compiler will say, hey, like, by the way, this function is
deprecated. And as the author of the function, you can also attach, like, notes
saying, hey, look, here’s why it’s deprecated, here’s what you should use
instead, you can say this has been deprecated since this release so-and-so. And
a long time ago, this became not just a feature of the Rust developers, but also
anyone can use this in their own libraries, too. But previously it was
restricted to things that weren’t macros, and now it works on macros as well. So
kind of, more steps towards making macros, kind of, feel less like their own
kind of like, cloistered off part of the language. More like first class, say,
or more integrated with the rest of how Rust normally works. So less special
I wanted to also real quick, kind of, mention, you can’t, like, if you were
curious to know more about the
deprecated macro, you can’t just go to, like,
the Rust API docs and, like, search for
deprecated, say, it is— as kind of
built-in compiler attribute, you actually have to go to the Rust reference,
which is, if you look in the reference under the— where did I have that here
somewhere? Well, I’ve lost it, but it was the diagnostics category under the
attributes section. If you look under there, you can see information. Also, if
you want to know about any of the other built-in macros in Rust like
say, you should also check the reference for that kind of thing. It would be
nice if this showed up in the API docs, because built-in attributes are kind of
indistinguishable from a procedural macro, or like another thing that you might
expect to be in API documentation, and I think you were saying how even if you
your own procedural macros nowadays, they won’t show up in the API docs.
Jon: Yeah, So this gets into the different types of procedural macros there
are. So there are procedural macros that generate function-like macros. These
are the same things you get if you used the
macro_rules!, the, like,
declarative macros from before.
Ben: Like a
Jon: Yeah. So,
format!, all of these are—
Ben: Name, then bang. And then some arguments inside parentheses and then, just like, you know, it looks like a normal, like, you know, syntax macro.
Jon: Yeah. Exactly.
Ben: The procedural, full blown shebang.
Jon: Yeah, and all of these function-like macros are already generated by
rustdoc, and they’re listed normally in the documentation. But things like
derived macros, and other kinds of attribute macros, such as— or attributes at
all. Such as
deprecated here, those, even though I don’t know whether that’s
implemented as a macro internally in the compiler, but it is an attribute that
you can use, and those I don’t think are generated in the docs at all. And
that’s also why they don’t show up in the documentation for the standard
Ben: So that would be very nice to have, just for user convenience. Did I cut you off before? Did you want to say—
Jon: No. I just wanted to say that this feels a bit to me like, similar change to being able to name macros in use statements, of just making macros feel more like first class citizens, alongside other things like types and traits and functions.
The other thing I wanted to mention briefly, when we talk about deprecation, is
that I’ve seen a number of crates use
#![deny(warnings)] to make sure that,
well, to essentially turn every warning into an error. This is a common pattern
in other languages as well, where you use
-Wall -Werror in C, for example. And
in Rust, you have to be a little bit careful about doing this, because it means
that even warnings about using deprecated methods also turn into hard errors.
And this means that a semantic versioning compatible bump of a dependency might
cause your crate to start issue warnings, which then become hard errors.
Ben: If you have this deny—
Ben: You have all warnings denied.
Ben: I think even the Rust team themselves, like for the purpose of like, Crater runs— and so Crater is a tool that just checks new versions of the compiler against all the crates on crates.io to see if there are any, like, problems, and it actually ignores the deny warnings lint because of this, and so it’s kind of like, you could just, if you want, enable this. It’s not a big deal, like, deprecation is just a thing.
Jon: And it’s because it means that semantically, semver-compatible updates of dependencies might now break your build, even though the update was, in fact, completely semver-compatible.
There’s another thing that landed in 1.38 which is this
So this is primarily used in debug context. So the idea here is that it’s
generic over some type
T just like the
size_of function, for example, and it
just gives you a string that describes the type you’re talking about. If you run
type_name, generic over
bool, then you’ll get back a string that just says
"bool". And the idea is, you can use this to print out your types, if you
don’t necessarily care about all the stuff that’s inside them. Or if you want to
print out a type that is not
Debug, than you can at least print its name. This
is also handy for macro authors. Like we talked about last episodes, there are a
couple of these kind of changes that we’re seeing in the language that might not
make a lot of sense for people who aren’t writing macros. But if you are writing
macros, then being able to just easily get at the name of a type is pretty
handy. This also has the flavor of something we talked about a little bit in the
past, and something that happened in the 1.34 release, which was this
Ben: Which predates our podcast. But I think we mentioned it in passing, where in Rust 1.34 we stabilized— we as in everyone.
Jon: Ben and I.
Ben: Jon and I, actually yes, we decided in our wisdom to stabilize the
type_id field, method, or— on the
Error type, actually.
Jon: Yeah, it was a combination of a trait and a downcast method.
Ben: Yeah. So it was a function defined on the
Error type in the standard
type_id. And the idea was that this would give you kind of a
unique identifier for whatever type was contained within. And there was a
problem— it was actually a security advisory— about this. On the security
Jon: Yeah. The problem there was really that the compiler— or, the code
generated by Rust or the safety guarantees, relied on a type faithfully giving
TypeId that the compiler had assigned to that type. But because
was a trait you could override, you could override it and just give some random,
TypeId. And now you could
downcast basically any type to any other
Ben: Which is bad.
Jon: Yeah. It turns out that—
Ben: Bad for memory safety.
Jon: Yeah, it turns out that that is actually a bad idea. Believe it or not.
Ben: Yeah. And so, actually, that’s one of the examples of something that was de-stabilized. I’m looking here at the time line for the security advisory here, where I think about a month after it had been released. It was actually, like, taken out of language entirely in a point release, saying, actually, there’s no way we can make this safe, because of the combination of these few features here. If you were to do this, it would cause instability. And so while it’s very unlikely that anybody actually did this, you just can’t have that kind of hole lying around. So yeah, a case where deprecation was not considered and there’s no, like, light touch. It was no, this has to go immediately. There’s just no way this can be safe.
Jon: Yeah, we don’t have too many of these in Rust land, where we decide something has to go away.
Ben: Even like the “mem uninit” we mentioned before. Like, even though like,
it’s almost— it’s considered in some cases, almost impossible to use correctly,
if you use it on any kind of generic type. That wasn’t even like, you know, hard
removed, even that we could remove it at any point. But now that we have the
type_id was just like, nope, it’s gotta go.
Jon: The only other one I can really think of is, I remember in the early
days, there was a
thread::scoped in Rust. You could pass it a closure to run—
Ben: Before 1.0? Was this the—
Jon: Yeah, I think it was nightly only for— I forget exactly.
Ben: There was one case where we had a thing stabilized for one day. And then Huon Wilson was like, hey, I was reading the release notes. And actually, you have the wrong type signature for this thing. And so we to actually, like, the day after. Someone had just forgotten it was an unsafe API, and somebody had meant to write a mutable reference when they wrote a shared reference or something. It was like, oops!
thread::scoped went away entirely, because there wasn’t—
Ben: I think this was before 1.0, though, which changes the thing entirely.
Jon: Yeah, I think you’re right.
Ben: Before 1.0 was a primordial time. Things changed quickly.
Jon: A giant primordial soup.
Ben: Yeah. Those are all the meaningful language changes this time around. Or, I guess there was actually was a library change. But we have more library changes, so—
Jon: Yes, we have some smaller ones. So one of them is— and some of you may
know about this method from before, but if you have a slice, or anything that
derefs to a slice, then you can join them with some separators. So the idea here
is— the example that comes most often to mind is, you have a string or you have
a slice of strings and you want to join them by some separator. So this is
usually something like a comma. You want a list to be comma separated as a
single string, and you can do the same thing for a slice. You have a slice of
u8s and you want to join those many slices of
u8s by some separator, and
previously you could only join them by a single separator, so a single
Whereas now, with this new change, you can join by something that is a slice
itself, so you might join by something like
0, 1, 2.
Ben: Yeah, I think if you think about it in terms of like, we’re familiar
join method on things where it’s like, you know, we just have a list
of numbers. You want to join it by a comma, and make a string out of them or
something. It doesn’t make a lot of sense, you think to yourself, well, why
wouldn’t I just, like, put, you know, the other things inside of the string that
I want to join by. Well, if you have, like a number and you have— I want this
list of numbers to be separated by, like, you know, 100 zeros or 100 fives or
whatever, it’s like, that isn’t a valid
u8, obviously. So you couldn’t just do
that. And now you can have any arbitrary thing inside, to separate your various
Jon: And there you also see that we have this
Ben: Yeah, again, we get back in the deprecation thing around, like, early
days of Rust, we stabilized a
connect function, which— and then people were
like, actually, every other language calls this
join, just to be, like,
familiar with everyone else, we should just call it
join. And so that was
deprecated. It’s still around. It was again, still being supported, it has this
new support as well. But nowadays you should be calling the
It’s just not a big deal to remove from the language, because it is deprecated,
and it will give a warning if you try to use it.
Jon: And if you don’t call
join you’re a dummy.
Ben: No, no, everyone who wants to use the thing. It’s fine, you know, it’s different strokes for different folks.
Jon: That’s true. That’s true. There’s another change that might seem a
little weird at first glance, and that is that raw pointers will now implement
Unpin for any
Ben: I think
Pin is kind of a complex subject. Is there a way that you
could summarize briefly what this means?
Jon: So last time I tried to summarize
Unpin, it ended up being
a three hour long video. But I will try my best. So the idea with the
Unpin types is that if you surround a type in
Pin, it means that you are
promising that you will never move that type again. So once you place it behind
Pin, that thing will never move in memory.
Ben: That location in memory forever.
Jon: Yes, until it gets dropped. And
Unpin means, I don’t care about that
contract. So if you put a type
T inside of a
Pin, you can’t get that
Pin again unless that
Unpin. And most types in Rust are
u8 doesn’t care whether you—
Ben: Most types don’t care if they—
Jon: And the few types that do are generally things like self-referential
structs, which you normally can’t write in Rust. But they can be constructed for
you, if you use things like
Ben: And the reason this exists is for, things that most matter, are— you
mentioned these self-referential structs, which includes generators, which are
being generated by the upcoming async/await syntax, which is kind of like— the
precursor to this was, well, we need a way for these generators to actually
contain references to themselves somehow, and so that’s what this is for. Most
users don’t care about
Pin. I think they probably shouldn’t. It’s more a
library implementer kind of thing. And in this case, we’re just adding it to
these raw pointers here. I guess the reasoning was, why not? Do you know the
Jon: Yeah. So the reasoning here is that most types should be
some types are not
Unpin, like we talked about. Some things are
interesting reasons, like a
Unpin even if
T is not
the reason for this is, if you move a
T behind that
Box does not
move. And so therefore, you can move that
Box freely, and the type
still stay in the same place. And the argument here is, the same thing applies
to raw pointers. If you move the pointer, that doesn’t move the
therefore the pointers should be
Unpin even if the
T is not
Ben: And was it just an abundance of caution that caused these to not be
originally marked as
Jon: I think that’s the case. That originally, it was like, well, who knows about raw pointers, really? They’re all sorts of complicated. And then the realization was, they should be fine because they’re just like heap pointers.
Jon: There’s also a really exciting new change that only matters perhaps for a small group of people.
Jon: Yeah. So if you have a
Duration, you can now call
as_secs_f64, which gives you a floating point number for the number of seconds
of that duration. And this is really handy if you want to do things like, just
print out how long something took, maybe in seconds, maybe in some other unit,
but you want to print it out with decimal places. Previously, you had a way to
get the number of seconds and the number of nanoseconds, and in some cases, like
the number of millis and and micros landed recently. But now you can just get a
single number, which is an
f32 or an
f64, which is the seconds, and the
decimals. And this is handy for printing out, especially if you’re doing
benchmarks and you want to do things like compute throughput. That’s a lot
easier now, because you can get the time taken as an
Ben: It’s kind of more convenience methods being added pretty quickly to
Duration type. Which was kind of just like, bare bones for quite a while.
Ben: So, pretty nice. Nice little ergonomic change.
Jon: Speaking of ergonomic changes, we have some interesting things coming
up in the next— or, it’s already in 1.38 but they’re nightly-only for now. And
those are, in particular, Cargo features that are really nice and hopefully
we’ll be able to use on stable Cargo pretty soon. The first of these is, you can
cargo fix --clippy. And this is something that I know a lot of people
have wanted for a while.
cargo fix is a sort of automated tool that cargo comes with, which
is, if the compiler tells you this doesn’t compile, try this instead.
cargo fix basically automatically applies those changes for you.
Ben: It’s very nice.
Jon: You can think of this as, how many times have you had the compiler tell
you, “do this instead” and you’re like, well, why don’t you do it? And that this
is exactly that.
cargo fix will just do it. And now there’s a
which is, run clippy, and if clippy suggests the fix, just make that fix for me.
We also, speaking of clippy, there’s also a nightly Cargo change that landed in 1.38, and that is, if you run clippy twice in a row, you will now still get the clippy warnings the second time you run it. Previously, we had this problem where, if you compiled your crate and then you ran clippy, you would get no warnings, because clippy would be like, oh, there’s nothing to compile. Everything is up to date. And that’s obviously not really what you want when you run clippy, you want the warnings. And so now clippy will re-compile your crate, even if you have previously compiled it.
Ben: There’s something else about a
Cargo.lock here, you mentioned, which
I haven’t seen. But you have some information about.
Jon: Yeah. So this is is not even nightly-only. This is sort of a hidden feature, so to speak.
Ben: That became stabilized with the 1.38 release.
Jon: Yeah. So now Cargo ships with support for an updated
format, and this updated format is disabled by default. And all the release
notes say, is really that it will use it if it sees it. It’s unclear how you
generate it in the first place, but this new
Cargo.lock format is supposed to
be diff-friendly. So if you check them into version control, rather than now,
getting like, 100 line changes because you ran
cargo update. Presumably you
should get fewer changes.
Ben: Which is nice, because at my company, we actually do— well, we just
began checking in our
Cargo.lock to our big monorepo, the thing that we use
Rust for. And GitHub, GitHub is actually smart enough to know that
is a generated file, and will not show the diff by default, even if it’s small.
But if you want to just do a
git diff in your command line, it’s nice to be
like, okay, just scroll past all the
Cargo.lock changes. Okay, here we go. The
Jon: Yeah, And it’s particularly annoying, because the
Cargo.lock file is
usually at the top, like it sorts first.
Ben: And it’s huge. Because it has all kinds of, like, you know, hashes about things and various like, data about every single crate that you want to compile.
Jon: Yeah, so I don’t know what this new format actually looks like, but I spotted them in, like, the detailed release notes, and this seems like something that would be pretty welcome.
We also have some exciting beta changes.
Ben: Yes, that’s it for 1.38. We can kind of talk about— so we, I think a
while back, probably one of our first episodes, you mention how, 1.38 was the
original target for async/await syntax to hit stable. That was pushed back by
one release, kind of missed the cutoff by a week or so. But not a big deal. Six
more weeks until it hits stable. It’s available for all to use. And in the
meantime, there are plenty of libraries who are excitedly preparing for this.
And so, I think we mentioned before, but async/await is not, kind of, the end-
all be-all of the async story in Rust. You can’t be like, yeah, I have this new
1.39 compiler. What do I do with it? If you actually want to use it in a serious
capacity, most folks who care about this, which is not everyone, if you don’t
care about async/await, then that’s fine. But if you do, it’s probably because
you’re using kind of web framework or it’s something with the web, or maybe some
kind of, like, backend service that’s very I/O heavy with SQL calls, or other
kinds of random IO that you’re doing. And so in this case, you want libraries to
actually support this. And so there’s quite a deep list of libraries that are
needed to make this very nice. And so, probably the
futures library is the
first one. And then on top of
futures, there is
tokio, which actually
manages to schedule all of your futures. And then there is
hyper, which lets
tokio to make HTTP calls. And then, you may be using a web framework
on top of that. And so at least, kind of, four libraries that you would want to
have stabilized, with new supported releases, before you could really say, hey,
I’m using async/await in a really official, like, production capacity. And so
the good news is that
hyper all have alpha releases
currently, where they’re preparing for async/await to become stable. And so I
think the goal, at least for the
futures, is certainly to be to have its
release before the 1.39 release comes out.
Jon: Yeah, I think the library authors here have been really good at keeping
up. And I think keeping up with each other as well. So when the new, I think
alpha-19 was released of
futures pretty recently, and then
tokio released a
new alpha right after that, and then
hyper released a new alpha right after
that. So there’s a pretty good coordination in the ecosystem. And I think the
idea is, that all of these are going to land stable versions the moment the—
essentially the current beta becomes the 1.39 stable.
Ben: And do we have a date for that? I could look up my calendar here if you want. Just distract the audience for a few seconds.
Jon: Yeah, I forget exactly when the 1.39 release is supposed to drop. I think the current expectation is that async/await will in fact land. It is in beta now, so that should be the case. There are still some known issues, but they’re known issues more in the sense of things to be improved in the future.
Ben: November 7th, is what I have in my calendar.
Jon: November 7th.
Ben: Yeah, so that should be the day that 1.39 lands and async/await syntax
becomes stable. And so hopefully by then, the goal is that all of these
fundamental libraries should become stable. And I think the bigger question now
is, like, I think, so
hyper should all be stable by
then with new releases. But web frameworks, if you want to just not issue like
raw HTTP calls with
hyper, if you want to do things with actual, like, routing
and perimeter handling and all this kind of stuff, you won’t have a framework
for that. And are they going to support this, and have— like, work on the new
releases of these underlying libraries? I know that Warp has a PR currently
working on that. I think you said Rocket?
Jon: Yeah. Rocket now uses alphas of
think. Not entirely clear to me why they use multiple runtimes, but they are.
And there’s an issue that’s open on basically rounding out and finishing off
that support for async/await, which is issue 1065, if anyone wants to look it up
and look at all the discussion that’s happening there. There’s also Tower. So
all the Tower stuff, which is from the— some of the same team that develops
Ben: Which doesn’t include Tower Web, which is their web framework, and was only kind of a proof of concept of Tower itself. I think right now it is currently unmaintained. They’re saying you should use Warp instead.
Jon: Yeah. But Hyper, for example, now uses Tower.
Jon: And so the Tower stack, I think, is also on
std::future. And it’s
also aiming for, like, a stable release.
Ben: Forgot about that, yeah.
Jon: I don’t know about any other— I don’t know about Actix Web and how
their progress is on
std::future. I’m not sure.
Ben: And then, there are probably things like Diesel as well, where if you want to have SQL calls happening asynchronously, I’m not sure how they’re doing right now. So we should have some kind of progress report hopefully, as the weeks roll on and this becomes closer. I mean, we’re recording this a bit late. Life gets in the way sometimes. Not a big deal, but it’s today, October ninth or so.
Jon: Yeah. So it’s about a month.
Ben: So we have a month out from, like, four weeks from here, you’ll be listening to this a few days after this, record it so— ever closer.
Jon: I also know that the— at least the
mysql_async crate also has an
alpha out for
Ben: I also saw that
reqwest as well. And so, the kind of, like, the easy
version of Hyper that’s not a web programmer, just kind of issue HTTP calls. But
do it in a very convenient way. And that has a new async release alpha, I
Jon: Yeah. So the ecosystem really is keeping up with this. And I think we’re going to expect basically all of them to issue new major releases the moment that 1.39 hits.
Ben: And thanks to all the folks who are contributing to these async things, which also includes our own Jon Gjengset here, I see you’re— I’m always, like, looking around and like, oh, it’s Jon’s name’s always appear in the release notes or in the commit log.
Jon: It’s funny because I accidentally signed up to Hacktoberfest, then immediately succeeded at the, like, you need to issue so-and-so many PR’s.
Ben: Nice. Okay.
Jon: Yeah, I think one thing that will be interesting with the 1.39 release is that the whole ecosystem is suddenly going to have a minimum version requirement of 1.39.
Ben: Yeah, that’s a good thing to think about.
Jon: It’s its own kind of interesting, that suddenly if you do anything in, like, the networking space, like, you’re going to have to need to be on 1.39 or or a recent beta nightly.
Ben: Which shouldn’t be too much of a problem, for I think people who are doing async/await stuff in Rust right now, we’re pretty used to tracking bleeding edge things. I don’t know, we’ll see. I know there are like, the big production users, like, you know, Google’s Fuchsia project and Microsoft. There’s a bunch of like, there’s a reason that Tokio has been so reluctant to make breaking changes because they have many large users. But it’s important to also have those users because they can also test out like, hey, does this is actually work? Are you, like, meeting your promises, and that kind of thing, in terms of performance and ergonomics.
Jon: In some ways, this is an opportunity for the ecosystem too, right? Like now, we’re going to do a synchronized release, basically, where everyone is going to issue breaking changes at once, and so now’s a chance to do some of the larger ecosystem changes.
Ben: And again, if you don’t care about async/await, then it’s not a big deal for you.
Jon: Yeah, then you can just—
Ben: If you aren’t doing web stuff, or I/O-bound stuff, if you’re just doing normal CPU-bound tasks, then it’s kind of like, yeah, cool, whatever. New future.
Jon: I think that’s all we had for the 1.38 release.
Ben: It’s all I had.
Jon: It was a small release, but I think it’s definitely progress. I think all of these are good changes, and it shows that the language is developing and maturing.
Ben: And even, like, you know, small changes, but under the hood, there are
still, like plenty of things, that have gone towards supporting again, like all
the generator work, async/await, like, there’s always work going on, like new
groundwork being laid for things to come the next year, even with regard to
const fn and various things with the trait resolver, Chalk, the like,
expanded, non-lexical lifetimes, the Polonius. And so, various secret projects
are always progressing in the background. So the machinery is all there, just
lying in wait, preparing to be used, getting tested.
Jon: Yeah, it’s really cool. All right. I think with that, we’re going to— are we signing off?
Ben: I’m signing off. See ya.
Ben: All right, bye.