
Rust 1.40 - mark-simulacrum
https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html
======
jeffdavis
The continuing improvements to procedural macros are great!

I do a fair amount of integration with C, and the work the rust team is doing
for procedural macros has helped _a lot_. Being able to use them in an extern
blocks will surely help more.

Like many, I have a wish list that I complain about sometimes, but I feel bad
about complaining because rust has done so much to improve my use case I don't
know where to begin. I should write up a blog post about all of the difficulty
I had, and how each release since around 1.28 has introduced features that
solved these problems one by one.

To me, Rust/C interop is the killer feature. Not only is it a low-level
language that can be used instead of C, it can also be used to _extend_ C
applications. I'm sure it was not easy to do this well, but what a great
strategic decision by the rust team to spend the effort on it!

~~~
joshbenford89
Can you recommend any good blog or tutorial on integrating C/Python and newer
releases of Rust?

~~~
jeffdavis
I didn't use much except for the official docs (book and reference). Googling
around shows some promising material.

Release notes are helpful -- when you see something added related to C, it's a
strong hint to read about the new feature.

Macro features are important because rust has sophisticated macros and C
macros are closer to text replacement. So when trying to emulate a C header,
you need to do a lot of macro magic in rust sometimes.

Sorry that I don't have more to offer from personal experience.

------
randyrand
Using #[non_exhaustive] on enums is going to be general bad practice, just as
many in c++ consider ‘default’ switch cases bad practice.

When a new state is added to an enum, we _want_ the code to not compile so
that we can fix all the places that need updating.

~~~
Guvante
That is why there are two versions available. The default matches the behavior
you describe and is the default because for small projects it is the right
decision.

However sometimes you are a dependency and you want to give up this
restriction to gain the ability to add things without having to bump your
major version number.

By far the most common example is error enums which don't necessarily need all
of their downstream crates to handle every error, they likely are bucketing
most of them anyway and non_exhaustive ensures they support that.

~~~
bcrosby95
Since the developer of a library has no insight into my application, they have
no idea how important an exhaustive match is or isn't in any given piece of
code I'm writing.

This is a decision library users should be making, not library writers.

~~~
skybrian
It seems like the main issue is consent. If you're using a library in a way
the author didn't agree to, that's fine, but you don't get any guarantee it
will keep working after an upgrade.

If you want to do that, you could edit your own copy of the library's source
code and nobody will mind. Maybe that's enough?

It seems like you shouldn't be able to publish a crate where you're using an
upstream library in a way they don't consent to, because now you're involving
others in this dispute. A basic requirement for publishing to a shared open
source ecosystem should be that you're resolving any disputes you have with
upstream libraries and not just going your own way.

------
penagwin
I don't personally use Rust (yet) but I love seeing its progress!

Congrats to everyone who has been contributing to Rust, it's definitely moving
the language forward!

~~~
moksly
There hasn’t been a single Rust job posting in the entire region of Denmark
where I live in 2019, so it’s probably fair to say that almost no one uses it.

The progress is still cool though.

~~~
nicklauri
The main reason is many companies have a lot of C/C++ devs or other devs
learned Rust, so they don't have to hire new Rust programmer. There are many
places using Rust, you should check this out: [https://www.rust-
lang.org/production/users](https://www.rust-lang.org/production/users)

~~~
Skunkleton
The above is also certainly non-exhaustive. Google isn't on the list, and they
are using rust in fuchia.

~~~
danellis

        #[non_exhaustive]
        https://www.rust-lang.org/production/users
    

There you go.

~~~
Skunkleton
lmao

------
kire456
The #[non_exhaustive] feature makes me unreasonably happy. It is a problem I
hadn't even realized might occur, and the solution is very elegant, forcing
depending code to be sufficiently general.

~~~
est31
For enums at least, I'm not recommending it's use (yet), as with
_Nonexhaustive you can make sure you caught all cases internally. Matching on
_Nonexhaustive as a _user_ of the library is of course a bad idea. There've
been proposals to a lint like #[deny(reachable)] to make such checks possible
for #[non_exhaustive] as well but it seems that nothing has happened yet:
[https://github.com/rust-
lang/rust/issues/44109#issuecomment-...](https://github.com/rust-
lang/rust/issues/44109#issuecomment-521781237)

~~~
kibwen
_> For enums at least, I'm not recommending it's use (yet), as with
_Nonexhaustive you can make sure you caught all cases internally._

I don't think this is necessary. The attribute in question is applied to an
enum variant, and that variant's constructor is then given only crate-wide
visibility. This looks to be simply a compiler-enforced codification of the
pattern you're describing.

~~~
est31
It can both be applied to enum variants as well as to entire enums. I meant
the latter case. From the release announcement:

> A perhaps more important aspect of #[non_exhaustive] is that it can also be
> attached to enums themselves. An example, taken from the standard library,
> is Ordering

For example, take this _Nonexhaustive enum case here:
[https://github.com/est31/rcgen/blob/d6b84d3d9d51b088dd672975...](https://github.com/est31/rcgen/blob/d6b84d3d9d51b088dd672975e68dcbcc286e347a/src/lib.rs#L172)

A little bit further down, I'm matching on the enum in the to_oid function.
I'd prefer if I got an error or at least a warning pointing to the match if I
added a new enum case and didn't update the match statement.

~~~
Nemo157
non_exhaustive only affects downstream code, within the crate you can still
treat it exhaustively. For example in this playground[0] if you build in test
mode the match works inside the crate, but fails in the doc-test because that
is treated as external code.

[0]: [https://play.rust-
lang.org/?version=stable&mode=debug&editio...](https://play.rust-
lang.org/?version=stable&mode=debug&edition=2018&gist=6ab1c7f5a94ca85915b114f97246b170)

~~~
est31
Oh that's an interesting point, I didn't know that. I guess I'll use
#[non_exhaustive] then after all.

------
Waterluvian
Wonderful! Any further news on evolution of the Rust Language Server? I'm
still hoping ~Santa~ Annual Gift Man will bring me a considerably crisper,
more accurate IDE-like experience to my favourite non-Intellij editor.

~~~
steveklabnik
Have you seen rust-analyzer? That’s effectively it.

~~~
Waterluvian
No I don't think I was aware of this. I've been playing with VSCode -> RLS
Plugin -> RLS. It looks like this is not that, so I'm pretty excited to check
it out.

Thanks for sharing!

~~~
dralley
Unfortunately you still have to compile it from source instead of install an
extension from the store, and there's no autoupdate.

But the experience is vastly better. I deleted RLS immediately. And it's not
that hard to install either.

~~~
rapsey
Analyser runs at 400% cpu constantly for me.

~~~
jayflux
Have you tried a recent build? They fixed a few issues around cpu usage over
the past few months

------
csande17
I'm a little confused by the decision to make breaking changes to the borrow
checker in Rust 2015. Wasn't the whole point of Rust 2015 to allow old code
that wasn't compatible with 2018's changes to compile? If keeping strict Rust
2015 source-compatibility was too burdensome for the compiler maintainers, why
not just remove Rust 2015 entirely and tell everyone to use the auto-upgrader
tools?

~~~
steveklabnik
The only reason that breaking changes were allowed to be made was that they
fixed soundness issues.

~~~
kibwen
To elaborate, the original borrow checker that launched with Rust 1.0 had edge
cases that could only be resolved with a drastically different analysis
pipeline. As a result, it wasn't able to properly reject some patterns that
were disallowed by the conceptual model. Over the course of several years this
new analysis pipeline was developed and the borrow checker was rewritten to
use it, which now properly rejects these patterns. But three years is plenty
of time for code in the wild to begin relying on edge cases, so there's been a
year-long deprecation cycle to warn anyone who might not have updated their
code by now.

~~~
csande17
Right, I guess I had it in my head that the Rust 2015-vs-2018 divide _was that
deprecation cycle_.

~~~
kibwen
The difference between Rust 2015 and 2018 is less than most people think.
Originally, yes, Rust 2018 was used to push the new borrow checker without
affecting code using Rust 2015. But unlike a "version" that gets deprecated
and left behind, a Rust edition perpetually continues to be supported and
benefit from improvements with every compiler release. But this means that in
order to support different borrow checkers in different editions the compiler
had to continue to ship with both borrow checkers, which, considering how much
code that is and the aforementioned bugs, was an intractable proposition in
the long term.

------
NieDzejkob
Woah, todo! is going to come in handy considering the wordiness of
unimplemented!. However, weirdly enough, the documentation claims it has been
stabilized in 1.39. Why is that?

~~~
steveklabnik
It’s just a bug. Would you like to file one or would you like me to?

~~~
NieDzejkob
I'll send a PR, one moment.

~~~
steveklabnik
Awesome, thanks!

------
mamcx
I like the IDEA but the implementation is not the good one.

Instead, this is what will be elegant:

    
    
        pub enum SearchOption {
            Left,
            Full,
        }
    
        pub enum SearchOptionBeta:SearchOption {
            Rigth,
        }
    

Yep, extending struct and enums.

This mean MATCH touch "SearchOption" as the "stable" API and the inner crate
touch SearchOptionBeta. When SearchOptionBeta need magic is that it match
SearchOption too. Later is just a matter of replace one for the other.

And this is even useful for more than to stabilize certain fields or arms...

~~~
swsieber
I'd personally do this:

    
    
      pub enum SearchOption {
          Left,
          Full,
          Beta(SearchOptionBeta),
      }
    
      #[non_exhaustive]
      pub enum SearchOptionBeta {
          Right
      }

~~~
mamcx
Yeah, this is how could be done with this, but also show why is a poor
abstraction.

If enums were abled to be extended:

    
    
      match e: SearchOptionBeta {
       SearchOptionBeta:: Left, Rigth, Full
      }

------
gfs
Can somebody elaborate on the #[non_exhaustive] use case inside a private
struct? Wouldn't a separate crate not be able to use the struct if it was in
another crate?

~~~
wtetzner
The point is that the struct is public, _and_ the fields are public, but users
of the crate cannot directly _create_ a new instance of the struct (without
going through a function call in the module). This allows users to access the
struct fields, but they cannot do any operations that would break if a new
field is introduced.

------
xiphias2
let x = Bar::Variant { a: 42 }; //~ ERROR

Of course it's an error, as Bar doesn't have a field called ,,a''

~~~
mark-simulacrum
Thanks for pointing this out! Unfortunately, unlike most of our docs we don't
yet have testing in place for the code examples on the blog. I've just pushed
up a fix though so once that propagates this should be fixed.

------
Siecje
Can you cross compile for another platform?

~~~
orf
Yes: [https://github.com/rust-embedded/cross](https://github.com/rust-
embedded/cross)

