
Rust 1.32 released - steveklabnik
https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html
======
kbenson
Wow, it's been a while since I caught one of these announcements, and I have
to say those those additions looks pretty awesome. I myself am a print
debugger, and the dbg macro looks like a major quality of life improvement in
that regard.

The default removal of jemalloc should greatly cut down on binary size as
well, if I understand correctly.

I've dabbled in Rust, but haven't had a major reason to use it for anything
yet. I'm looking forward to when that time comes.

~~~
adwhit
> I myself am a print debugger

In Rust, everyone is a print debugger. The only thing that really goes wrong
in normal code (once it compiles) is "why is this value not what I expect?".
Dropping down into GDB is way overkill.

~~~
scottlamb
This is a silly claim.

* Rust code can have memory errors + undefined behavior, because Rust code can say "unsafe". Plenty of real projects use "unsafe". (Alternate reason: because the compiler has soundness bugs.)

* Memory errors + undefined behavior aren't the only reasons people like debuggers. Consider: there are plenty of other memory-safe (GCed) languages in which people find debuggers useful (such as Java). "The only thing that really goes wrong in normal code (once it compiles) is 'why is this value not what I expect?'" is arguably true there as well.

And, for the record, gdb works decently well with Rust code. Not perfectly
(yet) but well enough to be useful. I have tried it (although I'm more of a
printf debugger myself).

~~~
vvanders
Honestly when I'm dealing with memory errors and undefined behaviors I can
count on my hands the number of time a debugger saved me and the hundreds of
times I've had to printf my way to victory thanks to 2/3/N-order effects that
cascade to the final corruption.

Don't get me wrong, they're handy but I find them much more useful for
stepping flow than root-causing errors.

Also if you're dealing with race conditions the only way to safely root-cause
to to stash away data somewhere in mem and print it later as
flushes/fences/etc change behavior. Debuggers make that even worse.

Love my debuggers for behavior issues but each tool has it's place.

~~~
Groxx
> _Also if you 're dealing with race conditions the only way to safely root-
> cause to to stash away data somewhere in mem and print it later as
> flushes/fences/etc change behavior. Debuggers make that even worse._

I'm not sure how Rust's support is here, but in my experience it's the exact
opposite. Debuggers with var-watch or conditional breakpoints can do this (and
a heck of a lot more) on the fly, and that's almost always faster than re-
compiling and running. Even at the extreme-worst case, you can be a print-
debugger with a debugger without needing to rebuild each time, just re-run.

~~~
vvanders
Your conditional breakpoint can change execution behavior thought flushing
cache/icache in a way that doesn't reproduce.

X86 is pretty orderly so you usually don't see that class of bugs until you
start getting on other architectures but when you do _man_ is it nasty. C/C++
volatile comes to mind particularly. MSCV makes it atomic and fenced which
isn't the case pretty much anywhere else.

Also debuggers don't help you with the 2nd/3rd order effects when you need to
trace something that's falling over across 5-6 different systems. With print
based debugging I can format + graph that stuff much faster than a debugger
can show me.

Like I said, different tools for different uses. It's just important to know
the right tool so that everything doesn't look like a nail.

~~~
Groxx
> _Your conditional breakpoint can change execution behavior thought flushing
> cache /icache in a way that doesn't reproduce._

Yes, that is definitely true. But so does calling a printing func that does
IO, since it often involves system-wide locks - I'm sure many here have
encountered bugs that go away when print statements are added. But debuggers
are definitely more invasive / have stronger side effects, and have no
workaround, yea.

Multiple systems: sorta. Past (legitimately shallow) multi-process debugging
that I've done has been pretty easy IMO, you just add a conditional breakpoint
on the IPC you want and then enable the breakpoints you care about. Only
slightly more complicated than multi-thread since the source isn't all in one
UI. Printing is language agnostic tho, so it's at least a viable fallback in
all cases, which does make it a lot more common.

\---

To be clear, I'm not saying there's _never_ a need for in-bin "debugging" with
prints, data collection of some kind, etc. You can do stuff that's infeasible
from the outside, it'll always have some place, and some languages/ecosystems
give you no option. Just that it's far later than most people encounter, when
a sophisticated debugger exists. E.g. printf debugging in Java that I
encounter is usually due to a lack of understanding of what the debugger can
do, not for any real benefit.

~~~
vvanders
> But so does calling a printing func that does IO, since it often involves
> system-wide locks

> the only way to safely root-cause to to stash away data somewhere in mem and
> print it later as flushes/fences/etc change behavior.

Dude, I _literally_ called that out in the root post ;).

~~~
Groxx
Memory races, yea. Logical races no. But yep - I'd forgotten the context,
agreed :)

------
timClicks
Although I'm somewhat embarrassed to admit, I bet that dbg! is going to be
extremely helpful in my Rust programming. Really appreciate that the team is
taking time to consider "trivial" usability/ergonomics additions to the
language.

------
KeyboardFire
It's funny that this is the first time I've seen a language explicitly condone
"print debugging." It's one of those things that everyone says you're not
supposed to do and then does anyway.

Does any other language have a similar feature?

~~~
root_axis
I think debuggers are not worth the cost for many kinds of debugging
scenarios. They're great for stepping through projects you're not really
familiar with or in situations where code seems to be in violation of baseline
expectations, but fiddling around with breakpoints and watches and other UI
particularities of the debugger carries more cognitive overhead than "print
debugging". Additionally, I think the problem is better solved by using
thoughtful and contextualized logging with appropriate severity levels. Couple
this with a TDD approach to development and you'll end up in a workflow that
is just _faster_ than stepping through lines of code when you could have your
assumptions verified through logs and test assertions.

~~~
jasonhansel
Agreed! Personally I've found that I can find and fix problems much faster
with a few print statements than with a debugger--debuggers can make it harder
to trace through the full execution of a program.

~~~
naasking
> debuggers can make it harder to trace through the full execution of a
> program.

Except you often don't want a full execution, you often just want a partial
execution where you suspect the problem arises. I can assure you that a good
UI debugger is extremely helpful. Command line debuggers less so.

~~~
mikekchar
This is why unit tests are so helpful. You only debug the part of the code
that's broken. It's a kind of a different way of thinking and people often
write what I consider to be "bad" tests -- i.e. tests that don't actually
exercise real portions of the code, but rather make tautological statements
about interfaces. I spend a considerable amount of time designing my code so
that various scenarios are easy to set up. If you find yourself reaching for a
fake/mock because it is hard to set up a scenario with real objects, it's an
indication of a problem.

This extra work pays off pretty quickly, though. When I have a bug, I find a
selection of tests that works with that code, add a couple of printf-
equivalents and then rerun the tests. Usually I can spot the error in a couple
of minutes. Being an older programmer (I worked professionally for over 10
years before Beck published the first XP book), I'm _very_ comfortable with
using a debugger. However since I started doing TDD, I have never once used
one. It's just a lot faster to printf debug.

The way I've explained it before is that it's like having an automated
debugger. The tests are just code paths that you would dig into if you were
debugging. The expectations in the tests are simply watch points. You run the
code and look at the results, only you don't have to single step it -- it just
runs in a couple of seconds and gives you the results.

You may think that the overhead of writing tests would be higher than the
amount saved with debugging and if it were only debugging, I think that would
be true. However, one of the things I've found over the years is that I'm
actually dramatically faster writing code with tests compared to writing it
without tests (keep in mind that I've got nearly 20 years of TDD experience --
yes... I started _that_ early on). I'm pretty good at it.

The main advantage is that when you are writing code without tests, usually
you sketch together a solution and then you run the app and see if it works.
Sometimes it does pretty much what you want, but usually you discover some
problems. You use a debugger, or you just modify the code and see what
happens. Depending on the system, you often have to get out of the context of
what you are doing, re-run the app, enter a whole bunch of information, etc,
etc. It takes time. Debuggers that can update information on the fly are great
time savers, but you still have to do a lot of contextual work.

It takes me some extra time to write tests, but running them is super quick
(as long as you aren't writing bad tests). Usually I insist that I can run the
relevant tests in less than 2 seconds. Ideally I like the entire suite to run
in less than a minute, though convincing my peers to adhere to these numbers
is often difficult. That 2 seconds is important, though. It's the amount of
time it takes your brain to notice that something is taking a long time. If
it's less than 2 seconds (and run whenever you save the file), usually you
will barely notice it.

In that way, I've got better focus and can stay in the zone of the code,
rather than repeatedly setting up my manual testing and looking at what it is
doing. Overall, it's a pretty big productivity improvement for me. YMMV.

~~~
andrewflnr
I really like the idea of tests as materialized debugging sessions.

------
xxpor
One thing I noticed: ne means native endianness. It's probably because I'm
used to C, but I'd have preferred he for host endianness and ne for network
order endianness.

~~~
tropo
The naming is far worse than that. For example, from_ne_bytes seems to imply
that bytes could have an endianness. That would require bitwise addressing.

~~~
xyzzyz
A _byte_ cannot have endiannes, but _bytes_ can, and that's how I think one
should read that name.

~~~
abainbridge
Wellll, the DSP I used to work on had 24-bit bytes. When we saved a data
structure onto the SD card (that had 8-bit bytes) we had to decide what
endianness to write the byte in. :-)

------
roadbeats
I’m waiting for async/await... that will start the party!

~~~
steveklabnik
You and many others... the lang team has been hard at work. We want it to
ship, but we also want to get it right. It will be a huge deal, for sure.

~~~
parley
I'm waiting eagerly too, thanks for all the hard work you do!

I read somewhere in all the discussions that Carl was hesitant to go all-in on
futures 0.3 (those are definitely landing in std, right?) in tokio before some
additional ergonomics had landed, possibly some language feature among them
but I may misremember...

Do you know the list of things and possibly their tracking issues? Futures in
std, async/await, etc, something something more? Would love to be able to keep
track and follow along :)

~~~
steveklabnik
No problem, though I don't work on this aspect at all, to be clear :)

> (those are definitely landing in std, right?)

Yes.

> Do you know the list of things and possibly their tracking issues?

[https://areweasyncyet.rs/](https://areweasyncyet.rs/) :D

~~~
parley
Ha, that was a superb answer, thanks! :D I'll be checking that site!

I know you may not have your fingers in this particular flower pot, so the
"you" was directed at the entire Rust community. However, while we're here you
still get a big personal thanks -- your Rust for Rubyists got me hooked those
years back and the docs/book (1st ed and then 2nd ed with Carol) work you've
done since is nothing short of amazing -- and with these latest developments I
hope you find a great place to continue your work <3

------
frio
Not that I use Rust for more than toy projects, and not that the choice of
allocator makes (any) difference for those... but I'm stoked to see the system
allocator used by default now. Tiny binaries are good binaries.

------
winstonewert
So, the question I have is, should I switch my projects back to jemalloc? Are
there are guidelines for determining where it makes sense and where it
doesn't? (Obviously to get the fully correct answer for my project, I should
benchmark, but how do I know if its even worth going to the effort of that?)

~~~
nickbee
It depends. In the gamedev industry, we noticed performance improvements when
switching the allocator. But “should” is relative.

You probably won’t get a 2x boost from it. But you might notice some
improvements. It’s worth trying if you can test it quickly.

Software best practices are like flossing: good in the long term, but probably
not crucial to keeping your bite.

~~~
majewsky
I'm not incredibly familiar with gamedev, but I would expect most allocations
in games to be performed by small-object allocators on top of the general-
purpose allocator, so the choice of general-purpose allocator should not make
that much of a difference, should it?

------
knowThySelfx
I love Rust too. But lately, been getting the feeling that its trying to do
"everything". Hope it doesn't end up the C++ way.

Don't get me wrong, dbg macro isn't one of them. Heavy user of print debugger
here.

------
nixpulvis
LOL, my dyslexia confused me pretty bad with `dbg!` I was expecting this to
hook into GDB somehow, and got really excited. It's still very neat, I'll be
using it a lot I'm sure. Reminds me of [https://github.com/reem/rust-
inspect](https://github.com/reem/rust-inspect) a little bit.

I'm also quite happy with the uniform path work that's landed. Rust now has
easily one of the best namespace management's I've used in a programming
language.

Cheers!

~~~
jonreem
Hey, that’s my library! I’m glad to see a similar macro getting added
upstream, so you no longer need to install libraries like this one for easy
print debugging.

~~~
nixpulvis
You never merged my PRs, QQ. Just teasing.

------
ChrisSD
How's the documentation coming along? I've had to take a break from it because
so far I've only been able to use if for hobby projects. Coming back to Rust
for me often means bouncing around different editions of the docs (especially
if FFI is involved) and searching blog posts, forums and my own old code to
try to remember how to do things. But then of course the language has changed
or best practice has so it's all out of date.

~~~
Hortinstein
I think it has come along really well. I started trying to learn it a few
years ago, but going through the official documentation that was recently
revised has been a breath of fresh air. Went from one of the most confusing
experiences to one of my favorite. Highly recommend starting here

[https://doc.rust-lang.org/book/index.html](https://doc.rust-
lang.org/book/index.html)

------
jake_the_third
As of the time of this post, the official standalone installer page
incorrectly lists 1.30.0 as the latest stable release. For users who prefer or
need standalone installers, please use the URL templates bellow to download
your packages until this issue has been resolved.

The URL template for normal rust installers is:

    
    
        * https://static.rust-lang.org/dist/rust-1.32.0-{TARGET-TRIPPLE}.{EXT}
    
        * https://static.rust-lang.org/dist/rust-1.32.0-{TARGET-TRIPPLE}.{EXT}.asc
    

The URL template for additional compilation target installers
(`x86_64-unknown-linux-musl`, `wasm32-unknown-unknown`, ..etc) is:

    
    
        * https://static.rust-lang.org/dist/rust-std-1.32.0-{TARGET-TRIPPLE}.{EXT}
    
        * https://static.rust-lang.org/dist/rust-std-1.32.0-{TARGET-TRIPPLE}.{EXT}.asc
    

To avoid a very long post (and a lot of scrolling), the list of links to all
target installers supported by rust has been omitted from this post. Refer to
the complete list of supported platforms in [https://forge.rust-
lang.org/platform-support.html](https://forge.rust-lang.org/platform-
support.html).

The file extension for auxiliary target installers is `.tar.gz` (or `.tar.xz`)
for all targets including Windows.

Note: Due to a known bug, browsing the complete list of all installers is not
available on [https://static.rust-lang.org](https://static.rust-lang.org). It
is however still possible to access dated repositories via the following URL
template:

[https://static.rust-lang.org/dist/YYYY-MM-DD/](https://static.rust-
lang.org/dist/YYYY-MM-DD/)

Installers for the current stable release of rust can be browsed at
[https://static.rust-lang.org/dist/2019-01-17/](https://static.rust-
lang.org/dist/2019-01-17/)

Cheers!

------
est31
Just recently I was looking at example code of an edition 2018 crate and what
I feared actually happened: I didn't know any more which crates this example
code used, because extern crate statements were missing. So yaay more manual
figuring out I guess...

~~~
the_duke
I never understood this argument: you just have to look in Cargo.toml.

Yes, for multi-target (eg lib + bin, ..) it can be a little more work to look
it up.

But the new system is SO much more convenient to use overall.

~~~
est31
For lib.rs in libraries or main.rs in binary only crates this works great. But
if you have multiple examples, then each example can use any dev-dependency it
wants and any of the normal dependencies. It's super hard to figure out which
crates are needed to add to make an example compile locally.

To give a concrete example, please look at this [1] Cargo.toml and this [2]
example and try to figure out the crates its using. I've highlighted them in
Cargo.toml, to show how irregular the use is [3].

We don't have test-only or binary only dependencies yet. They would make this
a bit easier.

I want to focus on the code I'm writing, not onto figuring out which crates I
need to include. On the bright side though, the system is still better than
what C++ got which is not knowing from which header a particular symbol came
from :).

[1]:
[https://github.com/djc/quinn/blob/e555d11a430b9760d149a27659...](https://github.com/djc/quinn/blob/e555d11a430b9760d149a2765998734b6acfcd4d/quinn/Cargo.toml)

[2]:
[https://github.com/djc/quinn/blob/e555d11a430b9760d149a27659...](https://github.com/djc/quinn/blob/e555d11a430b9760d149a2765998734b6acfcd4d/quinn/examples/client.rs)

[3]:
[https://gist.github.com/est31/7cb33e8a6b63c8798381bdb5e91a14...](https://gist.github.com/est31/7cb33e8a6b63c8798381bdb5e91a145a)

~~~
the_duke
Point taken!

I also wish we could specify /examples or /tests specific dependencies in
Cargo.toml.

A question here is though if such a complex structure is so rare that making
it easier for the 90%+ of crates is worth it, while inconveniencing the
complex cases.

------
ainar-g
dbg! looks neat. It made me wonder if any of the statically typed compiled
languages have an equivalent of Ruby's binding.pry or JS's debugger call? That
is, something like

    
    
      x = foo();
      invoke_debugger(); // An interactive console appears here.
      y = bar(x)

~~~
SCHiM
I use this sometimes with some C/C++ code.

Mostly, if I want a break somewhere I do this:

    
    
      *(int*)0 = 1;
    

Which will result in a crash, I attach my debugger, run the code and if it
reaches that line it will break and I can inspect everything I want.

It's easier than adding a __asm(int3) because it's cross platform. On windows
for example it's not possible to perform inline assembly in x64 builds, and
compiler intrinsics are not portable.

~~~
nitrogen
Have you ever had issues with the compiler removing/ignoring that line when
optimizations are turned on?

~~~
SCHiM
No, could it? If I ever noticed it I would make it a bit more complex.

------
est31
Using the literal fragment specifier in serde-big-array already to reduce code
size if possible: [https://github.com/est31/serde-big-
array/commit/c6e5669ffe65...](https://github.com/est31/serde-big-
array/commit/c6e5669ffe65116afb521d6fd489501d775e0abe)

------
krzat
What is the status on incremental compilation and code completion?

------
AceJohnny2
Typo note:

> literal _mactches_ against literals of any type;

~~~
steveklabnik
Thank you! [https://github.com/rust-lang/blog.rust-
lang.org/commit/a775b...](https://github.com/rust-lang/blog.rust-
lang.org/commit/a775ba5b8b07fa65f4c20fa77a2ac6b1e72c9e3d) (will be deployed in
a few minutes)

~~~
AceJohnny2
Oh it's just MD on Github.

... of course it is. Noted for next time ;)

------
alexandernst
Why every release of Rust appears on HN? (meanwhile Python, Node, Ruby, Perl,
PHP, etc... don't enjoy that same treatment)

~~~
steveklabnik
Other languages' releases do get submitted. I just checked Ruby, Python, and
Node, and all their last releases were submitted and got some upvotes, but not
a ton of discussion.

~~~
kenhwang
The Christmas release cycle of Ruby probably doesn't help either ;)

------
jackblack8989
Plug- Use QtCreator for a nice Rust GUI

~~~
mlevental
what? how?

