internal: Add an HIR pretty-printer This improves the "View HIR" command by pretty-printing the HIR to make it much more readable. Example function: ```rust fn newline(&mut self) { match self.buf.chars().rev().skip_while(|ch| *ch == ' ').next() { Some('\n') | None => {} _ => writeln!(self).unwrap(), } } ``` Previous output: ``` HIR expressions in the body of `newline`: Idx::<Expr>(0): Path(Path { type_anchor: None, mod_path: ModPath { kind: Super(0), segments: [] }, generic_args: [] }) Idx::<Expr>(1): Field { expr: Idx::<Expr>(0), name: Name(Text("buf")) } Idx::<Expr>(2): MethodCall { receiver: Idx::<Expr>(1), method_name: Name(Text("chars")), args: [], generic_args: None } Idx::<Expr>(3): MethodCall { receiver: Idx::<Expr>(2), method_name: Name(Text("rev")), args: [], generic_args: None } Idx::<Expr>(4): Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("ch"))] }, generic_args: [None] }) Idx::<Expr>(5): UnaryOp { expr: Idx::<Expr>(4), op: Deref } Idx::<Expr>(6): Literal(Char(' ')) Idx::<Expr>(7): BinaryOp { lhs: Idx::<Expr>(5), rhs: Idx::<Expr>(6), op: Some(CmpOp(Eq { negated: false })) } Idx::<Expr>(8): Closure { args: [Idx::<Pat>(1)], arg_types: [None], ret_type: None, body: Idx::<Expr>(7) } Idx::<Expr>(9): MethodCall { receiver: Idx::<Expr>(3), method_name: Name(Text("skip_while")), args: [Idx::<Expr>(8)], generic_args: None } Idx::<Expr>(10): MethodCall { receiver: Idx::<Expr>(9), method_name: Name(Text("next")), args: [], generic_args: None } Idx::<Expr>(11): Literal(Char('\n')) Idx::<Expr>(12): Block { id: BlockId(37), statements: [], tail: None, label: None } Idx::<Expr>(13): Path(Path { type_anchor: None, mod_path: ModPath { kind: Super(0), segments: [] }, generic_args: [] }) Idx::<Expr>(14): Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("std")), Name(Text("fmt")), Name(Text("Arguments")), Name(Text("new_v1"))] }, generic_args: [None, None, None, None] }) Idx::<Expr>(15): Array(ElementList { elements: [], is_assignee_expr: false }) Idx::<Expr>(16): Ref { expr: Idx::<Expr>(15), rawness: Ref, mutability: Shared } Idx::<Expr>(17): Array(ElementList { elements: [], is_assignee_expr: false }) Idx::<Expr>(18): Ref { expr: Idx::<Expr>(17), rawness: Ref, mutability: Shared } Idx::<Expr>(19): Call { callee: Idx::<Expr>(14), args: [Idx::<Expr>(16), Idx::<Expr>(18)], is_assignee_expr: false } Idx::<Expr>(20): MethodCall { receiver: Idx::<Expr>(13), method_name: Name(Text("write_fmt")), args: [Idx::<Expr>(19)], generic_args: None } Idx::<Expr>(21): MacroStmts { statements: [], tail: Some(Idx::<Expr>(20)) } Idx::<Expr>(22): MethodCall { receiver: Idx::<Expr>(21), method_name: Name(Text("unwrap")), args: [], generic_args: None } Idx::<Expr>(23): Match { expr: Idx::<Expr>(10), arms: [MatchArm { pat: Idx::<Pat>(5), guard: None, expr: Idx::<Expr>(12) }, MatchArm { pat: Idx::<Pat>(6), guard: None, expr: Idx::<Expr>(22) }] } Idx::<Expr>(24): Block { id: BlockId(36), statements: [], tail: Some(Idx::<Expr>(23)), label: None } ``` Output after this PR: ```rust fn newline(…) { match self.buf.chars().rev().skip_while( |ch| (*ch) == (' '), ).next() { Some('\n') | None => {}, _ => { // macro statements self.write_fmt( std::fmt::Arguments::new_v1( &[], &[], ), ) }.unwrap(), } } ``` It also works for consts and statics now. This should make debugging HIR-lowering related issues like https://github.com/rust-lang/rust-analyzer/issues/12940 much easier.
rust-analyzer is a modular compiler frontend for the Rust language. It is a part of a larger rls-2.0 effort to create excellent IDE support for Rust.
Quick Start
https://rust-analyzer.github.io/manual.html#installation
Documentation
If you want to contribute to rust-analyzer or are just curious about how things work under the hood, check the ./docs/dev folder.
If you want to use rust-analyzer's language server with your editor of choice, check the manual folder. It also contains some tips & tricks to help you be more productive when using rust-analyzer.
Security and Privacy
See the corresponding sections of the manual.
Communication
For usage and troubleshooting requests, please use "IDEs and Editors" category of the Rust forum:
https://users.rust-lang.org/c/ide/14
For questions about development and implementation, join rust-analyzer working group on Zulip:
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
Quick Links
- Website: https://rust-analyzer.github.io/
- Metrics: https://rust-analyzer.github.io/metrics/
- API docs: https://rust-lang.github.io/rust-analyzer/ide/
- Changelog: https://rust-analyzer.github.io/thisweek
License
rust-analyzer is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0).
See LICENSE-APACHE and LICENSE-MIT for details.