Rust 1.17 removes redundant static lifetime annotations
References in constants and statics can use an implicit static lifetime. The change shortens declarations without changing the lifetime they promise, alongside field initialization shorthand and clearer ownership diagnostics.
A reference in a constant declaration often spells out a lifetime that the context has already determined. Nested declarations repeat it at each reference, making a table of fixed strings look more complicated than its data. Rust 1.17 lets these declarations omit the explicit static lifetime while preserving the same lifetime requirement.
The April 27 announcement demonstrates the shorter spelling for both constants and statics. Its stabilization patch shows the implementation change, replacing a feature-gated static default with the accepted rule and removing the feature attribute from tests. The change is about an implied lifetime in a particular declaration context, not a general permission to omit every lifetime annotation.
I find the explicit lifetime model in Rust valuable when it explains a relationship the reader needs to understand. Repeating a fixed answer where no useful choice exists adds less information. This change removes that repetition while leaving the requirement on the referenced data intact.
A shorter declaration has the same requirement
The announcement starts with a constant containing a string reference. Before this change, the declaration writes the static lifetime explicitly. The new spelling leaves the reference type concise.
const NAME: &str = "Ferris";
static OTHER_NAME: &str = "Bors";
The declarations remain different kinds of items, but both use the new lifetime default. An omitted annotation is not a request for a runtime decision about how long the string survives. The context supplies the static requirement.
The improvement becomes clearer with nested references. For example, the announcement gives an array of string references behind another reference, where the older form repeats the static annotation at both levels. The equivalent shorter declaration keeps the shape of the data visible.
const NAMES: &[&str; 2] = &["Ferris", "Bors"];
The array length and the distinction between the array reference and its string elements remain present. Removing the repeated lifetime does not erase those type details. It lets the part that varies between declarations receive more attention than a lifetime already fixed by the context.
The stabilization patch also preserves tests involving cases where lifetime elision does not supply every relationship. That boundary matters because function references and other nested types may describe relationships beyond a single static reference. The rule is a specific default, not a new lifetime inference system for arbitrary APIs.
Field initialization removes another repetition
Rust 1.17 adds field initialization shorthand. When a local variable has the same name as the destination structure field, the programmer can write that name once. The announcement compares Point { x: x, y: y } with Point { x, y }.
struct Point {
x: i32,
y: i32,
}
fn point(x: i32, y: i32) -> Point {
Point { x, y }
}
The field names still state where the values go. Local names still have to resolve in the surrounding scope. The shorter form removes a duplicated token in the common same-name case, while the explicit field-to-expression form remains useful when names differ or values require computation.
These two changes share a limited purpose. They remove repeated information without hiding an important policy decision. An implicit static lifetime in the relevant item context has a fixed meaning, while a shorthand field initializer has an existing local binding to identify its value.
I like these changes because they reduce the visual cost of ordinary code without making an unfamiliar abstraction necessary. The data structure and ownership rules remain the things a reader needs to understand. A shorter initializer does not become an alternative object model.
Diagnostics explain why ownership matters
The release also improves the error for adding two string slices. Its example explains that String + &str works while &str + &str does not. The new diagnostic recommends obtaining an owned string on the left and explains that appending may require reallocation.
That explanation is more useful than a generic suggestion that an Add implementation might be missing. It connects the rejected expression to the ownership requirement. The programmer needs storage that can accept the appended contents, and a borrowed string slice does not by itself provide that owned destination.
This makes the diagnostic part of teaching the language model. The compiler still rejects the unsupported operation, but it supplies a reason tied to the operation the programmer intended. It does not make concatenation succeed through an implicit allocation whose ownership is hidden from the source.
Cargo receives a related consistency improvement in its own domain. A build.rs file at the package root now follows the common convention for a build script without requiring the usual explicit declaration. The announcement notes an opt-out through build = false. A convention becomes a documented default while retaining a way to express a different intention.
The same release removes the old Makefile-based build system for Rust itself, leaving the Rust and Cargo-based system introduced earlier. It also restores local documentation installation by default after users discovered its absence while offline. These are practical changes to how people obtain and work with the language. The lifetime default fits within that broader effort by making a common declaration say only the information its context does not already supply.