rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
13.68k stars 1.5k forks source link

`include!` macro silently gives empty string if destination file is outside of the crate #17040

Open saschanaz opened 1 month ago

saschanaz commented 1 month ago

rust-analyzer version: 0.3.1916-standalone (7a8374c16 2024-04-08)

rustc version: rustc 1.77.2 (25ef9e3d8 2024-04-09)

editor or extension: VSCode, rust-analyzer v0.3.1916

relevant settings: N/A?

repository link (if public, optional): https://github.com/saschanaz/rust-include-repro

code snippet to reproduce: (Please refer to the repo to see the exact file tree)

include!("in-src.rs");
include!("../in-crate.rs");
include!("../../in-workspace.rs");

fn main() {
    in_src();
    in_crate();
    in_workspace();
}

The issue is threefold:

  1. The function name of in_workspace does not autocomplete in main()
  2. Hovering over in_workspace(); shows nothing
  3. Clicking "Inline macro" feature from light bulb menu for include!("../../in-workspace.rs") just deletes the line

The build result works as expected, so this should be rust-analyzer specific.

See also: https://bugzilla.mozilla.org/show_bug.cgi?id=1890431

saschanaz commented 3 weeks ago

Got some hint from #3767 and added some println, and it seems relative_file() is failing to load the file:

https://github.com/rust-lang/rust-analyzer/blob/5bf2f85c8054d80424899fa581db1b192230efb5/crates/hir-expand/src/builtin_fn_macro.rs#L668-L670

saschanaz commented 3 weeks ago

https://github.com/rust-lang/rust-analyzer/issues/15836#issuecomment-1805907174 seems to apply here?

saschanaz commented 3 weeks ago

So basically only the files that included in load_crate_graph() is supported for include!().

Maybe a fix can parse and load include!() string literals early enough? Thoughts? @Veykril

saschanaz commented 3 weeks ago

If parsing files requires a lot of changes, maybe at least allow adding some files in the list by environment variables?

davidbarsky commented 2 weeks ago

So basically only the files that included in load_crate_graph() is supported for include!().

Yes, that's correct. I think that making source root resolution look outside the crate might be feasible, but I think you might be better off not include!ing those source files.

saschanaz commented 1 week ago

Yes, that's correct. I think that making source root resolution look outside the crate might be feasible, but I think you might be better off not include!ing those source files.

Sure if the whole code is Rust, but if one needs to bind between other languages and Rust and the bindgen is not in Rust side (e.g. some Python code as in our case), the generated file ends up being outside of the crate graph.

How are build.rs-generated files being include!()-ed by rust-analyzer right now? Can a similar way help this case too?

Veykril commented 1 week ago

The corresponding out-dir is added correctly to the set of known files for a crate, so if your build script emits a file that the crate of that build script is then including that should work fine, it won't work cross crates though. This not working here is a known problem with our current VFS setup.