This PR is there to start a discussion on the basis of a working implementation, but is not meant to merge as-is until the discussion is over.
The gist of it is that I'm proposing to:
- Use cargo (and only cargo) to find the build target for the current file, and set the variables used by
rust-cargo
accordingly.
- Leave the
rust
checker for single rust files, which means not setting up any variables for it in flycheck-rust
.
And as I'm unsure whether this will break anyone's setup, I'm asking for feedback.
cc @flycheck/rust
Read on for the details.
To fix #38, I figured I might as well clean up the logic a bit in flycheck-rust, which was getting a bit redundant. Originally, it seems we used various methods to get the information to pass to the rustc
checker in order to be able to check single rust files. Then we started to use cargo
directly to get this information, and now we have two ways of doing things. I think that #8 intended for cargo to be the main way to extract the information needed to run the rust checkers, and this PR aims to do that.
As I understand it, the role of flycheck-rust is to set the variables used by the rust checkers in flycheck, so the checkers can produce meaningful errors for the current file. The rust checkers (especially rust-cargo
) won't actually do anything without the proper variables set first, especially flycheck-rust-crate-type
and flycheck-rust-binary-name
. These variables could also be set directly by the user, by file-local variables or .dir-locals.el
or any other means. Flycheck-rust will just try to set them when their value can be found automatically.
Also, I understand there's a slight mismatch between flycheck checkers that are meant to run on single files, but cargo
only builds targets, not individual files. We cannot point cargo to the file X and say "give me the compilation errors for X". We have to say "give me compilation errors for the binary crate Y", where crate Y contains and makes use of the file X, and we will get errors for X (among all the other files in Y). The problem with that is that we have no way to know for sure that file X is part of crate Y. cargo
won't tell us, and we would need to resolve the imports and build a dependency graph to know the answer; that's certainly out of scope. The only cases where we can be certain is when cargo read-manifest
gives us the exact filenames for targets. Other than that, we can make educated guesses based on the conventional cargo layout (e.g., any file under src/
other than src/main.rs
contribute to the library target). These guesses may fail if the project actually does not follow the convention, but then the user can always override these guesses with local variables.
I set up a test crate, added all the relevant test cases from the conventional cargo layout I could find, and just used cargo
to find the correct target to build based on the buffer filename. Even when deleting most of the code, it just works and sets up the flycheck-rust-crate-type
and flycheck-rust-binary-name
correctly for all the test cases.
This fixes #38, increases our coverage, and gets rid of most of the code. However, I don't know if I've broken anything else, especially for the plain rust
checker.
I left out setting these variables:
flycheck-rust-crate-root
is unneeded for rust-cargo
and might just be redundant with flycheck-rust-binary-name
flycheck-rust-check-tests
: I don't understand why we would skip tests in executables. It's less surprising if all the code is checked, including code behind the #[cfg(test)]
feature.
flycheck-rust-library-path
is unneeded for rust-cargo
as well, as cargo already handles passing the dependencies to rustc. It certainly is needed for the rust
checker, but only when building crates, which brings me to the last point.
As I gathered from #8, the use case for the bare rust
checker is to check single files that are not part of a cargo project (like StackOverflow answers, or minimal working examples), leaving the rust-cargo
checker for pretty much anything else. Though if that is the case, I don't understand why we we pass the variable flycheck-rust-crate-type
to rustc
in the rust
checker, or flycheck-rust-library-path
, especially as we have flycheck-rust-args
to already pass arbitrary arguments to rustc
. That may be a separate PR to flycheck if it turns out these variables are indeed superfluous.
Note: an alternative would be to add the ability to cargo to give us a list of build targets a file is associated with. That way, we could just get rid of flycheck-rust
altogether and just invoke that new command in rust-cargo
directly. I don't know if the cargo maintainers would be open to it, or how complex it would be to implement (I'm guessing not much, since the dependency information should already be available, but I haven't checked).
needs-input