Latest in branch 1.65
1.65.0
Released 03 Nov 2022
(3 years ago)
SoftwareRust
Version1.65
Initial release1.65.0
03 Nov 2022
(3 years ago)
Latest release1.65.0
03 Nov 2022
(3 years ago)
Support status16 Dec 2022
(Ended 3 years, 5 months ago)
Release noteshttps://github.com/rust-lang/rust/releases/tag/1.65.0
Source codehttps://github.com/rust-lang/rust/tree/1.65.0
Downloadhttps://github.com/rust-lang/rust/releases/tag/1.65.0
Rust 1.65 ReleasesView full list

What Is New in Rust 1.65

Category Highlights
New Features Generic Associated Types (GATs), let-else statements, break from labeled blocks, split DWARF debuginfo on Linux
Improvements MIR inlining (3-10% faster compile times), Cargo job-queue sorting, const Backtrace API, const pointer offset_from
Deprecations RLS removed; a small LSP server now warns and points users to rust-analyzer
Breaking Changes Removal of RLS may require IDE configuration updates; new split-debuginfo flag changes default debug layout on Linux

How do Generic Associated Types (GATs) change trait design in Rust 1.65?

Generic Associated Types let you parameterize associated types with lifetimes, type, or const generics, enabling more expressive trait APIs.

In practice, GATs allow patterns such as borrowing iterators, pointer families, and array borrowing without resorting to work-arounds.

trait LendingIterator {
    type Item<'a> where Self: 'a;
    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}

This matters if you maintain libraries that expose iterator-like abstractions over borrowed data; you can now encode the lifetime relationship directly in the trait.

What is the new let-else statement and when should I use it?

The let-else statement lets you bind a pattern and immediately diverge if the pattern does not match.

It replaces repetitive match or if-let chains, keeping the binding scope clean.

let (Some(count_str), Some(item)) = (it.next(), it.next()) else {
    panic!("invalid input");
};

Use it when you need early exit on a failed pattern match, such as parsing command-line arguments or deserializing simple formats.

How can I break out of a labeled block without using a loop?

Rust 1.65 introduces labeled break statements for ordinary block expressions, allowing early exit with an optional value.

This provides a structured alternative to the "loop-once" idiom.

let result = 'block: {
    do_thing();
    if condition_not_met() {
        break 'block 1;
    }
    do_next_thing();
    3
};

Watch out for nested blocks; the label must refer to the immediate block you intend to exit.

How does split DWARF debug info improve Linux build times?

Split DWARF separates debug symbols into distinct .dwo files (or a single .dwp package), allowing the linker to skip them during normal builds.

This can noticeably reduce link times, especially for large crates with extensive debug information.

Use -Csplit-debuginfo=unpacked for separate .dwo files or -Csplit-debuginfo=packed for a .dwp package; the default remains -Csplit-debuginfo=off.

Most teams will enable the packed mode in CI to keep artifact sizes small while still having full debug data available on demand.

What performance and tooling improvements arrived in Rust 1.65?

Rust 1.65 brings several under-the-hood enhancements that reduce compile time and improve ergonomics.

  • MIR inlining is now on for optimized builds, shaving 3-10% off real-world compile times.
  • Cargo now sorts pending jobs before scheduling, leading to more predictable parallel builds.
  • The Backtrace API is const-compatible, so you can capture backtraces in const contexts.
  • Pointer offset_from methods are also const, enabling compile-time pointer arithmetic.

In practice, these changes mean faster CI pipelines and the ability to embed richer error information without runtime overhead.

Frequently Asked Questions

Does Rust 1.65 require any changes to existing Cargo.toml files?
No, Cargo.toml syntax remains unchanged and most projects will compile without modifications.

Can I use let-else in a const function?
Yes, let-else works in const contexts as long as the else block diverges with a const panic or return.

How do I enable split DWARF on Linux?
Pass -Csplit-debuginfo=packed or -Csplit-debuginfo=unpacked to rustc or set RUSTFLAGS accordingly.

Is the new break 'label syntax compatible with older Rust versions?
No, it was stabilized in 1.65, so older compilers will reject it.

What is a simple code example of using a Generic Associated Type?
trait PointerFamily { type Pointer: Deref; fn new(value: T) -> Self::Pointer; }.

Will removing RLS affect my IDE integration?
Most IDEs now recommend rust-analyzer, so you may need to switch the LSP server configuration.

Releases In Branch 1.65

VersionRelease date
1.65.003 Nov 2022
(3 years ago)