[HN Gopher] Rust 1.56.0 and Rust 2021
       ___________________________________________________________________
        
       Rust 1.56.0 and Rust 2021
        
       Author : steveklabnik
       Score  : 333 points
       Date   : 2021-10-21 14:59 UTC (8 hours ago)
        
 (HTM) web link (blog.rust-lang.org)
 (TXT) w3m dump (blog.rust-lang.org)
        
       | mjw1007 wrote:
       | In 2017 or so when Rust editions were invented, the notion was
       | that editions were primarily a "rallying point" (a way to make
       | Rust's continuous release process feel more like Java's or
       | C++'s), and only secondarily an (opt-in) change to the language
       | itself.
       | 
       | See for example the summary at the top of https://rust-
       | lang.github.io/rfcs/2052-epochs.html
       | 
       | It seems to to me that that aspect has now been dropped: TFA
       | simply says "Editions are a mechanism for opt-in changes that may
       | otherwise pose backwards compatibility risk."
       | 
       | I'm not sure this change of direction has been officially
       | announced anywhere, though.
       | 
       | (I think this is a good change: last time I saw cases of people
       | asking questions like "How do I do foo in Rust 2018", and getting
       | a mix of answers like "Nothing in Rust 2018 affects foo" and
       | "Since Rust 1.20 you've been able to use std::foo::bar to do
       | that".)
        
         | nicoburns wrote:
         | The 2018 was widely considered to be overly pressured (contrary
         | to the usual Rust approach of shipping it when it's ready),
         | which led to burnt out compiler devs, and a bunch of people
         | with unmet expectations. I think the approach to decouple Big
         | Bang features from editions has been made in response to that.
        
           | mjw1007 wrote:
           | It's hard to tell how much of the trouble with 2018 was due
           | to the concept of having a major release with several things
           | being updated together, and how much was due to the mistake
           | of setting too early a deadline (by pre-announcing that it
           | would be "Rust 2018" rather than "Rust 2019").
        
           | kzrdude wrote:
           | 2021 was explicitly a "nothing new" edition, at least.
        
         | pornel wrote:
         | It created confusion, because:
         | 
         | * lumping marketing of cool features with an announcement of a
         | few incompatible changes was easily misinterpreted as all new
         | features requiring a new incompatible edition (while in fact
         | almost all marketed features were already available in the old
         | edition).
         | 
         | * celebration of features developed in recent years under one
         | big event sounded like all these features were brand new and
         | released at once.
         | 
         | For people who didn't follow Rust development, the announcement
         | sounded like Rust suddenly made a lot of incompatible changes.
        
         | steveklabnik wrote:
         | It was discussed as part of the 2021 Edition RFC.
        
         | tialaramex wrote:
         | Interesting. It mentions stuff like the library and
         | documentation.
         | 
         | When IntoIterator for arrays first stabilized (with the hack
         | hiding into_iter() for backwards compatibility) I considered
         | making all the documentation changes to use natural arrays in
         | standard library examples, which of course would now be the
         | obvious way to write it whereas previously it was ugly.
         | 
         | I didn't do it (and now I have a job keeping me too busy) and I
         | haven't gone back to look at examples to see if all/ most /
         | some were updated to use arrays in the now natural way.
        
       | Fiahil wrote:
       | It's not written in the announcement, but I am under the
       | impression that Rust 1.56 compiles a bit faster. Is that right ?
        
         | Macha wrote:
         | Here's some compile benchmarks from the LLVM update which is
         | the main reason for compile time changes:
         | 
         | https://perf.rust-lang.org/compare.html?start=ef9549b6c0efb7...
         | 
         | Some things compile decently faster (~ 10%), some things
         | compile a little faster or slower (~ +/- 3%), some things have
         | a bigger perf hit but not as many as had a bigger perf gain (~
         | -10%).
         | 
         | So it's faster on average but the data is muddy enough that you
         | probably wouldn't stick it front and center on your release
         | notes.
        
           | dralley wrote:
           | Does anyone know what change was responsible for the big
           | improvement from a few days ago?
           | 
           | https://perf.rust-lang.org
           | 
           | It's less of a universal improvement than the pass manager,
           | but for most of the benchmarks that it does impact it seems
           | just as large, or larger.
        
             | kzrdude wrote:
             | From the graph, it points out this commit. And from the
             | description, I think it's exactly that commit and not just
             | one close to it. I heard it was a big improvement.
             | 
             | https://github.com/rust-lang/rust/commit/63cc2bb
             | 
             | > Enable new pass manager with LLVM 13
             | 
             | > https://github.com/rust-lang/rust/pull/88243
        
         | benschulz wrote:
         | I believe this is mostly due to the switch to LLVM 13[1].
         | 
         | [1]: https://twitter.com/ryan_levick/status/1443202538099073027
        
           | eska wrote:
           | That seems to have been a mixed bag. But they also enabled
           | PGO (or was it LTO?) and that was mentioned to be a bigger
           | improvement.
        
             | woodruffw wrote:
             | PGO requires a runtime profile, so I doubt they've enabled
             | that by default :-)
             | 
             | Rust has had LTO for quite a while, and it's normally a
             | source of _longer_ compilation times rather than shorter
             | ones (since LTO in LLVM-world involves mashing all of the
             | bitcode together and (re-)running a lot of expensive
             | analyses to further optimize across translation unit
             | boundaries.
             | 
             | OTOH they've been making continuous improvements to the
             | incremental compilation mode since 1.51/2, so that's
             | probably among the sources of improvements here.
        
           | nicoburns wrote:
           | I believe the new pass manager isn't due to be enabled by
           | default until the next version (1.57)
        
             | runevault wrote:
             | Yeah the significant improvements from 13 will require that
             | last I heard.
        
       | eska wrote:
       | Finally a nice way to init hash maps and all other kinds of
       | collections! The former was really unattractive to Rust newbies!
        
       | stusmall wrote:
       | I love the concept of editions. I haven't anything like it in
       | other languages. Having the ability to have one project made up
       | of crates of many different editions is brilliant. It makes
       | breaking language changes that would otherwise be a nonstarter
       | become minor and easy to manage. Love it
        
         | remram wrote:
         | Lots of languages have opt-in features/extensions/pragmas,
         | which are more granular but somewhat similar. Like Python's
         | __future__, Haskell's #LANGUAGE, and Rust's #![feature].
         | 
         | Adding 20 lines of #[!feature(...)] to every project would get
         | old quick.
        
         | steveklabnik wrote:
         | While there's nothing exactly like it yet, we did consider the
         | ways that many similar systems work. There's a lot of
         | similarities, even though I do think Editions end up being
         | meaningfully distinct.
         | 
         | As an example, here's a comment of mine on the original RFC
         | (which was called "epochs"): https://github.com/rust-
         | lang/rfcs/pull/2052#issuecomment-315... (the part with "Some
         | language development comparisons")
        
           | avgcorrection wrote:
           | > I think the main problem here is semver.
           | 
           | Maybe it's ironic that semver (machine-readable versioning)
           | ended up being a liability due to interpretation by people
           | (i.e. we can't release a 2.0 because it would "send the wrong
           | message").
        
             | steveklabnik wrote:
             | While semver was _intended_ as machine-readable versioning,
             | and still mostly is, given that sevmer does not say what an
             | "api" is in any way means that it's still defined by humans
             | at the end of the day.
             | 
             | I think I'm in agreement :)
        
               | stouset wrote:
               | Of course there's always Hyrum's Law[1], which can be
               | summed up as
               | 
               | > All observable behaviors of your system will be
               | depended on by somebody.
               | 
               | Even minor bugfixes will at some point invariably break
               | somebody who depended upon the broken behavior. So semver
               | really boils down to a human assessment of whether any
               | potential breakage is incidental or intended.
               | 
               | [1]: https://www.hyrumslaw.com/
        
               | tialaramex wrote:
               | Hyrum's Law reminds me of Frank Borman's "A superior
               | pilot uses his superior judgement to avoid situations
               | which require the use of his superior skill". On the user
               | side Hyrum's law is a situation where you're going to
               | need superior skill to fix it. You should instead have
               | used superior judgement to avoid this situation
               | altogether.
               | 
               | As a library author I don't feel there's any value in
               | considering Hyrum's Law. I can't help those poor fools,
               | for all I know they're relying on me not updating the
               | documentation to warn them they shouldn't rely on
               | undocumented behaviour I'm about to change... Rust
               | provides a pretty clear line in the sand on API changes
               | we can use to choose semver policy. If your program has a
               | proc macro to copy-paste sections of my source code into
               | yours so you can access my non-public functions, I can't
               | see that from where I am and you're lucky it ever worked,
               | I am under no obligation to ensure it magically stays
               | working in my next bugfix release.
        
               | avgcorrection wrote:
               | And I agree with you on the solution: version the
               | language (or whatever other more conceptual thing) by
               | year and the program by semver. It's the only thing that
               | makes sense given the constraints.
        
         | emteycz wrote:
         | ES(year) for JavaScript
        
           | nicoburns wrote:
           | A better JavaScript example would be strict mode, which is
           | opt-in with "use strict" and changes quite a bit of the
           | semantics of the code while being completely interoperable
           | with non-strict JS code.
        
             | Macha wrote:
             | Yeah, and the "use" statements for this came from Perl
             | which is probably the originator of this pattern here.
        
           | RussianCow wrote:
           | Newer versions of JavaScript do not break compatibility with
           | older versions, whereas different editions of Rust break
           | compatibility in various ways while still allowing
           | interoperability between libraries written in different
           | editions. That makes the two approaches very different.
        
         | bee_rider wrote:
         | Although if they hit Rust version 2.XX.Y this might add some
         | (probably brief) confusion.
        
           | RussianCow wrote:
           | I remember reading somewhere that Rust will never have a v2,
           | but now I can't find a source.
        
             | nicoburns wrote:
             | There are currently no plans, but I don't think it's a hard
             | never. I'd probably be willing to bet it'll be at least 10
             | years though.
        
         | nivertech wrote:
         | Solidity (a PL in which Ethereum's so called "smart
         | contracts"[1] are developed) has version pragmas [2] at the top
         | of each file.
         | 
         | That's necessary b/c there are lots of breaking changes between
         | language/compiler versions[3].
         | 
         | --
         | 
         | [1] they are more like DB triggers than contracts
         | 
         | [2] https://docs.soliditylang.org/en/develop/layout-of-source-
         | fi...
         | 
         | [3] https://docs.soliditylang.org/en/develop/050-breaking-
         | change...
        
           | woodruffw wrote:
           | Version pragmas themselves aren't new -- even Perl has
           | them[1]. What makes Rust's implementation nice (and somewhat
           | unique) is its commitment to backwards compatibility while
           | _allowing_ codebases to incrementally move towards a new
           | edition.
           | 
           | [1]: https://perldoc.perl.org/functions/use
        
           | tialaramex wrote:
           | From one your links:
           | 
           | > It just instructs the compiler to check whether its version
           | matches the one required by the pragma. If it does not match,
           | the compiler issues an error.
           | 
           | This is very different from Rust where your Rust 1.56.0
           | compiler will cheerfully compile Rust 2015, Rust 2018 and
           | Rust 2021 code, into the same program even. Rust editions are
           | _not_ about the compiler version, they 're about the
           | _language_ and every Rust compiler will compile every
           | language edition it knows about.
        
         | cygx wrote:
         | _> I haven 't anything like it in other languages_
         | 
         | Perl can do it not only at module level, but at block level
         | within a single source file.
        
         | xamolxix wrote:
         | > I haven't anything like it in other languages
         | 
         | Is that different from compiling one lib with --std=c++11 and
         | another with --std=c++17?
        
           | EdSchouten wrote:
           | Yes, in that in C++ it would break if one library used a
           | modern language feature as part of its public header files.
        
             | chc wrote:
             | Surely the difference there is that Rust doesn't have
             | header files.
        
               | masklinn wrote:
               | Not necessarily, you could imagine a system where the
               | header file specifies its edition.
        
               | dralley wrote:
               | But don't header files generally get concatenated
               | together due to the way "dumb" textual includes work?
        
               | cpeterso wrote:
               | A header file can check #if __STDC_VERSION__ or
               | __cplusplus versions to make some code conditionally
               | available for, say, C11 or C++11.                 #if
               | __STDC_VERSION__ >= 201112L         // C11 feature
               | #endif            #if __cplusplus >= 201103L         //
               | C++11 feature       #endif
        
             | [deleted]
        
             | hiccuphippo wrote:
             | Can't you compile libraries to object files independently
             | with whatever version of c++ they require and then link
             | them together?
        
               | int_19h wrote:
               | You'd still need the header that describes the public
               | interface of such a separately compiled object file.
               | 
               | Also, this doesn't work with templates, and modern
               | idiomatic C++ tends to be template-heavy.
        
               | tialaramex wrote:
               | Yes. If the only value the library brings to you is that
               | it generates a particular object file, you can divorce
               | that object file from your chosen language version
               | entirely.
               | 
               | If you have libraries that you don't care if they're C or
               | Pascal or a Lisp implemented in raw machine code, then
               | this works just fine and you needn't care about Rust's
               | editions feature. Rust will also cheerfully consume these
               | libraries although of course everything about them is by
               | definition Unsafe in Rust terms.
               | 
               | But most people want their C++ libraries to deliver a bit
               | more than "Here is some machine code, and here are some
               | symbol names that map to the machine code or to raw
               | binary data". Like maybe they want to be able to
               | _implement_ an Interface the library describes, or they
               | want to use a Concept the library names. You can 't do
               | those things using language-independent object files.
               | 
               | Rust library A, from edition 2021 can implement a Trait
               | from library B (edition 2018) on its thin wrapper of a
               | type from library C (edition 2015) and then you can
               | consume the resulting type, with its trait
               | implementation, from your Rust 2018 program.
        
               | MaulingMonkey wrote:
               | The problem is a C++ library's headers must be compiled
               | with the settings, context, and flags of every downstream
               | thing that depends on them, rather than separately.
               | 
               | Which isn't such a big problem if your C++ library
               | exposes a minimal C-like API from it's headers, with most
               | of the meat of the library hidden away in source files,
               | but might be a very big problem if your C++ library is a
               | miserable little pile of ~~secrets~~ _templates_ , a la
               | boost.
        
           | heftig wrote:
           | If the application is using C++17, wouldn't the headers of
           | the C++11 lib then be compiled as C++17, potentially breaking
           | things?
           | 
           | PS: The other way around is more obviously broken, with the
           | C++17 lib headers getting compiled using C++11.
        
             | pjmlp wrote:
             | Or you make use of the preprocessor or if constexpr, and
             | then have the specific code for each language version.
        
               | int_19h wrote:
               | The maintainers would have to do it for every new
               | language version that breaks them, though. The edition
               | system keeps old stuff working without any effort.
        
               | pjmlp wrote:
               | I don't want to start this discussion thread yet again,
               | but I am a firm believer that edition system only appears
               | to work right now because:
               | 
               | 1 - Rust is still quite young and doesn't have 30 years
               | of accumulated editions
               | 
               | 2 - There is still only one major Rust compiler
               | 
               | 3 - Editions are designed only to work when compiling the
               | whole project, including 3rd party dependencies, from
               | source code within a single build
               | 
               | 4 - So far the editions don't have semantic breaking
               | changes across editions, where behaviour changes across
               | the edition border
               | 
               | 5 - There is no plan to ever have editions work across
               | ABIs
               | 
               | So "The edition system keeps old stuff working without
               | any effort." might not be true when Rust achieves an
               | adoption scale similar to C and C++, in about 20 years,
               | with several accumulated editions, and a couple of
               | compilers in use.
               | 
               | I might be proven wrong, but that is how I see it today.
        
               | tialaramex wrote:
               | It's certainly true that if C++ library maintainers are
               | up for the ever-growing maintenance burden, they can all
               | individually deliver the same promise Rust gets out of
               | the box.
               | 
               | This is in practice what the maintainers of the three
               | standard libraries have to do, perhaps one or more of
               | them will offer their opinion about that experience?
        
           | orra wrote:
           | I don't know what guarantees your typical C++ compiler gives
           | you that those can link together?
           | 
           | Regardless, at the very least, you would need to write the
           | headers to be interoperable.
        
           | masklinn wrote:
           | Aside from the header issue, it doesn't allow for or support
           | backwards-incompatible changes.
           | 
           | Because editions are opt-in (and library-level source
           | metadata) the language itself can be modified in non-
           | backwards-compatible ways.
           | 
           | So for instance a C++ with editions could make ctors
           | `explicit` by default, or it could entirely change the
           | automatic member generation (by removing it for instance). As
           | long as the ABI and API remain compatible, that's fine.
        
             | neandrake wrote:
             | It's probably worth noting that the backwards compatibility
             | breaking changes I think only applies to the language and
             | not the standard library. I'm unable to look up the details
             | right now but I believe there's a trait function defined in
             | stdlib which is deprecated, supersede, but can't be removed
             | even as part of an Edition, or it would break older code.
        
               | masklinn wrote:
               | That is correct, editions are mostly about language-level
               | syntactic changes, the APIs have to be compatible between
               | editions. The only place where that isn't the case is the
               | standard prelude (the "builtins" you don't have to
               | import).
        
               | tialaramex wrote:
               | The ability to replace the prelude does mean that you can
               | imagine if somebody invents a much better thing than,
               | say, Rust's iterators Rust 2050 can have a prelude that
               | brings in std::better::Iterator instead of
               | std::iter::Iterator and then most coders will end up
               | using the new better iterators, just because that's the
               | kind you get out of the box.
               | 
               | Anybody who literally refers to std::iter::Iterator gets
               | the old ones of course as does any library code from
               | prior editions, but the documentation could lead those
               | few people in the right direction. And presumably
               | std::better::Iterator politely implements
               | std::iter::IntoIterator because why not.
               | 
               | I would be interested to understand if they're allowed to
               | replace the macros. The standard macros aren't actually
               | from the prelude, but instead if you aren't no_std you
               | get all the standard macros anyway. Are they allowed to
               | change those in a future edition? Or not?
        
               | stormbrew wrote:
               | Personally I'd kinda like it if preludes were decoupled
               | from editions in some way. Like, fine to have a default
               | per-edition but there are times I would _really_ like to
               | have a prelude without all the `impl <T> X for T`s
               | included.
               | 
               | You can kinda do this now with `#[no_implicit_prelude]` I
               | think but it has somewhat odd semantics. It applies to
               | all submodules, unlike most attributes, and then if you
               | define your own prelude you need to use it in every
               | submodule because they won't all have their own.
               | 
               | If it's gonna have global effect I think it'd be better
               | if it was:                   #[prelude]         mod
               | my_prelude {             use std::whatever::*;         }
               | 
               | and then my_prelude would be included in all submodules
               | by default.
        
               | nicoburns wrote:
               | Seems like it ought to new possible to rename
               | std::iter::Iterator to std::iter::OldIterator, add
               | std::iter::NewIterator, and then vary which iterator
               | std::iter::Iterator points to based on edition.
               | 
               | Maybe that would be considered too confusing though.
        
           | pornel wrote:
           | Yes, because C versions are frozen in time, and editions
           | aren't. Today Rust added brand new features to Rust 2015 and
           | Rust 2018, and will continue to expand them forever (every
           | new feature lands in all editions whenever possible).
           | 
           | Rust editions are closer to source code parsing modes. More
           | like enabling trigraphs in C or "use strict" in JS.
           | 
           | Additionally, textual header inclusion in C makes mixing
           | versions tricky. Rust has properly isolated crates, and
           | tracks edition per AST node (so that even cross-crate macros
           | work correctly with mixed editions).
        
             | alerighi wrote:
             | C compilers usually backport features in older standards as
             | well (I know, they are breaking the standard). One example
             | are C++ style comments, that are in the standard only from
             | C99, but basically every compiler supports them even in
             | ANSI/C90 mode.
             | 
             | By the way the difference is that Rust is not a standard,
             | thus is easier to evolve (the process is much shorter). On
             | the other side, the fact that a language changes slowly
             | it's something good in a way, it means that you don't have
             | to continue to change the way you do things, and update
             | older projects.
             | 
             | That to everyone that has to maintain code for decades it's
             | important. And every serious software project (not hobby
             | stuff) does stay in production decades really. I don't use
             | Rust, or even C++, for that reason.
        
               | nicoburns wrote:
               | > On the other side, the fact that a language changes
               | slowly it's something good in a way, it means that you
               | don't have to continue to change the way you do things,
               | and update older projects.
               | 
               | Isn't the point of Rust editions that this is also true
               | for Rust? Don't want to update to a new edition? Then...
               | don't. The old ones are maintained.
        
       | Luker88 wrote:
       | Wonderful, but still disappointed that easy strict-type-wrapping
       | is not a thing yet.
       | 
       | There have been a few RFC trying to work on deriving a type from
       | another, and while I agree it's much more complex than it sounds,
       | I also find it's a huge missing point.
       | 
       | If I have to reimplement a wrapper myself for all Traits, I most
       | likely won't bother, leading to less typesafety, leading to more
       | bugs :(
        
       | pjmlp wrote:
       | Finally here! Congratulations to everyone.
        
       | yakubin wrote:
       | I'm eagerly awaiting the Cargo feature "named profiles"[1]. It's
       | already merged, but not yet announced to be planned for any
       | specific Cargo version. It will allow users to create custom
       | profiles with different build parameters from the standard ones,
       | so you can e.g. create a "profiling" profile which is based on
       | the "release" profile, so that it has all the nice optimizations,
       | but with debug information included, so that it works well with
       | _cargo-flamegraph_ :                 [profile.profiling]
       | inherits = "release"       debug = true
       | 
       | [1]: <https://github.com/rust-lang/cargo/pull/9943>
       | 
       | And then there's the less fireworky, but still appreciated,
       | _Iterator::map_while_ [2], which is going to be in Rust 1.57.
       | 
       | [2]: <https://github.com/rust-lang/rust/pull/89086>
        
         | steveklabnik wrote:
         | Unless something is special about this feature, new features
         | generally aren't "planned" for specific versions in general.
         | Since this landed two weeks ago, that means that it should land
         | in the beta version of Cargo once that branches for this
         | release (I didn't check if it has yet or not), which would
         | place it to be stable in the next release of Rust, 1.57.0.
        
           | yakubin wrote:
           | Thanks for the clarification. I just went by what's specified
           | in the sidebar on GitHub in the "Milestone" section.
        
             | steveklabnik wrote:
             | Any time. Cargo doesn't use the Milestone feature of GitHub
             | at all, so that's why that's empty :)
        
       | nynx wrote:
       | Woot woot, transmute is const now
        
         | orra wrote:
         | Curious what the applications are. Collections? Would you write
         | a lot of "unsafe" const code, given the chance?
        
           | brink wrote:
           | It's useful for handling data that came from outside Rust.
           | 
           | If you have a byte array that you've received over a network
           | connection that represents an array of floats, or you need to
           | convert a 32bit RGBA pixel buffer that you got from some
           | clang ffi binding to a byte pixel buffer without having to
           | split/copy to a new vector.
        
           | kzrdude wrote:
           | Happy that the const subset of the language grows
        
           | luizfelberti wrote:
           | I will shamefully admit to using transmute in very sinful
           | ways, such as having enums that are repr(u16) or something
           | like that at multiple numeric ranges such as:
           | #[repr(u16)]         enum Foo { A = 0, B }
           | #[repr(u16)]         enum Bar { A = 3200, B }
           | struct FooOrBar(u16);
           | 
           | And then proceeding to violate all of the unwritten rules of
           | Rust by wrangling casts across these types like a goddamn
           | wizard
           | 
           | I'm not proud of this...
        
             | lilyball wrote:
             | This sounds like a great example of where you might want a
             | union (https://doc.rust-
             | lang.org/1.56.0/reference/items/unions.html)
        
               | luizfelberti wrote:
               | Ooh I forgot the language had those!
               | 
               | I still feel like this trick has it's place though, as an
               | example take a look at where I stole this trick from, by
               | matklad [0] and tell me what you think :)
               | 
               | [0] https://github.com/rust-
               | analyzer/rowan/blob/d2c7843858da9d9e...
        
           | nynx wrote:
           | I can't think of an example now, but it has come up before
           | when working on collections and other things.
        
           | steveklabnik wrote:
           | One thing that's come up a couple times are... well, what
           | transmute is, that is, two types that have the same
           | representation, and you want to cast between them. For
           | example, the "try Rust out in the Linux kernel" code has a
           | function that turns a byte slice into a &Cstr via a
           | transmute. Those kinds of conversions can be useful inside of
           | const fns.
        
             | ishanjain28 wrote:
             | Hi Steve,
             | 
             | I came across this post which presents an example using
             | rust's transmute and it's incorrect behavior when the
             | alignment is different.
             | https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-
             | ru...
             | 
             | Is this issue still present? I tried to figure it out the
             | other day using latest rust's nightly but the llvm ir
             | output has so much going on that I didn't _really_
             | understand what was going on
        
               | steveklabnik wrote:
               | I am unsure about the specific details about IR that's
               | emitted (though at first glance it seems we do emit the
               | alignment attribute now, I think?), but transmute is, as
               | the documentation says, "incredibly" unsafe:
               | 
               | > Because transmute is a by-value operation, alignment of
               | the transmuted values themselves is not a concern. As
               | with any other function, the compiler already ensures
               | both T and U are properly aligned. However, when
               | transmuting values that point elsewhere (such as
               | pointers, references, boxes...), the caller has to ensure
               | proper alignment of the pointed-to values.
               | 
               | This code is doing the latter incorrectly, and therefore
               | invokes UB, as far as I can tell. To be honest, I don't
               | use transmute very often and so I don't have every single
               | last corner case about it memorized.
               | 
               | It's not so much an "issue" as it is "Here's an API
               | that's extremely sharp in Rust, and a similar, but less
               | sharp API in Zig."
        
               | MaulingMonkey wrote:
               | Per transmute's docs @ https://doc.rust-
               | lang.org/std/mem/fn.transmute.html:
               | 
               | > Because transmute is a by-value operation, alignment of
               | the transmuted values themselves is not a concern. As
               | with any other function, the compiler already ensures
               | both T and U are properly aligned. However, when
               | transmuting values that point elsewhere (such as
               | pointers, references, boxes...), the caller has to ensure
               | proper alignment of the pointed-to values.
               | 
               | The post you've linked transmutes a _reference_ , and as
               | the caller fails to explicitly ensure proper alignment,
               | it explicitly risks invoking undefined behavior - I would
               | consider the code buggy. The easiest way to prove it's
               | broken would be to create an reference that's more likely
               | to be unaligned (&array[1] instead of &array[0]?) and run
               | the code on a less misalignment-tolerant platform (ARM?).
               | 
               | Here are some 100% sound alternatives using bytemuck (no
               | unsafe required!) and core::ptr::{read,write}_unaligned
               | (unsafe required):
               | 
               | https://play.rust-
               | lang.org/?version=stable&mode=debug&editio...
        
               | jarpadat wrote:
               | That discussion is a bit strange. In that example Foo is
               | implicitly #[repr(Rust)] meaning it has an undefined
               | layout. In particular, a,b is unordered, and even if you
               | don't care which order you get, there is the question of
               | padding (a reasonable compiler will tightly pack a,b but
               | that's not required).
               | 
               | For this reason, we never reach the question of alignment
               | because we know neither i32, u8, nor any other type has
               | the same layout as Foo (undefined layout).
               | 
               | It is certainly true that unsafe Rust is _veeeeery_
               | unsafe, as perhaps evidenced by me being the first person
               | to point out the repr issue. On the other hand this
               | scheme has a lot of advantages for writing safe Rust.
        
       | jjice wrote:
       | Really excited for the reserved prefixes. Lots of possibilities
       | there. I'm really rooting for f-strings to stream line format!
       | calls.
        
       | mbStavola wrote:
       | I'm so excited to finally have disjoint captures in closures;
       | many papercuts on that one when I worked heavily with Amethyst a
       | while back as there were a few closure-based APIs.
       | 
       | Thanks to all the contributors for getting us to the 2021
       | edition!
        
         | k__ wrote:
         | That's the stuff Rust needs more of!
        
       | dthul wrote:
       | Love the 2021 edition changes and also the fact that they are so
       | minor!
        
       | nayuki wrote:
       | I'm confused about the bullet point "IntoIterator for arrays". I
       | thought this was added already in Rust 1.53.0. Did something else
       | happen?
       | 
       | See https://blog.rust-
       | lang.org/2021/06/17/Rust-1.53.0.html#whats...
        
         | steveklabnik wrote:
         | There's an explanation at the bottom of the section; this
         | landed as a hack in previous editions, but works via the normal
         | mechanisms in Rust 2021.
         | 
         | "Since this special case for .into_iter() is only required to
         | avoid breaking existing code, it is removed in the new edition,
         | Rust 2021, which will be released later this year."
         | 
         | As a user, you're right that there's not really an external-
         | facing change here.
        
         | davisoneee wrote:
         | To follow Steve's comment:
         | 
         | > Until Rust 1.53, only references to arrays implement
         | IntoIterator. This means you can iterate over &[1, 2, 3] and
         | &mut [1, 2, 3], but not over [1, 2, 3] directly.
         | 
         | ...now, you can also iterate over [1, 2, 3] etc.
         | 
         | https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterat...
        
           | steveklabnik wrote:
           | Right, but the point is that you can do that as of 1.53.0,
           | you didn't have to wait until this release and the edition to
           | do it.
        
             | tialaramex wrote:
             | You know all this, but while _some_ obvious things work in
             | 1.53.0 one important thing causes scary warnings because it
             | is shadowed by the back compat hack.
             | 
             | "for x in myArray" works fine, just like "for x in
             | myVector" but whereas "myVector.into_iter().foo()" does
             | what you expect, "myArray.into_iter().foo() is actually
             | giving foo an iterator over the references just as it would
             | have in 2017 and now produces a warning about this into the
             | bargain.
             | 
             | In Rust 2021 myArray.into_iter() does what a modern Rust
             | programmer expects it to do, provide an iterator over
             | myArray itself.
             | 
             | The warning does explain how you can get that iterator in
             | 1.53.0 of course, but you need to write some ugly syntax
             | whereas in Rust 2021 the obvious syntax just does what you
             | expect as if arrays had always been IntoIterator.
        
       ___________________________________________________________________
       (page generated 2021-10-21 23:01 UTC)