Navigate (Ctrl+Click) through std library (from macro)?

I am trying to use Ctrl+Click in VS Code + rust-analyzer (stable) to navigate my way from "Hello World" into the bowels of Rust.


fn main() {
    println!("Hello, world!");

I can click on println! just fine - I understand that this is a macro, and it takes me into with

macro_rules! println {
    () => ($crate::print!("\n"));
    ($($arg:tt)*) => ({

But: inside that very macro block, I cannot successfully Ctrl+Click on anything. I'd expect that $crate::print! takes me to the macro definition (right above) and that $crate::io::_print takes me into the source code of the std library, i.e. to

pub fn _print(args: fmt::Arguments<'_>) {
    print_to(args, stdout, "stdout");

I have managed to correctly configure the lldb.launch.sourceMap, so I can actually debug and then step into the library code ... and then Ctrl-Click there. I'd rather not run a debugger, though, just for surfing.

If my newbie understanding of macros in Rust is correct, then rust-analyzer would even have a rather decent chance at doing what I am asking it to do? (Mature C/C++ IDEs can even work some magic under in a much worse setting)

1 Like

rust-analyzer cannot currently do this. The problem is that the macro definition is just a bunch of tokens that only become meaningful wherever the macro is expanded, and RA cannot know in general that $crate::io::_print is even a path.

I can imagine various features that would help with this though (none of which are currently implemented):

  • our "expand macro" functionality could be improved to show expansions inline and allow you to use navigation features in the expanded code.
  • we could add a heuristic to detect $crate paths and allow navigating to them in macro definitions.
  • it might even be possible to keep some context when using "go to definition" on a macro call, which would allow us to interpret the macro definition in the context of the original call. I think IntelliJ does something similar with type parameters already, and I seem to remember talking about this with @matklad before. It'd be very far-future though.
1 Like

IntelliJ struggles exactly the same way as VS Code + rust-analyzer at the moment - despite making some noises around "expanding macros" or some such. (Exact same hello-world, FWIW).

From my (non-)understanding of Rust macros and crates so far, I believe implementing "just" item #2 in your list ($crate source code auto-detection and making them available as targets for browsing) might yield considerable benefit across all platforms.

The first item item involves (likely) considerable effort in specific VS Code extension support, while for the third item, you already offered an outlook.

Many thanks!

1 Like

Note that analysis of code that uses macros, and the anaysis of the code of the macros itself, are two very different things from the implementation point of view. See "the first case / the second case" here: GitHub - matklad/proc-caesar: A proc-macro to break Rust IDEs

In my case, it is the implementation of the println macro, or just any macro, where some form of assistance would be quite welcome.

That assistance doesn't have to be perfectly correct - a sufficient level of adequacy could help, here, too. In the case of on std, for instance, Ctrl-Click on "crate::print!" could identify the identifier "print" as a lovely destination, within the nearest source file(s) - e.g. the current file. This would basically reduce the feature to a glorified grep, but it might add value.

PS: Beware of what I am writing - I installed rust, VS Code, rust-analyzer yesterday night and am only now selectively poking at the language. Learning now :wink: that most macros are abstract syntax "tree" / parse stream manipulation engines, for instance. I have exactly zero clue based on real world experience what realistically could constitute added value for rust-analyzer.