Stream: t-compiler/rust-analyzer

Topic: Finding a FunciĆ³n given a CrateDefMap


kev (Jan 01 2021 at 18:59, on Zulip):

A related question I also had was given a CrateDefMap and a path to a function. How would I get the data and the body of that function?

An example I had in mind was:

mod foo {

      fn a() {
        let _j = 1 + 1;
     }

     fn b() {}

}

I have a crateDefMap structure and I know the path to a is foo::a . Is there a way to recover the data on a such as it's visibility and it's content such as the let statement?

kev (Jan 01 2021 at 19:13, on Zulip):

Oh so this is related because I was following the logic of the DefCollector which calls the ModCollector.

The ModCollector finds a function here: https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/hir_def/src/nameres/collector.rs#L1042

and extracts a DefData object from the found function. I noticed, the DefData object has the function name.

This line is then called: https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/hir_def/src/nameres/collector.rs#L1168

Where the FunctionID is added to the module ItemScope(L1169), then the visibility is resolved relative to the module the function was defined in(L1170-1174) then on L115-1179 we update the namespaces, but I'm not too sure what is exactly happening here with the GlobImports types and ItemScope types.

Florian Diebold (Jan 01 2021 at 19:14, on Zulip):

CrateDefMap has a resolve_path function that you could use for this, but it's unlikely to be the right thing to use

kev (Jan 01 2021 at 19:19, on Zulip):

Florian Diebold said:

CrateDefMap has a resolve_path function that you could use for this, but it's unlikely to be the right thing to use

Is it because we no longer will need the function names once the DefMap is constructed?

Florian Diebold (Jan 01 2021 at 19:22, on Zulip):

it just kind of depends on where that path actually comes from

kev (Jan 01 2021 at 19:22, on Zulip):

kev said:

Florian Diebold said:

CrateDefMap has a resolve_path function that you could use for this, but it's unlikely to be the right thing to use

Is it because we no longer will need the function names once the DefMap is constructed?

For example, given:

fn hello() {
 world()
}

fn world() {}

Since hello calls world when I go to resolve hello I would need some way to access world wherever it is. I thought that this would be via it's name unless we somehow know the FunctionID for world when we are resolving hello

Florian Diebold (Jan 01 2021 at 19:27, on Zulip):

resolving world in that situation happens through a Resolver, which uses the CrateDefMap but also handles stuff like generics, local bindings etc.

kev (Jan 01 2021 at 19:34, on Zulip):

Florian Diebold said:

resolving world in that situation happens through a Resolver, which uses the CrateDefMap but also handles stuff like generics, local bindings etc.

Oh I see, I guess since they are both from the same module, this can be resolved quite easily using the ItemScope which has a HashMap from Name to ModuleDefID.

If they are not in the same module, then I guess since there is also a HashMap linking ModuleNames to ModuleIDs then that case is also fine.

If they are not in the same Crate, then I guess you can look into the extern_prelude which has the CrateName and the ModuleDefId which would the FunctionID. From the CrateName you can get the CrateID and subsequently the CrateMap for that Crate.

Is this correct?

Florian Diebold (Jan 01 2021 at 19:40, on Zulip):

that's roughly what's happening. See the resolve_path_fp_with_macro function, which does the actual work of resolving paths using the CrateDefMap

kev (Jan 01 2021 at 19:48, on Zulip):

Florian Diebold said:

that's roughly what's happening. See the resolve_path_fp_with_macro function, which does the actual work of resolving paths using the CrateDefMap

Ah okay thanks for the help, still debugging resolve_path_fp_with_macro with a test case to see how it works, I think my initial confusion has been cleared. Thank you

Last update: Jul 26 2021 at 14:00UTC