What Is New in Rust 1.30
| Category | Highlights |
|---|---|
| New Features | Attribute-like and function-like procedural macros, macro import via use, raw identifiers, crate keyword in paths, #[panic_handler] for no_std, stable proc_macro crate. |
| Improvements | Unified module-system path resolution, visibility matching in macros, stable tool attributes, Iterator::find_map, new IP address constants. |
| Deprecations | trim_left/trim_right renamed to trim_start/trim_end (old names deprecated). |
How can I write custom attribute-like and function-like procedural macros in Rust 1.30?
Rust 1.30 adds stable support for attribute-like and function-like procedural macros, letting you generate code beyond #[derive].
These macros receive raw token streams and return generated code, enabling powerful DSLs and framework integrations.
- Attribute-like macro signature:
#[proc_macro_attribute] pub fn my_attr(attr: TokenStream, item: TokenStream) -> TokenStream { ... } - Function-like macro signature:
#[proc_macro] pub fn my_macro(input: TokenStream) -> TokenStream { ... }
Example usage in a web framework:
#[route(GET, "/")]
fn index() {
// handler body
}
Because the proc_macro crate is now stable, crates like syn and quote can be used without nightly features.
What changes were made to the module system and import paths in Rust 1.30?
Rust 1.30 unifies path resolution so that external crates are automatically in scope and the crate keyword can be used in any path.
Key adjustments:
- External crates no longer need a leading
::;serde_json::from_strworks from any module. - The
cratekeyword explicitly starts a path at the crate root, removing the confusing mix of absolute and relative paths. - Import statements still begin at the crate root, but regular expressions now follow the same rules as other paths.
Before:
mod foo {
fn bar() {
::serde_json::from_str("...");
}
}
After:
mod foo {
fn bar() {
serde_json::from_str("...");
// or crate::foo::bar() for internal items
}
}
How can I use Rust keywords as identifiers with the new raw identifier syntax?
Rust 1.30 introduces raw identifiers, allowing keywords to be used as variable or function names by prefixing them with r#.
This is useful when interfacing between editions or when generating code that collides with future keywords.
let r#for = true;
fn r#match() { /* ... */ }
r#match();
The syntax works everywhere a normal identifier is allowed, and the compiler treats the name literally without reserving it.
How does Rust 1.30 enable building no_std applications with a custom panic handler?
Rust 1.30 stabilizes the #[panic_handler] attribute, allowing developers to define their own panic routine for no_std binaries.
With this attribute you can now ship bare-metal or embedded executables that do not link the standard library.
#![no_std]
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
Prior to 1.30 only libraries could be no_std; now full applications can be built without the standard library.
Which standard library APIs were stabilized or renamed in Rust 1.30?
Rust 1.30 stabilizes several convenience APIs and renames whitespace-trimming methods for better Unicode clarity.
- New constants:
Ipv4Addr::BROADCAST,Ipv4Addr::LOCALHOST,Ipv4Addr::UNSPECIFIED,Ipv6Addr::LOCALHOST,Ipv6Addr::UNSPECIFIED. - Iterator extension:
Iterator::find_mapcombinesfindandmapin one pass. - Trim method rename:
trim_left→trim_start,trim_right→trim_end, and the corresponding*_matchesvariants.
The old trim_left/trim_right names are deprecated and will be removed in a future release.
Frequently Asked Questions
Does Rust 1.30 require any changes to existing #[derive] macros?
Existing #[derive] macros continue to work unchanged, but you can now also create attribute-like macros for more flexibility.
Can I import a macro with the use keyword in Rust 1.30?
Yes, you write use serde_json::json; and then call json!({ "key": "value" }) without needing #[macro_use].
Is the crate keyword now usable in paths outside of use statements?
Yes, you can write crate::module::function() to refer to an item from the crate root in any expression.
Are the old trim_left and trim_right methods still available in Rust 1.30?
The old names are still present but deprecated; the recommended forms are trim_start and trim_end.
How do I declare a panic handler for a no_std binary in Rust 1.30?
You add #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { loop {} } to your crate.
What is the new raw identifier syntax for using reserved words as names?
You prefix the identifier with r#, for example let r#for = true; or fn r#match() { }.