Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Rust 1.36 Stabilizes Futures, Backports Non-Lexical Lifetimes, and More

Rust 1.36 Stabilizes Futures, Backports Non-Lexical Lifetimes, and More

This item in japanese

Following its roadmap to Rust 2018, Rust 1.36's most awaited new feature is support for the Future trait, which is the first step towards bringing async/await to the language. Additionally, it backports non-lexical lifetimes (NLL) to improve the borrow checker, and introduces a new alloc crate to enable the creation of memory allocation-dependent libraries that do not require std.

Futures are supported in Rust through the Future trait, whose core method, poll, attempts to resolve the future. In case the final value is not yet ready, poll will suspend the current task and wake it at a later time when it can poll again. The polling task can specify a Waker, which the Future will use to wake it up. A Future should never be polled after it resolved. This may produce panic, block indefinitely the calling task, or other kind of problems. Significantly, though, poll is a safe method and its implementation shall guarantee it does not corrupt memory under any conditions.

Non-lexical lifetimes, introduced in Rust 1.31 (Rust 2018), can now be used with Rust 2015 as well. With NLL supported in Rust 2015, the old borrow checker is closer to be removed from the language. To make this a safe transition, the new borrow checker will emit warnings wherever it encounters code that is accepted by the old borrow checker but not legal anymore when using the new one. Non-lexical lifetimes are a major improvement to the Rust borrow checker by making it take into account the actual lifetime of a variable without necessarily binding it to its lexical scope.

Another new stable feature in Rust 1.36 is the alloc crate, which is the result of factoring the global memory allocator and all types depending on it out of the std crate. Consequently, std imports all of those types from alloc and re-exports them to preserve compatibility. Likewise, any library crate that requires memory allocation can import alloc directly and do not add a dependency on std, which is quite a large crate and not necessarily available for all environments, e.g., embedded systems. This is an important step, says the Rust team, to make it possible to create a larger ecosystem of #![no_std] libraries. It is important to notice that alloc support has been stabilized only for library crates, meaning #![no_std] binaries will still require nightly Rust to be allowed to use alloc. To sum this up, you can create a #![no_std] library that depends on the global memory allocator by using:


extern crate alloc;

Rust 1.36 is also paving to way to removing mem::uninitialized, which is now considered too dangerous to be left in the language, and replace its uses with the safer MaybeUninit<T>. Until now, mem::uninitialized was used to bypass Rust initialization checks to implement lazy allocation. The only catch is its use irremediably breaks Rust safety, since the compiler assumes those values are correctly initialized. The new MaybeUninit<T> type will support the same kind of behaviour but it will require the programmer to explicitly express its intention of using the value, hopefully after correct initialization, by using .assume_init().

As a final note, Rust 1.36 sports a new implementation of HashMap<K,V> that is faster on average and has lower memory overhead thanks to its use of the SwissTable design.

Rate this Article