Commit graph

31254 commits

Author SHA1 Message Date
Lukas Wirth
737d5088e5 fix: Fix trait method completions not acknowledging Deref impls 2024-08-25 10:47:30 +02:00
Lukas Wirth
191949eabe fix: Fix metadata retrying eating original errors 2024-08-25 09:28:47 +02:00
bors
2025b43653 Auto merge of #17927 - ChayimFriedman2:speedup-new-usages, r=Veykril
perf: Speed up search for short associated functions, especially very common identifiers such as `new`

`@Veykril` said in https://github.com/rust-lang/rust-analyzer/pull/17908#issuecomment-2292958068 that people complain searches for `new()` are slow (they are right), so here I am to help!

The search is used by IDE features such as rename and find all references.

The search is slow because we need to verify each candidate, and that requires analyzing it; the key to speeding it up is to avoid the analysis where possible.

I did that with a bunch of tricks that exploits knowledge about the language and its possibilities. The first key insight is that associated methods may only be referenced in the form `ContainerName::func_name` (parentheses are not necessary!) (Rust doesn't include a way to `use Container::func_name`, and even if it will in the future most usages are likely to stay in that form.

Searching for `::` will help only a bit, but searching for `Container` can help considerably, since it is very rare that there will be two identical instances of both a container and a method of it.

However, things are not as simple as they sound. In Rust a container can be aliased in multiple ways, and even aliased from different files/modules. If we will try to resolve the alias, we will lose any gain from the textual search (although very common method names such as `new` will still benefit, most will suffer because there are more instances of a container name than its associated item).

This is where the key trick enters the picture. The key insight is that there is still a textual property: a container namer cannot be aliased, unless its name is mentioned in the alias declaration, or a name of alias of it is mentioned in the alias declaration.

This becomes a fixpoint algorithm: we expand our list of aliases as we collect more and more (possible) aliases, until we eventually reach a fixpoint. A fixpoint is not guaranteed (and we do have guards for the rare cases where it does not happen), but it is almost so: most types have very few aliases, if at all.

We do use some semantic information while analyzing aliases. It's a balance: too much semantic analysis, and the search will become slow. But too few of it, and we will bring many incorrect aliases to our list, and risk it expands and expands and never reach a fixpoint. At the end, based on benchmarks, it seems worth to do a lot to avoid adding an alias (but not too much), while it is worth to do a lot to avoid the need to semantically analyze func_name matches (but again, not too much).

After we collected our list of aliases, we filter matches based on this list. Only if a match can be real, we do semantic analysis for it.

The results are promising: searching for all references on `new()` in `base-db` in the rust-analyzer repository, which previously took around 60 seconds, now takes as least as two seconds and a half (roughly), while searching for `Vec::new()`, almost an upper bound to how much a symbol can be used, that used to take 7-9 minutes(!) now completes in 100-120 seconds, and with less than half of non-verified results (aka. false positives).

This is the less strictly correct (but faster) branch of this patch; it can miss some (rare) cases (there is a test for that - `goto_ref_on_short_associated_function_complicated_type_magic_can_confuse_our_logic()`). There is another branch that have no false negatives but is slower to search (`Vec::new()` never reaches a fixpoint in aliases collection there). I believe it is possible to create a strategy that will have the best of both worlds, but it will involve significant complexity and I didn't bother, especially considering that in the vast majority of the searches the other branch will be more than enough. But all in all, I decided to bring this branch (of course if the maintainers will agree), since our search is already not 100% accurate (it misses macros), and I believe there is value in the additional perf.

You can find the strict branch at https://github.com/ChayimFriedman2/rust-analyzer/tree/speedup-new-usages-strict.

Should fix #7404, I guess (will check now).
2024-08-23 09:17:47 +00:00
bors
44fd708415 Auto merge of #17912 - alibektas:cargo_check_on_binary, r=Veykril
fix: run flycheck without rev_deps when target is specified

Since querying for a crate's target is a call to salsa and therefore blocking, flycheck task is now deferred out of main thread by using `GlobalState`s `deferred_task_queue`. Fixes #17829  and https://github.com/rust-lang/rustlings/issues/2071
2024-08-23 09:03:11 +00:00
Ali Bektas
03456c545f Apply changes 2024-08-22 23:59:01 +02:00
Chayim Refael Friedman
6a910f637e Add cov_marks to test #17927 2024-08-22 20:52:51 +03:00
Chayim Refael Friedman
d89bdd9b83 Speed up search for short associated functions, especially very common identifiers such as new
The search is used by IDE features such as rename and find all references.

The search is slow because we need to verify each candidate, and that requires analyzing it; the key to speeding it up is to avoid the analysis where possible.

I did that with a bunch of tricks that exploits knowledge about the language and its possibilities. The first key insight is that associated methods may only be referenced in the form `ContainerName::func_name` (parentheses are not necessary!) (Rust doesn't include a way to `use Container::func_name`, and even if it will in the future most usages are likely to stay in that form.

Searching for `::` will help only a bit, but searching for `Container` can help considerably, since it is very rare that there will be two identical instances of both a container and a method of it.

However, things are not as simple as they sound. In Rust a container can be aliased in multiple ways, and even aliased from different files/modules. If we will try to resolve the alias, we will lose any gain from the textual search (although very common method names such as `new` will still benefit, most will suffer because there are more instances of a container name than its associated item).

This is where the key trick enters the picture. The key insight is that there is still a textual property: a container namer cannot be aliased, unless its name is mentioned in the alias declaration, or a name of alias of it is mentioned in the alias declaration.

This becomes a fixpoint algorithm: we expand our list of aliases as we collect more and more (possible) aliases, until we eventually reach a fixpoint. A fixpoint is not guaranteed (and we do have guards for the rare cases where it does not happen), but it is almost so: most types have very few aliases, if at all.

We do use some semantic information while analyzing aliases. It's a balance: too much semantic analysis, and the search will become slow. But too few of it, and we will bring many incorrect aliases to our list, and risk it expands and expands and never reach a fixpoint. At the end, based on benchmarks, it seems worth to do a lot to avoid adding an alias (but not too much), while it is worth to do a lot to avoid the need to semantically analyze func_name matches (but again, not too much).

After we collected our list of aliases, we filter matches based on this list. Only if a match can be real, we do semantic analysis for it.

The results are promising: searching for all references on `new()` in `base-db` in the rust-analyzer repository, which previously took around 60 seconds, now takes as least as two seconds and a half (roughly), while searching for `Vec::new()`, almost an upper bound to how much a symbol can be used, that used to take 7-9 minutes(!) now completes in 100-120 seconds, and with less than half of non-verified results (aka. false positives).

This is the less strictly correct (but faster) of this patch; it can miss some (rare) cases (there is a test for that - `goto_ref_on_short_associated_function_complicated_type_magic_can_confuse_our_logic()`). There is another branch that have no false negatives but is slower to search (`Vec::new()` never reaches a fixpoint in aliases collection there). I believe it is possible to create a strategy that will have the best of both worlds, but it will involve significant complexity and I didn't bother, especially considering that in the vast majority of the searches the other branch will be more than enough. But all in all, I decided to bring this branch (of course if the maintainers will agree), since our search is already not 100% accurate (it misses macros), and I believe there is value in the additional perf.
2024-08-22 20:52:51 +03:00
Chayim Refael Friedman
2fa0d4e2a8 When descending into macros in search, first check if there is a need to - i.e. if we are inside a macro call
This avoids the need to analyze the file when we are not inside a macro call.

This is especially important for the optimization in the next commit(s), as there the common case will be to descent into macros but then not analyze.
2024-08-22 20:52:51 +03:00
bors
9b724459b5 Auto merge of #17943 - Veykril:diags, r=Veykril
fix: Improve proc-macro panic message and workspace loading failure diagnostic
2024-08-22 16:47:56 +00:00
Lukas Wirth
ada65feaa1 Improve proc-macro panic message and workspace loading failure diagnostic 2024-08-22 18:46:23 +02:00
bors
a84c3d4d08 Auto merge of #17898 - Veykril:descend-2.0, r=Veykril
internal: Improve macro token mapping heuristics

Fixes https://github.com/rust-lang/rust-analyzer/issues/16235
2024-08-22 16:17:22 +00:00
Lukas Wirth
f854e19ef0 Fix sorting order for tokens in hover 2024-08-22 18:08:36 +02:00
bors
0fe4653871 Auto merge of #17942 - HKalbasi:fp-const-eval, r=HKalbasi
Implement floating point casts in const eval

fix #17926
2024-08-22 16:02:50 +00:00
Lukas Wirth
46feeb3f05 Consider interleaving hover kinds 2024-08-22 17:29:32 +02:00
Lukas Wirth
01fc1e57d2 Sort hover results by relevance 2024-08-22 17:01:51 +02:00
Lukas Wirth
c2a07e21f5 Thread file id through descension API for semantic highlighting 2024-08-22 16:45:37 +02:00
Lukas Wirth
354ab7a9e8 Rename macro descension functions 2024-08-22 16:24:01 +02:00
Lukas Wirth
64064907ce Fully remove old macro descension API 2024-08-22 16:18:01 +02:00
Lukas Wirth
495118015e Remove DescendPreference::SameKind 2024-08-22 16:00:57 +02:00
hkalbasi
850a83c7ce Implement floating point casts in const eval 2024-08-22 09:16:00 -04:00
Lukas Wirth
ce8f32022b Drop MacroInputKind 2024-08-22 12:39:53 +02:00
Lukas Wirth
f979667fb5 Remove DescendPreference::SameText 2024-08-22 12:34:20 +02:00
bors
011e3bb9ac Auto merge of #17939 - ShoyuVanilla:maybe-sized-fix, r=Veykril
fix: Wrong `Sized` predicate for `generic_predicates_for_param`

I found this gathers wrong `Self: Sized` bound while implementing object safety, though I couldn't find proper test for this.

If we call `generic_predicates_for_param` to `Bar` in the following code;
```rust
trait Foo<T: ?Sized> {}
trait Bar<T: Foo<Self> + ?Sized> {}
```
it returns `T: Sized` and `Self: Sized` bound, because normaly, the `?Sized` bound applied properly in L1059 with;
3723e5910c/crates/hir-ty/src/lower.rs (L1035-L1061)

But we filter them before it is lowered with that function here;

3723e5910c/crates/hir-ty/src/lower.rs (L1540-L1586)

So, the `?Sized` bounded params are not gathered into `ctx.unsized_types` and thus we are applying them implicit `Sized` bound here;

3723e5910c/crates/hir-ty/src/lower.rs (L1591-L1602)
2024-08-22 08:38:27 +00:00
Shoyu Vanilla
71080cfb6b fix: Wrong Sized predicate for generic_predicates_for_param 2024-08-22 00:32:44 +09:00
Ali Bektas
ffc3bfe435 Run flycheck only on crate if target is binary. 2024-08-21 01:39:16 +02:00
bors
3723e5910c Auto merge of #17913 - alibektas:ratoml_improvements, r=alibektas
fix: Add workspace level config to ratoml
2024-08-20 11:25:19 +00:00
bors
0e8df6f873 Auto merge of #17930 - Veykril:config-user-config, r=alibektas
Remove the ability to configure the user config path

Being able to do this makes little sense as this is effectively a cyclic dependency (and we do not want to fixpoint this really).
2024-08-20 11:10:55 +00:00
Ali Bektas
2559ddf631 Old configs are back 2024-08-20 12:35:56 +02:00
Ali Bektas
94ed6217dd Next up : generating configs for workspace level configs 2024-08-20 12:35:56 +02:00
Ali Bektas
d51fd9f196 Define workspace level configs. 2024-08-20 12:35:54 +02:00
bors
b02c214132 Auto merge of #17932 - Veykril:default-reply-lat-sensitive, r=Veykril
fix: Fix panics for semantic highlighting at startup

Without this we might try to process semantic highlighting requests before the database has entries for the given file resulting in a panic. There is no work to be done either way so delay this like we do with other request handlers.
2024-08-20 07:55:41 +00:00
Lukas Wirth
9b7b93e031 fix: Fix panics for semantic highlighting at startup 2024-08-20 09:53:37 +02:00
bors
979e3b54f7 Auto merge of #17886 - Wilfred:prime_caches_quiescent, r=Veykril
internal: ServerStatusParams should consider 'prime caches' in quiescent status

Priming caches is a performance win, but it takes a lock on the salsa database and prevents rust-analyzer from responding to e.g. go-to-def requests.

This causes confusion for users, who see the spinner next to rust-analyzer in the VS Code footer stop, so they start attempting to navigate their code.

Instead, set the `quiescent` status in LSP to false during cache priming, so the VS Code spinner persists until we can respond to any LSP request.
2024-08-19 17:30:25 +00:00
Wilfred Hughes
0edb0e1e62 ServerStatusParams should consider 'prime caches' in quiescent status
Priming caches is a performance win, but it takes a lock on the salsa
database and prevents rust-analyzer from responding to e.g. go-to-def
requests.

This causes confusion for users, who see the spinner next to
rust-analyzer in the VS Code footer stop, so they start attempting to
navigate their code.

Instead, set the `quiescent` status in LSP to false during cache
priming, so the VS Code spinner persists until we can respond to any
LSP request.
2024-08-19 10:27:53 -07:00
bors
644617361d Auto merge of #17924 - ShoyuVanilla:issue-17921, r=Veykril
fix: Panic when a TAIT exists in a RPIT

Fixes  #17921

When there is a TAIT inside of a RPIT like;

```rust
trait Foo {}
type Bar = impl Foo;
fn foo<A>() -> impl Future<Output = Bar> { .. }
```

while inferencing `fn foo`, `insert_inference_vars_for_impl_trait` tries to substitute impl trait bounds of `Bar`, i.e. `Implemented(Foo)` with RPITs `placeholders`, and this causes panic

fa00326247/crates/hir-ty/src/infer.rs (L903-L905)
2024-08-19 14:17:07 +00:00
Shoyu Vanilla
722f0d3b46 fix: Panic when a TAIT exists in a RPIT 2024-08-19 23:07:13 +09:00
Lukas Wirth
90e08d3c93 Allow user config to not exist 2024-08-19 16:00:06 +02:00
Lukas Wirth
fd3fce2600 Remove the ability to configure the user config path 2024-08-19 15:12:33 +02:00
bors
c9955bf86b Auto merge of #17929 - Veykril:invocation-loc-docs, r=Veykril
minor: Improve documentation for `InvocationStrategy`

cc https://github.com/rust-lang/rust-analyzer/pull/17888
2024-08-19 12:25:38 +00:00
Lukas Wirth
3c4cdbbd1a Improve documentation for InvocationStrategy 2024-08-19 14:23:05 +02:00
bors
0c395dc5a4 Auto merge of #17928 - roife:fix-issue-17869, r=Veykril
fix: keep comments in convert_while_to_loop

Fix #17869.
2024-08-19 10:20:50 +00:00
roife
6a85595bb8 fix: keep comments in convert_while_to_loop 2024-08-19 17:27:54 +08:00
bors
c1879398af Auto merge of #17888 - Tyrubias:remove-invocation-location, r=Veykril
chore(config): remove `invocationLocation` in favor of `invocationStrategy`

These flags were added to help rust-analyzer integrate with repos requiring non-Cargo invocations. The consensus is that having two independent settings are no longer needed. This change removes `invocationLocation` in favor of `invocationStrategy` and changes the internal representation of `InvocationStrategy::Once` to hold the workspace root.

Closes #17848.
2024-08-19 08:19:38 +00:00
Victor Song
b0f20c7deb chore(config): remove invocationLocation in favor of invocationStrategy
These flags were added to help rust-analyzer integrate with repos
requiring non-Cargo invocations. The consensus is that having two
independent settings are no longer needed. This change removes
`invocationLocation` in favor of `invocationStrategy` and changes
the internal representation of `InvocationStrategy::Once` to hold
the workspace root.
2024-08-19 02:25:40 -05:00
bors
ba973db72a Auto merge of #17925 - darichey:issue-17767, r=Veykril
Include generics when lowering extern type

Fixes #17767
2024-08-19 07:20:55 +00:00
David Richey
e350bc2cf5 Include generics when lowering extern type 2024-08-18 15:12:01 -05:00
bors
fa00326247 Auto merge of #17915 - Veykril:offline-no-deps, r=Veykril
feat: Make rust-analyzer work partially when offline

Helps out with https://github.com/rust-lang/rust-analyzer/issues/12499 a bit
2024-08-17 17:20:39 +00:00
Lukas Wirth
1013bf36dc Adress new clippy::large_enum_variant diagnostics 2024-08-17 19:18:56 +02:00
Lukas Wirth
07c1b83e98 feat: Make rust-analyzer work partially when missing an internet connection 2024-08-17 19:14:46 +02:00
bors
469b06214a Auto merge of #17916 - ShoyuVanilla:issue-17711, r=Veykril
fix: Wrong BoundVar index when lowering impl trait parameter of parent generics

Fixes #17711

From the following test code;

```rust
//- minicore: deref
use core::ops::Deref;

struct Struct<'a, T>(&'a T);

trait Trait {}

impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> {
    fn foo(&self) -> &Self { self }

    fn bar(&self) {
        let _ = self.foo();
    }

}
```

when we call `register_obligations_for_call` for `let _ = self.foo();`,

07659783fd/crates/hir-ty/src/infer/expr.rs (L1939-L1952)

we are querying `generic_predicates` and it has `T: Deref<Target = impl Trait>` predicate from the parent `impl Struct`;

07659783fd/crates/hir-ty/src/lower.rs (L375-L399)

but as we can see above, lowering `TypeRef = impl Trait` doesn't take into account the parent generic parameters, so the `BoundVar` index here is `0`, as `fn foo` has no generic args other than parent's,

But this `BoundVar` is pointing at `'a` in `<'a, T: Deref<Target = impl Trait>>`.
So, in the first code reference `register_obligations_for_call`'s L:1948 - `.substitute(Interner, parameters)`, we are substituting `'a` with `Ty`, not `Lifetime` and this makes panic inside the chalk.

This PR fixes this wrong `BoundVar` index in such cases
2024-08-17 17:00:52 +00:00