-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stabilize let else
#93628
Stabilize let else
#93628
Conversation
r? @jackh726 (rust-highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
9c1b8d2
to
68d46b6
Compare
This comment has been minimized.
This comment has been minimized.
68d46b6
to
f0a8446
Compare
This looks good to me; I'll start a T-lang FCP. |
Shall we stabilize @rfcbot merge |
Team member @joshtriplett has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
This comment has been minimized.
This comment has been minimized.
@rfcbot concern not-while-rustfmt-breaks-on-it I remembered it not formatting last I tried using it in rustc, and sure enough it still seems to fail when I try it in playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=350415c3adb74101bbdc002031976b70 (There's enough people using rustfmt in CI that I think adding formatting support for it after stabilization would be impolite.) EDIT: "breaks" is not the word I should have used here. I meant "while rustfmt is unable to normalize formatting for the construct", since that's what I'd expect rustfmt to do for all stable syntax. |
It's not that rustfmt is "breaking" on it, but the formatting rules aren't established yet so rustfmt is just leaving whatever you wrote in place. You have trailing whitespace in your snippet, and rustfmt is just acknowledging the presence of what was originally written; it's not modifying what was already there/inserting trailing whitespace itself. |
I think that's my complaint. I think it's clear that we'd want rustfmt to format it, but based on https://rust-lang.github.io/rfcs/2437-rustfmt-stability.html it'd need to be a new version to add formatting support for it if we did so after stabilization. And I don't think that dance is worth it; it should just have formatting support in the release that stabilizes it. |
f0a8446
to
70a6fb4
Compare
That's not the case actually. rustfmt has always had leeway to make formatting changes for "new" syntax (we have to) until such time as the formatting has actually been stabilized. We try very hard to only do this once, which is why the "first do no harm" pattern followed for syntax that's new to rustfmt. I've never seen a case where stabilization of a feature was held up on rustfmt, and doing so would be a big mistake IMO. Throughout my time working on rustfmt it's often been an after thought where we weren't even aware of syntax changes until long after they'd been in use, and there's plenty of cases where rustfmt exhibits this same behavior on long-standing syntax (e.g. try adding comments between trait bounds). I'd think that blocking feature stabilization on style guide + formatting stabilization would either greatly elongate the lead time for feature availability on stable, or create large amounts of friction on the rustfmt side between expediency (not wanting to block) and formatting stability + quality/correctness. Also, and I say this as someone that spends a large chunk of my free time trying to maintain and improve rustfmt 😄, there's a non-zero subset of the Rust population that dislikes rustfmt and doesn't use it whatsoever. If I were one of those folks I think it would be extremely frustrating to not have access to a language feature on stable simply because of an optional tool I don't leverage. |
This comment has been minimized.
This comment has been minimized.
🎉 the stabilization PR has been merged 🎉 Getting let else into the language was very much a team effort, and I would like to thank everyone who was involved in their introduction and stabilization. In particular I would like to thank: Authors of the RFCs 1303 and 3137: PR authors for the implementation in the compiler: @camsteffen (lowering, tests) @compiler-errors (diagnostics, ICE fixes) @cormacrelf (initial implementation, lowering, tests) @dingxiangfei2009 (lowering, tests) @est31 (stabilization, diagnostics, tests) @JohnTitor (ICE fixes) Reviewers of those PRs: @cjgillot @petrochenkov @nagisa @matthewjasper @oli-obk @Mark-Simulacrum @pnkfelix @joshtriplett @jackh726 Everyone who tested out let-else, filed issues/bug reports, provided guidance and feedback in the RFCs, PRs and issues, including team members who approved FCPs. |
… r=petrochenkov Show let-else suggestion on stable. The E0005 error message has a suggestion to use let-else. Now that let-else is stabilized, I think this message should be included on non-nightly toolchains. I suspect this was just an oversight from rust-lang#93628. [`E0005.stderr`](https://github.com/ehuss/rust/blob/be1c7aad723126b2ea65543b4ceed54167b841a2/src/test/ui/error-codes/E0005.stderr#L22-L25) contains an example of what this suggestion looks like.
… r=petrochenkov Show let-else suggestion on stable. The E0005 error message has a suggestion to use let-else. Now that let-else is stabilized, I think this message should be included on non-nightly toolchains. I suspect this was just an oversight from rust-lang#93628. [`E0005.stderr`](https://github.com/ehuss/rust/blob/be1c7aad723126b2ea65543b4ceed54167b841a2/src/test/ui/error-codes/E0005.stderr#L22-L25) contains an example of what this suggestion looks like.
The `let_else` feature was stabilized by [rust-lang/rust#93628][1]. [1]: rust-lang/rust#93628
Pkgsrc changes: * We now manage to build for mipsel-unknown-netbsd, but despite the target spec saying cpu = "mips3", the compiler manages to emit 64-bit instructions which cause "illegal instruction" error. Will need more work. The mipsel-unknown-netbsd entry is commentd out since there is no 1.64.0 bootstrap. * Managed to retain the build of aarch64_be, llvm needed a patch to avoid use of neon instructions in the BE case (llvm doesn't support use of neon in BE mode). Ref. patch to src/llvm-project/llvm/lib/Support/BLAKE3/blake3_impl.h. * The minimum gcc version is now 7.x, and that includes the cross-compiler for the targets. For i386 this also needs to /usr/include/gcc-7 include files in the target root, because immintrin.h from gcc 5 is not compatible with gcc 7.x. This applies for the targets where we build against a root from netbsd-8 (sparc64, powerpc, i386), and files/gcc-wrap gets a hack for this. * Pick up tweak for -latomic inclusion from rust-lang/rust#104220 and rust-lang/rust#104572 * Retain ability to do 32-bit NetBSD, by changing from 64 to 32 bit types in library/std/src/sys/unix/thread_parker/netbsd.rs. * I've struggled a bit to get the "openssl-src" build with -latomic where it's needed. I introduce "NetBSD-generic32" system type and use it for the NetBSD mipsel target. There is another attempt to do the same in the patch to vendor/openssl-sys/build/main.rs. * Bump bootstraps to 1.64.0, checksum updates. Upstream changes: Version 1.65.0 (2022-11-03) ========================== Language -------- - [Error on `as` casts of enums with `#[non_exhaustive]` variants] (rust-lang/rust#92744) - [Stabilize `let else`](rust-lang/rust#93628) - [Stabilize generic associated types (GATs)] (rust-lang/rust#96709) - [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy] (rust-lang/rust#97739) - [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")] (rust-lang/rust#99332) - [Uninitialized integers, floats, and raw pointers are now considered immediate UB](rust-lang/rust#98919). Usage of `MaybeUninit` is the correct way to work with uninitialized memory. - [Stabilize raw-dylib for Windows x86_64, aarch64, and thumbv7a] (rust-lang/rust#99916) - [Do not allow `Drop` impl on foreign ADTs] (rust-lang/rust#99576) Compiler -------- - [Stabilize -Csplit-debuginfo on Linux] (rust-lang/rust#98051) - [Use niche-filling optimization even when multiple variants have data] (rust-lang/rust#94075) - [Associated type projections are now verified to be well-formed prior to resolving the underlying type] (rust-lang/rust#99217) - [Stringify non-shorthand visibility correctly] (rust-lang/rust#100350) - [Normalize struct field types when unsizing] (rust-lang/rust#101831) - [Update to LLVM 15](rust-lang/rust#99464) - [Fix aarch64 call abi to correctly zeroext when needed] (rust-lang/rust#97800) - [debuginfo: Generalize C++-like encoding for enums] (rust-lang/rust#98393) - [Add `special_module_name` lint] (rust-lang/rust#94467) - [Add support for generating unique profraw files by default when using `-C instrument-coverage`] (rust-lang/rust#100384) - [Allow dynamic linking for iOS/tvOS targets] (rust-lang/rust#100636) New targets: - [Add armv4t-none-eabi as a tier 3 target] (rust-lang/rust#100244) - [Add powerpc64-unknown-openbsd and riscv64-unknown-openbsd as tier 3 targets] (rust-lang/rust#101025) - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Don't generate `PartialEq::ne` in derive(PartialEq)] (rust-lang/rust#98655) - [Windows RNG: Use `BCRYPT_RNG_ALG_HANDLE` by default] (rust-lang/rust#101325) - [Forbid mixing `System` with direct system allocator calls] (rust-lang/rust#101394) - [Document no support for writing to non-blocking stdio/stderr] (rust-lang/rust#101416) - [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`](rust-lang/rust#95295) This also changes the safety conditions on `Layout::from_size_align_unchecked`. Stabilized APIs --------------- - [`std::backtrace::Backtrace`] (https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html) - [`Bound::as_ref`] (https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.as_ref) - [`std::io::read_to_string`] (https://doc.rust-lang.org/stable/std/io/fn.read_to_string.html) - [`<*const T>::cast_mut`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_mut) - [`<*mut T>::cast_const`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_const) These APIs are now stable in const contexts: - [`<*const T>::offset_from`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) - [`<*mut T>::offset_from`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) Cargo ----- - [Apply GitHub fast path even for partial hashes] (rust-lang/cargo#10807) - [Do not add home bin path to PATH if it's already there] (rust-lang/cargo#11023) - [Take priority into account within the pending queue] (rust-lang/cargo#11032). This slightly optimizes job scheduling by Cargo, with typically small improvements on larger crate graph builds. Compatibility Notes ------------------- - [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`] (rust-lang/rust#95295). This also changes the safety conditions on `Layout::from_size_align_unchecked`. - [`PollFn` now only implements `Unpin` if the closure is `Unpin`] (rust-lang/rust#102737). This is a possible breaking change if users were relying on the blanket unpin implementation. See discussion on the PR for details of why this change was made. - [Drop ExactSizeIterator impl from std::char::EscapeAscii] (rust-lang/rust#99880) This is a backwards-incompatible change to the standard library's surface area, but is unlikely to affect real world usage. - [Do not consider a single repeated lifetime eligible for elision in the return type] (rust-lang/rust#103450) This behavior was unintentionally changed in 1.64.0, and this release reverts that change by making this an error again. - [Reenable disabled early syntax gates as future-incompatibility lints] (rust-lang/rust#99935) - [Update the minimum external LLVM to 13] (rust-lang/rust#100460) - [Don't duplicate file descriptors into stdio fds] (rust-lang/rust#101426) - [Sunset RLS](rust-lang/rust#100863) - [Deny usage of `#![cfg_attr(..., crate_type = ...)]` to set the crate type] (rust-lang/rust#99784) This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny. - [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches] (rust-lang/rust#101072) This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM. Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Add `x.sh` and `x.ps1` shell scripts] (rust-lang/rust#99992) - [compiletest: use target cfg instead of hard-coded tables] (rust-lang/rust#100260) - [Use object instead of LLVM for reading bitcode from rlibs] (rust-lang/rust#98100) - [Enable MIR inlining for optimized compilations] (rust-lang/rust#91743) This provides a 3-10% improvement in compiletimes for real world crates. See [perf results] (https://perf.rust-lang.org/compare.html?start=aedf78e56b2279cc869962feac5153b6ba7001ed&end=0075bb4fad68e64b6d1be06bf2db366c30bc75e1&stat=instructions:u).
… r=petrochenkov Show let-else suggestion on stable. The E0005 error message has a suggestion to use let-else. Now that let-else is stabilized, I think this message should be included on non-nightly toolchains. I suspect this was just an oversight from rust-lang#93628. [`E0005.stderr`](https://github.com/ehuss/rust/blob/be1c7aad723126b2ea65543b4ceed54167b841a2/src/test/ui/error-codes/E0005.stderr#L22-L25) contains an example of what this suggestion looks like.
Pkgsrc changes: * pkglint cleanups, bump bootstrap kits to 1.65.0. * New target: mipsel-unknown-netbsd, for cpu=mips32 with soft-float. * Managed to retain the build of aarch64_be, llvm needed a patch to avoid use of neon instructions in the BE case (llvm doesn't support use of neon in BE mode). Ref. patch to src/llvm-project/llvm/lib/Support/BLAKE3/blake3_impl.h. Also submitted upstream of LLVM to the BLAKE3 maintainers. * The minimum gcc version is now 7.x, and that includes the cross-compiler for the targets. For i386 this also needs to /usr/include/gcc-7 include files in the target root, because immintrin.h from gcc 5 is not compatible with gcc 7.x. This applies for the targets where we build against a root from netbsd-8 (sparc64, powerpc, i386), and files/gcc-wrap gets a hack for this. * Pick up tweak for -latomic inclusion from rust-lang/rust#104220 and rust-lang/rust#104572 * Retain ability to do 32-bit NetBSD, by changing from 64 to 32 bit types in library/std/src/sys/unix/thread_parker/netbsd.rs. * I've tried to get the "openssl-src" build with -latomic where it's needed. I've introduced the "NetBSD-generic32" system type and use it for the NetBSD mipsel target. There is another attempt to do the same in the patch to vendor/openssl-sys/build/main.rs. Upstream changes: Version 1.66.1 (2023-01-10) =========================== - Added validation of SSH host keys for git URLs in Cargo ([CVE-2022-46176](https://www.cve.org/CVERecord?id=CVE-2022-46176)) Version 1.66.0 (2022-12-15) =========================== Language -------- - [Permit specifying explicit discriminants on all `repr(Int)` enums](rust-lang/rust#95710) ```rust #[repr(u8)] enum Foo { A(u8) = 0, B(i8) = 1, C(bool) = 42, } ``` - [Allow transmutes between the same type differing only in lifetimes](rust-lang/rust#101520) - [Change constant evaluation errors from a deny-by-default lint to a hard error](rust-lang/rust#102091) - [Trigger `must_use` on `impl Trait` for supertraits](rust-lang/rust#102287) This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`. - [Allow `..X` and `..=X` in patterns](rust-lang/rust#102275) - [Uplift `clippy::for_loops_over_fallibles` lint into rustc](rust-lang/rust#99696) - [Stabilize `sym` operands in inline assembly](rust-lang/rust#103168) - [Update to Unicode 15](rust-lang/rust#101912) - [Opaque types no longer imply lifetime bounds](rust-lang/rust#95474) This is a soundness fix which may break code that was erroneously relying on this behavior. Compiler -------- - [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](rust-lang/rust#101329) - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. - [Add support for linking against macOS universal libraries](rust-lang/rust#98736) Libraries --------- - [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](rust-lang/rust#101040) - [Update to Unicode 15](rust-lang/rust#101821) Stabilized APIs --------------- - [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text) - [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed) - [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned) - [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned) - [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first) - [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value) - [Add `AsFd` implementations for stdio lock types on WASI.](rust-lang/rust#101768) - [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E) - [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html) - [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32) - [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip) - [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html) Rustdoc ------- - [Add Rustdoc warning for invalid HTML tags in the documentation](rust-lang/rust#101720) Cargo ----- - [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html) - [`cargo publish` now waits for the new version to be downloadable before exiting](rust-lang/cargo#11062) See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more. Compatibility Notes ------------------- - [Only apply `ProceduralMasquerade` hack to older versions of `rental`](rust-lang/rust#94063) - [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](rust-lang/rust#102385) - [Don't export `__wasm_init_memory` on WebAssembly.](rust-lang/rust#102426) - [Only export `__tls_*` on wasm32-unknown-unknown.](rust-lang/rust#102440) - [Don't link to `libresolv` in libstd on Darwin](rust-lang/rust#102766) - [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](rust-lang/rust#103277) - [Opaque types no longer imply lifetime bounds](rust-lang/rust#95474) This is a soundness fix which may break code that was erroneously relying on this behavior. - [Make `order_dependent_trait_objects` show up in future-breakage reports](rust-lang/rust#102635) - [Change std::process::Command spawning to default to inheriting the parent's signal mask](rust-lang/rust#101077) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Enable BOLT for LLVM compilation](rust-lang/rust#94381) - [Enable LTO for rustc_driver.so](rust-lang/rust#101403) Version 1.65.0 (2022-11-03) ========================== Language -------- - [Error on `as` casts of enums with `#[non_exhaustive]` variants] (rust-lang/rust#92744) - [Stabilize `let else`](rust-lang/rust#93628) - [Stabilize generic associated types (GATs)] (rust-lang/rust#96709) - [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy] (rust-lang/rust#97739) - [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")] (rust-lang/rust#99332) - [Uninitialized integers, floats, and raw pointers are now considered immediate UB](rust-lang/rust#98919). Usage of `MaybeUninit` is the correct way to work with uninitialized memory. - [Stabilize raw-dylib for Windows x86_64, aarch64, and thumbv7a] (rust-lang/rust#99916) - [Do not allow `Drop` impl on foreign ADTs] (rust-lang/rust#99576) Compiler -------- - [Stabilize -Csplit-debuginfo on Linux] (rust-lang/rust#98051) - [Use niche-filling optimization even when multiple variants have data] (rust-lang/rust#94075) - [Associated type projections are now verified to be well-formed prior to resolving the underlying type] (rust-lang/rust#99217) - [Stringify non-shorthand visibility correctly] (rust-lang/rust#100350) - [Normalize struct field types when unsizing] (rust-lang/rust#101831) - [Update to LLVM 15](rust-lang/rust#99464) - [Fix aarch64 call abi to correctly zeroext when needed] (rust-lang/rust#97800) - [debuginfo: Generalize C++-like encoding for enums] (rust-lang/rust#98393) - [Add `special_module_name` lint] (rust-lang/rust#94467) - [Add support for generating unique profraw files by default when using `-C instrument-coverage`] (rust-lang/rust#100384) - [Allow dynamic linking for iOS/tvOS targets] (rust-lang/rust#100636) New targets: - [Add armv4t-none-eabi as a tier 3 target] (rust-lang/rust#100244) - [Add powerpc64-unknown-openbsd and riscv64-unknown-openbsd as tier 3 targets] (rust-lang/rust#101025) - Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Don't generate `PartialEq::ne` in derive(PartialEq)] (rust-lang/rust#98655) - [Windows RNG: Use `BCRYPT_RNG_ALG_HANDLE` by default] (rust-lang/rust#101325) - [Forbid mixing `System` with direct system allocator calls] (rust-lang/rust#101394) - [Document no support for writing to non-blocking stdio/stderr] (rust-lang/rust#101416) - [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`](rust-lang/rust#95295) This also changes the safety conditions on `Layout::from_size_align_unchecked`. Stabilized APIs --------------- - [`std::backtrace::Backtrace`] (https://doc.rust-lang.org/stable/std/backtrace/struct.Backtrace.html) - [`Bound::as_ref`] (https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.as_ref) - [`std::io::read_to_string`] (https://doc.rust-lang.org/stable/std/io/fn.read_to_string.html) - [`<*const T>::cast_mut`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_mut) - [`<*mut T>::cast_const`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.cast_const) These APIs are now stable in const contexts: - [`<*const T>::offset_from`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) - [`<*mut T>::offset_from`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from) Cargo ----- - [Apply GitHub fast path even for partial hashes] (rust-lang/cargo#10807) - [Do not add home bin path to PATH if it's already there] (rust-lang/cargo#11023) - [Take priority into account within the pending queue] (rust-lang/cargo#11032). This slightly optimizes job scheduling by Cargo, with typically small improvements on larger crate graph builds. Compatibility Notes ------------------- - [`std::layout::Layout` size must not overflow `isize::MAX` when rounded up to `align`] (rust-lang/rust#95295). This also changes the safety conditions on `Layout::from_size_align_unchecked`. - [`PollFn` now only implements `Unpin` if the closure is `Unpin`] (rust-lang/rust#102737). This is a possible breaking change if users were relying on the blanket unpin implementation. See discussion on the PR for details of why this change was made. - [Drop ExactSizeIterator impl from std::char::EscapeAscii] (rust-lang/rust#99880) This is a backwards-incompatible change to the standard library's surface area, but is unlikely to affect real world usage. - [Do not consider a single repeated lifetime eligible for elision in the return type] (rust-lang/rust#103450) This behavior was unintentionally changed in 1.64.0, and this release reverts that change by making this an error again. - [Reenable disabled early syntax gates as future-incompatibility lints] (rust-lang/rust#99935) - [Update the minimum external LLVM to 13] (rust-lang/rust#100460) - [Don't duplicate file descriptors into stdio fds] (rust-lang/rust#101426) - [Sunset RLS](rust-lang/rust#100863) - [Deny usage of `#![cfg_attr(..., crate_type = ...)]` to set the crate type] (rust-lang/rust#99784) This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny. - [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches] (rust-lang/rust#101072) This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM. Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Add `x.sh` and `x.ps1` shell scripts] (rust-lang/rust#99992) - [compiletest: use target cfg instead of hard-coded tables] (rust-lang/rust#100260) - [Use object instead of LLVM for reading bitcode from rlibs] (rust-lang/rust#98100) - [Enable MIR inlining for optimized compilations] (rust-lang/rust#91743) This provides a 3-10% improvement in compiletimes for real world crates. See [perf results] (https://perf.rust-lang.org/compare.html?start=aedf78e56b2279cc869962feac5153b6ba7001ed&end=0075bb4fad68e64b6d1be06bf2db366c30bc75e1&stat=instructions:u).
The `let else` feature was stabilized by [rust-lang/rust#93628][1] in Rust 1.65.0. [1]: rust-lang/rust#93628
The latest release of nanoserde has adopted the use of `let...else` statements, which were stabilized in Rust 1.65 via: rust-lang/rust#93628.
The latest release of nanoserde has adopted the use of `let...else` statements, which were stabilized in Rust 1.65 via: rust-lang/rust#93628.
The latest release of nanoserde has adopted the use of `let...else` statements, which were stabilized in Rust 1.65 via: rust-lang/rust#93628
The latest release of nanoserde has adopted the use of `let...else` statements, which were stabilized in Rust 1.65 via: rust-lang/rust#93628
* Confirmed following functionality with Air75: * Reading bootloader, hash matches other NuPhy products * Reading full-flash * Added Air75 part (another Air60 reference) * Added minimum Rust version (let-else not stabilized before Rust 1.65 w/ PR rust-lang/rust#93628)
* Confirmed following functionality with Air75: * Reading bootloader, hash matches other NuPhy products * Reading full-flash * Added Air75 part (another Air60 reference) * Added minimum Rust version (let-else not stabilized before Rust 1.65 w/ PR rust-lang/rust#93628)
🎉 Stabilizes the
let else
feature, added by RFC 3137. 🎉Reference PR: rust-lang/reference#1156
closes #87335 (
let else
tracking issue)FCP: #93628 (comment)
Stabilization report
Summary
The feature allows refutable patterns in
let
statements if the expression isfollowed by a diverging
else
:Differences from the RFC / Desugaring
Outside of desugaring I'm not aware of any differences between the implementation and the RFC. The chosen desugaring has been changed from the RFC's original. You can read a detailed discussion of the implementation history of it in @cormacrelf 's summary in this thread, as well as the followup. Since that followup, further changes have happened to the desugaring, in #98574, #99518, #99954. The later changes were mostly about the drop order: On match, temporaries drop in the same order as they would for a
let
declaration. On mismatch, temporaries drop before theelse
block.Test cases
In chronological order as they were merged.
Added by df9a2e0 (#87688):
ui/pattern/usefulness/top-level-alternation.rs
to ensure the unreachable pattern lint visits patterns insidelet else
.Added by 5b95df4 (#87688):
ui/let-else/let-else-bool-binop-init.rs
to ensure that no lazy boolean expressions (using&&
or||
) are allowed in the expression, as the RFC mandates.ui/let-else/let-else-brace-before-else.rs
to ensure that no}
directly preceding theelse
is allowed in the expression, as the RFC mandates.ui/let-else/let-else-check.rs
to ensure that#[allow(...)]
attributes added to the entirelet
statement apply for theelse
block.ui/let-else/let-else-irrefutable.rs
to ensure that theirrefutable_let_patterns
lint fires.ui/let-else/let-else-missing-semicolon.rs
to ensure the presence of semicolons at the end of thelet
statement.ui/let-else/let-else-non-diverging.rs
to ensure theelse
block diverges.ui/let-else/let-else-run-pass.rs
to ensure the feature works in some simple test case settings.ui/let-else/let-else-scope.rs
to ensure the bindings created by the outerlet
expression are not available in theelse
block of it.Added by bf7c32a (#89965):
ui/let-else/issue-89960.rs
as a regression test for the ICE-on-error bug Erroneous 'ref mut' in let-else binding causes ICE #89960 . Later in 102b912 this got removed in favour of more comprehensive tests.Added by 8565419 (#89974):
ui/let-else/let-else-if.rs
to test for the improved error message that points out thatlet else if
is not possible.Added by 9b45713:
ui/let-else/let-else-allow-unused.rs
as a regression test for let-else: linting forunused
bindings is not handled correctly #89807, to ensure that#[allow(...)]
attributes added to the entirelet
statement apply for bindings created by thelet else
pattern.Added by 61bcd8d (#89841):
ui/let-else/let-else-non-copy.rs
to ensure that a copy is performed out of non-copy wrapper types. This mirrorsif let
behaviour. The test case bases on rustc internal changes originally meant for Adopt let_else across the compiler #89933 but then removed from the PR due to the error prior to the improvements of Implement let-else type annotations natively #89841.ui/let-else/let-else-source-expr-nomove-pass.rs
to ensure that while there is a move of the binding in the successful case, theelse
case can still access the non-matching value. This mirrorsif let
behaviour.Added by 102b912 (#89841):
ui/let-else/let-else-ref-bindings.rs
andui/let-else/let-else-ref-bindings-pass.rs
to checkref
andref mut
keywords in the pattern work correctly and error when needed.Added by 2715c5f (#89841):
rfc2005
test suite.Added by fec8a50 (#89841):
ui/let-else/let-else-deref-coercion-annotated.rs
andui/let-else/let-else-deref-coercion.rs
to check deref coercions.Added since this stabilization report was originally written (2022-02-09)
Added by 76ea566 (#94211):
ui/let-else/let-else-destructuring.rs
to give a nice error message if an user tries to do an assignment with a (possibly refutable) pattern and anelse
block, like asked for in destructuring assignment and let else #93995.Added by e7730dc (#94208):
ui/let-else/let-else-allow-in-expr.rs
to test whether#[allow(unused_variables)]
works in the expr, as well as its non presence, as well as putting it on the entirelet else
affects the expr, too. This was adding a missing test as pointed out by the stabilization report.ui/let-else/let-else-allow-unused.rs
andui/let-else/let-else-check.rs
to ensure that non-presence of#[allow(unused)]
does issue the unused lint. This was adding a missing test case as pointed out by the stabilization report.Added by 5bd7106 (#94208):
ui/let-else/let-else-slicing-error.rs
, a regression test for Wrong suggestion for slice patterns when using let-else statement #92069, which got fixed without addition of a regression test. This resolves a missing test as pointed out by the stabilization report.Added by 5374688 (#98574):
src/test/ui/async-await/async-await-let-else.rs
to test the interaction of async/await withlet else
Added by 6c529de (#98574):
src/test/ui/let-else/let-else-temporary-lifetime.rs
as a (partial) regression test for Let-else does not drop temporaries at the end of the statement #98672Added by 9b56640 (#99518):
src/test/ui/let-else/let-else-temp-borrowck.rs
as a regression test forlet_else
returns in surprising borrowck errors with impl trait #93951src/test/ui/let-else/let-else-temporary-lifetime.rs
to include a partial regression test for Let-else does not drop temporaries at the end of the statement #98672 (especially regardingelse
drop order)Added by baf9a7c (#99518):
src/test/ui/let-else/let-else-temporary-lifetime.rs
to include a partial regression test forlet_else
returns in surprising borrowck errors with impl trait #93951, similar tolet-else-temp-borrowck.rs
Added by 60be2de (#99518):
src/test/ui/let-else/let-else-temporary-lifetime.rs
to include a program that can now be compiled thanks to borrow checker implications of Let-else: break out scopes when a let-else pattern fails to match #99518Added by 47a7a91 (#100132):
src/test/ui/let-else/issue-100103.rs
, as a regression test for ICE trying to useErr(1)?
withlet_else
in atry
block #100103, to ensure that there is no ICE when doingErr(...)?
inside else blocks.Added by e3c5bd6 (#100443):
src/test/ui/let-else/let-else-then-diverge.rs
, to verify that there is no unreachable code error with the current desugaring.Added by 9818526 (#100443):
src/test/ui/let-else/issue-94176.rs
, to make sure that a correct span is emitted for a missing trailing expression error. Regression test for Missing trailing expression in block withlet else
yields incorrectly spanned error message #94176.Added by e182d12 (#100434):
let else
(this bug surfaced in many different ways)Added by e262856 (#99954):
src/test/ui/let-else/let-else-temporary-lifetime.rs
extended to contain & borrows as well, as this was identified as an earlier issue with the desugaring: Let-else does not drop temporaries at the end of the statement #98672 (comment)Added by 2d8460e (#99291):
src/test/ui/let-else/let-else-drop-order.rs
a matrix based test for various drop order behaviour oflet else
. Especially, it verifies equality oflet
andlet else
drop orders, resolving a stabilization blocker.Added by 1b87ce0 (#101410):
src/test/ui/let-else/let-else-temporary-lifetime.rs
to add the-Zvalidate-mir
flag, as a regression test for ICE: broken mir with let-else, -Zvalidate-mir #99228Added by af591eb (#101410):
src/test/ui/let-else/issue-99975.rs
as a regression test for the ICE Internal Compiler Error: Broken MIR in Item(...) Withlet_else
Usage #99975.Added by this PR:
ui/let-else/let-else.rs
, a simple run-pass check, similar toui/let-else/let-else-run-pass.rs
.Things not currently tested
The→ test added by e7730dc#[allow(...)]
tests check whether allow works, but they don't check whether the non-presence of allow causes a lint to fire.There is no→ test added by e7730dc#[allow(...)]
test for the expression, as there are tests for the pattern and the else block.→ test added by e7730dclet-else-brace-before-else.rs
forbids thelet ... = {} else {}
pattern and there is a rustfix to obtainlet ... = ({}) else {}
. I'm not sure whether the.fixed
files are checked by the tooling that they compile. But if there is no such check, it would be neat to make sure thatlet ... = ({}) else {}
compiles.Wrong suggestion for slice patterns when using let-else statement #92069 got closed as fixed, but no regression test was added. Not sure it's worth to add one.→ test added by 5bd7106consistency between→ test added by 2d8460elet else
andif let
regarding lifetimes and drop order: Stabilizelet else
#93628 (comment)Edit: they are all tested now.
Possible future work / Refutable destructuring assignments
RFC 2909 specifies destructuring assignment, allowing statements like
FooBar { a, b, c } = foo();
.As it was stabilized, destructuring assignment only allows irrefutable patterns, which before the advent of
let else
were the only patterns thatlet
supported.So the combination of
let else
and destructuring assignments gives reason to think about extensions of the destructuring assignments feature that allow refutable patterns, discussed in #93995.A naive mapping of
let else
to destructuring assignments in the form ofSome(v) = foo() else { ... };
might not be the ideal way.let else
needs a divergingelse
clause as it introduces new bindings, while assignments have a default behaviour to fall back to if the pattern does not match, in the form of not performing the assignment. Thus, there is no good case to require divergence, or even anelse
clause at all, beyond the need for having some introducer syntax so that it is clear to readers that the assignment is not a given (enums and structs look similar). There are better candidates for introducer syntax however than an emptyelse {}
clause, likemaybe
which could be added as a keyword on an edition boundary:Further design discussion is left to an RFC, or the linked issue.