rust-lang / rust-lang/rust-analyzer
Monomorphised go to definition
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 16.9k
- Forks
- 2.2k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 72
Description
Ideally, we should be able to follow a chain of go-to definitions to drill down to the specific implementations relied upon.
This would happen after https://github.com/rust-analyzer/rust-analyzer/issues/4558 is resolved.
One example is give in https://github.com/rust-analyzer/rust-analyzer/issues/2541#issuecomment-565199436
Larger example
I often find myself trying to work out what code gets called in a specific instantiation of a generic function, e.g. intrait Flob {
fn flobulate(self); //<-E
}
impl Flob for u32 {
fn flobulate(self) { //<- D
some::cool::implementation()
}
}
fn exec<T: Flob>(val: T) { // <-B
val.flobulate(); // <-C
}
fn main() {
exec(10u32); // <-A
}
I would click go to definition on exec at A, which would take me to B. I'd then click go to definition of flobulate at C, which I would want to take me to D, but instead takes me to E. If I want to find out what the specific implementation of flobulate actually does, I have to drop what I'm doing to track this manually. This means tracking which types are used in the instantiation I am interested in, trace them though (following associated types manually) and then track down the specific trait implementation which is actually used.
This is not fun, and feels like something rust-analyzer could help with.
My proposed user experience would be that the generics would be tracked, in a sense monomorphising the generic types upon go to definition.
My super high level implementation suggestion would be:
When you follow a go to definition on a generic function, the generics the function is called with are pushed onto a stack somewhere. Ideally, going back using mouse 4 or alt-left would pop this stack. These generics would then be used to get the specific type information for the first step as far as possible. These types could also be displayed as inlay hints next to the generic declaraction, e.g.
fn exec<T: Flob{inlay hint: =u32}>(val: T) { // <-B
val.flobulate(); // <-C
}
in my example and
impl<T: fmt::Display + ?Sized{inlay hint: = i32}> ToString for T {
fn to_string(&self) -> String {
/* ... */
buf.write_fmt(format_args!("{}", self))
/* ... */
}
}
in the example from https://github.com/rust-analyzer/rust-analyzer/issues/2541#issuecomment-565199436
Most of this is copied from my comment on zulip, where further related discussion might occur.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the prerequisite issue #4558, then review the linked examples in issue #2541 and the related Zulip discussion. The work is complete when go-to-definition can carry generic instantiation information through a chain and resolve a trait method to the specific implementation used, with optional generic inlay hints as described.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100