Drop support for non-syroot proc macro ABIs
This makes some bigger changes to how we handle the proc-macro-srv things, for one it is now an empty crate if built without the `sysroot-abi` feature, this simplifies some things dropping the need to put the feature cfg in various places. The cli wrapper now actually depends on the server, instead of being part of the server that is just exported, that way we can have a true dummy server that just errors on each request if no sysroot support was specified.
internal: Add config to specifiy lru capacities for all queries
Might help figuring out what queries should be limited by LRU by default, as currently we only limit `parse`, `parse_macro_expansion` and `macro_expand`.
fix: allow new, subsequent `rust-project.json`-based workspaces to get proc macro expansion
As detailed in https://github.com/rust-lang/rust-analyzer/issues/14417#issuecomment-1485336174, `rust-project.json` workspaces added after the initial `rust-project.json`-based workspace was already indexed by rust-analyzer would not receive procedural macro expansion despite `config.expand_proc_macros` returning true. To fix this issue:
1. I changed `reload.rs` to check which workspaces are newly added.
2. Spawned new procedural macro expansion servers based on the _new_ workspaces.
1. This is to prevent spawning duplicate procedural macro expansion servers for already existing workspaces. While the overall memory usage of duplicate procedural macro servers is minimal, this is more about the _principle_ of not leaking processes 😅.
3. Launched procedural macro expansion if any workspaces are `rust-project.json`-based _or_ `same_workspaces` is true. `same_workspaces` being true (and reachable) indicates that that build scripts have finished building (in Cargo-based projects), while the build scripts in `rust-project.json`-based projects have _already been built_ by the build system that produced the `rust-project.json`.
I couldn't really think of structuring this code in a better way without engaging with https://github.com/rust-lang/rust-analyzer/issues/7444.
Remove client side proc-macro version check
The server already verifies versions due to ABI picking now so there shouldn't be a need for the client side check anymore
fix: Do not retry inlay hint requests
Should close https://github.com/rust-lang/rust-analyzer/issues/13372, retrying the way its currently implemented is not ideal as we do not adjust offsets in the requests, but doing that is a major PITA, so this should at least work around one of the more annoying issues stemming from it.
Add Cargo-style project discovery for Buck and Bazel Users
This feature requires the user to add a command that generates a `rust-project.json` from a set of files. Project discovery can be invoked in two ways:
1. At extension activation time, which includes the generated `rust-project.json` as part of the linkedProjects argument in `InitializeParams`.
2. Through a new command titled "rust-analyzer: Add current file to workspace", which makes use of a new, rust-analyzer-specific LSP request that adds the workspace without erasing any existing workspaces. Note that there is no mechanism to _remove_ workspaces other than "quit the rust-analyzer server".
Few notes:
- I think that the command-running functionality _could_ merit being placed into its own extension (and expose it via extension contribution points) to provide build-system idiomatic progress reporting and status handling, but I haven't (yet) made an extension that does this nor does Buck expose this sort of functionality.
- This approach would _just work_ for Bazel. I'll try and get the tool that's responsible for Buck integration open-sourced soon.
- On the testing side of things, I've used this in around my employer's Buck-powered monorepo and it's a nice experience. That being said, I can't think of an open-source repository where this can be tested in public, so you might need to trust me on this one.
I'd love to get feedback on:
- Naming of LSP extensions/new commands. I'm not too pleased with how "rust-analyzer: Add current file to workspace" is named, in that it's creating a _new_ workspace. I think that this command being added should be gated on `rust-analyzer.discoverProjectCommand` on being set, so I can add this in sequent commits.
- My Typescript. It's not particularly good.
- Suggestions on handling folders with _both_ Cargo and non-Cargo build systems and if I make activation a bit better.
(I previously tried to add this functionality entirely within rust-analyzer-the-LSP server itself, but matklad was right—an extension side approach is much, much easier.)
This feature requires the user to add a command that generates a
`rust-project.json` from a set of files. Project discovery can be invoked
in two ways:
1. At extension activation time, which includes the generated
`rust-project.json` as part of the linkedProjects argument in
InitializeParams
2. Through a new command titled "Add current file to workspace", which
makes use of a new, rust-analyzer specific LSP request that adds
the workspace without erasing any existing workspaces.
I think that the command-running functionality _could_ merit being
placed into its own extension (and expose it via extension contribution
points), if only provide build-system idiomatic progress reporting and
status handling, but I haven't (yet) made an extension that does this.
Handle trait alias definitions
Part of #2773
This PR adds a bunch of structs and enum variants for trait aliases. Trait aliases should be handled as an independent item because they are semantically distinct from traits.
I basically started by adding `TraitAlias{Id, Loc}` to `hir_def::item_tree` and iterated adding necessary stuffs until compiler stopped complaining what's missing. Let me know if there's still anything I need to add.
I'm opening up this PR for early review and stuff. I'm planning to add tests for IDE functionalities in this PR, but not type-related support, for which I put FIXME notes.
Beginning of MIR
This pull request introduces the initial implementation of MIR lowering and interpreting in Rust Analyzer.
The implementation of MIR has potential to bring several benefits:
- Executing a unit test without compiling it: This is my main goal. It can be useful for quickly testing code changes and print-debugging unit tests without the need for a full compilation (ideally in almost zero time, similar to languages like python and js). There is a probability that it goes nowhere, it might become slower than rustc, or it might need some unreasonable amount of memory, or we may fail to support a common pattern/function that make it unusable for most of the codes.
- Constant evaluation: MIR allows for easier and more correct constant evaluation, on par with rustc. If r-a wants to fully support the type system, it needs full const eval, which means arbitrary code execution, which needs MIR or something similar.
- Supporting more diagnostics: MIR can be used to detect errors, most famously borrow checker and lifetime errors, but also mutability errors and uninitialized variables, which can be difficult/impossible to detect in HIR.
- Lowering closures: With MIR we can find out closure capture modes, which is useful in detecting if a closure implements the `FnMut` or `Fn` traits, and calculating its size and data layout.
But the current PR implements no diagnostics and doesn't support closures. About const eval, I removed the old const eval code and it now uses the mir interpreter. Everything that is supported in stable rustc is either implemented or is super easy to implement. About interpreting unit tests, I added an experimental config, disabled by default, that shows a `pass` or `fail` on hover of unit tests (ideally it should be a button similar to `Run test` button, but I didn't figured out how to add them). Currently, no real world test works, due to missing features including closures, heap allocation, `dyn Trait` and ... so at this point it is only useful for me selecting what to implement next.
The implementation of MIR is based on the design of rustc, the data structures are almost copy paste (so it should be easy to migrate it to a possible future stable-mir), but the lowering and interpreting code is from me.
Rename `checkOnSave` settings to `check`
Now that flychecks can be triggered without saving the setting name doesn't make that much sense anymore. This PR renames it to just `check`, but keeps `checkOnSave` as the enabling setting.
feat: add the ability to limit the number of threads launched by `main_loop`
## Motivation
`main_loop` defaults to launch as many threads as cpus in one machine. When developing on multi-core remote servers on multiple projects, this will lead to thousands of idle threads being created. This is very annoying when one wants check whether his program under developing is running correctly via `htop`.
<img width="756" alt="image" src="https://user-images.githubusercontent.com/41831480/206656419-fa3f0dd2-e554-4f36-be1b-29d54739930c.png">
## Contribution
This patch introduce the configuration option `rust-analyzer.numThreads` to set the desired thread number used by the main thread pool.
This should have no effects on the performance as not all threads are actually used.
<img width="1325" alt="image" src="https://user-images.githubusercontent.com/41831480/206656834-fe625c4c-b993-4771-8a82-7427c297fd41.png">
## Demonstration
The following is a snippet of `lunarvim` configuration using my own build.
```lua
vim.list_extend(lvim.lsp.automatic_configuration.skipped_servers, { "rust_analyzer" })
require("lvim.lsp.manager").setup("rust_analyzer", {
cmd = { "env", "RA_LOG=debug", "RA_LOG_FILE=/tmp/ra-test.log",
"/home/jlhu/Projects/rust-analyzer/target/debug/rust-analyzer",
},
init_options = {
numThreads = 4,
},
settings = {
cachePriming = {
numThreads = 8,
},
},
})
```
## Limitations
The `numThreads` can only be modified via `initializationOptions` in early initialisation because everything has to wait until the thread pool starts including the dynamic settings modification support.
The `numThreads` also does not reflect the end results of how many threads is actually created, because I have not yet tracked down everything that spawns threads.
fix a bunch of clippy lints
fixes a bunch of clippy lints for fun and profit
i'm aware of this repo's position on clippy. The changes are split into separate commits so they can be reviewed separately
This makes code more readale and concise,
moving all format arguments like `format!("{}", foo)`
into the more compact `format!("{foo}")` form.
The change was automatically created with, so there are far less change
of an accidental typo.
```
cargo clippy --fix -- -A clippy::all -W clippy::uninlined_format_args
```
Seems like these can be safely fixed. With one, I was particularly
surprised -- `Some(pats) => &**pats,` in body.rs?
```
cargo clippy --fix -- -A clippy::all -D clippy::explicit_auto_deref
```
I am not certain if this will improve performance,
but it seems having a .clone() without any need should be removed.
This was done with clippy, and manually reviewed:
```
cargo clippy --fix -- -A clippy::all -D clippy::redundant_clone
```
feat: Add an option to hide adjustment hints outside of `unsafe` blocks and functions
As the title suggests: this PR adds an option (namely `rust-analyzer.inlayHints.expressionAdjustmentHints.hideOutsideUnsafe`) that allows to hide adjustment hints outside of `unsafe` blocks and functions:
![2022-12-21_23-11](https://user-images.githubusercontent.com/38225716/208986376-d607de62-8290-4e16-b7fe-15b762dc5f60.png)
Requested by `@BoxyUwU` <3
Don't show runnable code lenses in libraries outside of the workspace
Addresses #13664. For now I'm just disabling runnable code lenses since the ones that display the number of references and implementations do work correctly with external code.
Also made a tiny TypeScript change to use the typed `sendNotification` overload.
Mega-sync from `rust-lang/rust`
This essentially implements `@oli-obk's` suggestion here https://github.com/rust-lang/rust-analyzer/pull/13459#issuecomment-1297285607, with `@eddyb's` help.
This PR is equivalent to 14 syncs (back and forth) between `rust-lang/rust` and `rust-lang/rust-analyzer`.
Working from this list (from bottom to top):
```
(x) a2a1d9954⬆️ rust-analyzer
(x) 79923c382⬆️ rust-analyzer
(x) c60b1f641⬆️ rust-analyzer
(x) 8807fc4cc⬆️ rust-analyzer
(x) a99a48e78⬆️ rust-analyzer
(x) 4f55ebbd4⬆️ rust-analyzer
(x) f5fde4df4⬆️ rust-analyzer
(x) 459bbb422⬆️ rust-analyzer
(x) 65e1dc4d9⬆️ rust-analyzer
(x) 3e358a682⬆️ rust-analyzer
(x) 31519bb39⬆️ rust-analyzer
(x) 8231fee46⬆️ rust-analyzer
(x) 22c8c9c40⬆️ rust-analyzer
(x) 9d2cb42a4⬆️ rust-analyzer
```
(This listed was assembled by doing a `git subtree push`, which made a branch, and looking at the new commits in that branch, picking only those that were `⬆️ rust-analyzer` commits)
We used the following commands to simulate merges in both directions:
```shell
TO_MERGE=22c8c9c40 # taken from the list above, bottom to top
git merge --no-edit --no-ff $TO_MERGE
git merge --no-edit --no-ff $(git -C ../rust log --pretty=format:'%cN | %s | %ad => %P' | rg -m1 -F "$(git show --no-patch --pretty=format:%ad $TO_MERGE)" | tee /dev/stderr | rg '.* => \S+ (\S+)$' --replace '$1')
```
We encountered no merge conflicts that Git wasn't able to solve by doing it this way.
Here's what the commit graph looks like (as shown in the Git Lens VSCode extension):
<img width="1345" alt="image" src="https://user-images.githubusercontent.com/7998310/203984523-7c1a690a-8224-416c-8015-ed6e49667066.png">
This PR closes#13459
## Does this unbreak `rust->ra` syncs?
Yes, here's how we tried:
In `rust-analyzer`:
* check out `subtree-fix` (this PR's branch)
* make a new branch off of it: `git checkout -b subtree-fix-merge-test`
* simulate this PR getting merged with `git merge master`
In `rust`:
* pull latest master
* make a new branch: `git checkout -b test-change`
* mess with rust-analyzer (I added a comment to `src/tools/rust-analyzer/Cargo.toml`)
* commit
* run `git subtree push -P src/tools/rust-analyzer ra-local final-sync` (this follows the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html))
This created a `final-sync` branch in `rust-analyzer`.
In `rust-analyzer`:
* `git merge --no-ff final-sync` (this follows the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html))
Now `git log` in `rust-analyzer` shows this:
```
commit 460128387e46ddfc2b95921b2d7f6e913a3d2b9f (HEAD -> subtree-fix-merge-test)
Merge: 0513fc02a 9ce6a734f
Author: Amos Wenger <amoswenger@gmail.com>
Date: Fri Nov 25 13:28:24 2022 +0100
Merge branch 'final-sync' into subtree-fix-merge-test
commit 0513fc02a08ea9de952983624bd0a00e98044b36
Merge: 38c98d1ff6918009fe
Author: Amos Wenger <amoswenger@gmail.com>
Date: Fri Nov 25 13:28:02 2022 +0100
Merge branch 'master' into subtree-fix-merge-test
commit 9ce6a734f37ef8e53689f1c6f427a9efafe846bd (final-sync)
Author: Amos Wenger <amoswenger@gmail.com>
Date: Fri Nov 25 13:26:26 2022 +0100
Mess with rust-analyzer just for fun
```
And `git diff 0513fc02a08ea9de952983624bd0a00e98044b36` shows this:
```patch
diff --git a/Cargo.toml b/Cargo.toml
index 286ef1e7d..c9e24cd19 100644
--- a/Cargo.toml
+++ b/Cargo.toml
`@@` -32,3 +32,5 `@@` debug = 0
# ungrammar = { path = "../ungrammar" }
# salsa = { path = "../salsa" }
+
+# lol, hi
```
## Does this unbreak `ra->rust` syncs?
Yes, here's how we tried.
From `rust`:
* `git checkout -b sync-from-ra`
* `git subtree pull -P src/tools/rust-analyzer ra-local subtree-fix-merge-test` (this is adapted from the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-clippy-to-rust-langrust), you would normally use `ra-upstream master` but we're simulating things here)
A commit editor pops up, there was no merge conflicts.
## How do we prevent this from happening again?
Like `@bjorn3` said in https://github.com/rust-lang/rust-analyzer/pull/13459#issuecomment-1293587848
> Whenever syncing from rust-analyzer -> rust you have to immediately sync the merge commit from rust -> rust-analyzer to prevent merge conflicts in the future.
But if we get it wrong again, at least now we have a not-so-painful way to fix it.
Fix: Handle empty `checkOnSave/target` values
This fixes a regression introduced by #13290, in which failing to set `checkOnSave/target` (or `checkOnSave/targets`) would lead to an invalid config.
[Fixes#13660]
Support multiple targets for checkOnSave (in conjunction with cargo 1.64.0+)
This PR adds support for the ability to pass multiple `--target` flags when using
`cargo` 1.64.0+.
## Questions
I needed to change the type of two configurations options, but I did not plurialize the names to
avoid too much churn, should I ?
## Zulip thread
https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/Issue.2013282.20.28supporting.20multiple.20targets.20with.201.2E64.2B.29
## Example
To see it working, on a macOS machine:
```sh
$ cd /tmp
$ cargo new cargo-multiple-targets-support-ra-test
$ cd !$
$ mkdir .cargo
$ echo '
[build]
target = [
"aarch64-apple-darwin",
"x86_64-apple-darwin",
]
' > .cargo/config.toml
$ echo '
fn main() {
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
#[cfg(all(target_arch = "x86_64", target_os = "macos"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
{
let a = std::fs::read_to_string("/tmp/test-read");
}
}
' > src/main.rs
# launch your favorite editor with the version of RA from this PR
#
# You should see warnings under the first two `let a = ...` but not the third
```
## Screen
![Two panes of a terminal emulator, on the left pane is the main.rs file described above, with warnings for the first two let a = declaration, on the right pane is a display of the .cargo/config.toml, an ls of the current files in the directory and a call to cargo build to show the same warnings as in the editor on the left pane](https://user-images.githubusercontent.com/7951708/192122707-7a00606a-e581-4534-b9d5-b81c92694e8e.png)
Helps with #13282
scip: Generate symbols for local crates.
Consider something like:
```
// a.rs
pub struct Foo { .. } // Foo is "local 1"
fn something() {
crate:🅱️:Bar::new() // Bar is "local 1", but of "b.rs"
}
// b.rs
pub struct Bar { .. } // "local 1"
```
Without this there's no way to disambiguate whether "local 1" references "Bar" or "Foo".
feat: add config for inserting must_use in `generate_enum_as_method`
Should fix#13312
Didn't add a test because I was not sure on how to add test for a specific configuration option, tried to look for the usages for other `AssistConfig` variants but couldn't find any in `tests`. If there is a way to test this, do point me towards it.
I tried to extract the formatting string as a common `template_string` and only have if-else for that, but it didn't compile :(
Also it seems these tests are failing:
```
test config::tests::generate_config_documentation ... FAILED
test config::tests::generate_package_json_config ... FAILED
```
Can you also point me to how to correct these 😅 ( I guess there is some command to automatically generate these? )
Implement invocation strategy config
Fixes https://github.com/rust-lang/rust-analyzer/issues/10793
This allows to change how we run build scripts (and `checkOnSave`), exposing two configs:
- `once`: run the specified command once in the project root (the working dir of the server)
- `per_workspace`: run the specified command per workspace in the corresponding workspace
This also applies to `checkOnSave` likewise, though `once_in_root` is useless there currently, due to https://github.com/rust-lang/cargo/issues/11007
The reason for that was that we were calculating the crate defmaps
of the file we are saving by accident causing us to get stuck waiting
on their expensive computation, while we only need the relevant crate
id.
The main change here should be that flags are not inhereted, so
$ rust-analyzer analysis-stats . -v -v
would do what it should do
We also no longer Don\'t
This fixes a typo first appearing in #94624
in which test-macro diagnostic uses "a" article twice.
Since I searched sources for " a a " sequences,
I also fixed the same issue in a few source files where I found it.
Signed-off-by: Petr Portnov <gh@progrm-jarvis.ru>
Amalgamate file changes for the same file ids in process_changes
When receiving multiple change events for a single file id where the last change is a delete the server panics, as it tries to access the file contents of a deleted file. This occurs due to the VFS changes and the in memory file contents being updated immediately, while `process_changes` processes the events afterwards in sequence which no longer works as it will only observe the final file contents. By folding these events together, we will no longer try to process these intermediate changes, as they aren't relevant anyways.
Potentially fixes https://github.com/rust-lang/rust-analyzer/issues/13236
When receiving multiple change events for a single file id where the
last change is a delete the server panics, as it tries to access the
file contents of a deleted file. This occurs due to the VFS changes and
the in memory file contents being updated immediately, while
`process_changes` processes the events afterwards in sequence which no
longer works as it will only observe the final file contents. By
folding these events together, we will no longer try to process these
intermediate changes, as they aren't relevant anyways.
Potentially fixes https://github.com/rust-lang/rust-analyzer/issues/13236