3050: Refactor type parameters, implement argument position impl trait r=matklad a=flodiebold
I wanted to implement APIT by lowering to type parameters because we need to do that anyway for correctness and don't need Chalk support for it; this grew into some more wide-ranging refactoring of how type parameters are handled 😅
- use Ty::Bound instead of Ty::Param to represent polymorphism, and explicitly
count binders. This gets us closer to Chalk's way of doing things, and means
that we now only use Param as a placeholder for an unknown type, e.g. within
a generic function. I.e. we're never using Param in a situation where we want
to substitute it, and the method to do that is gone; `subst` now always works
on bound variables. (This changes how the types of generic functions print;
previously, you'd get something like `fn identity<i32>(T) -> T`, but now we
display the substituted signature `fn identity<i32>(i32) -> i32`, which I think
makes more sense.)
- once we do this, it's more natural to represent `Param` by a globally unique
ID; the use of indices was mostly to make substituting easier. This also
means we fix the bug where `Param` loses its name when going through Chalk.
- I would actually like to rename `Param` to `Placeholder` to better reflect its use and
get closer to Chalk, but I'll leave that to a follow-up.
- introduce a context for type lowering, to allow lowering `impl Trait` to
different things depending on where we are. And since we have that, we can
also lower type parameters directly to variables instead of placeholders.
Also, we'll be able to use this later to collect diagnostics.
- implement argument position impl trait by lowering it to type parameters.
I've realized that this is necessary to correctly implement it; e.g. consider
`fn foo(impl Display) -> impl Something`. It's observable that the return
type of e.g. `foo(1u32)` unifies with itself, but doesn't unify with e.g.
`foo(1i32)`; so the return type needs to be parameterized by the argument
type.
This fixes a few bugs as well:
- type parameters 'losing' their name when they go through Chalk, as mentioned
above (i.e. getting `[missing name]` somewhere)
- impl trait not being considered as implementing the super traits (very
noticeable for the `db` in RA)
- the fact that argument impl trait was only turned into variables when the
function got called caused type mismatches when the function was used as a
value (fixes a few type mismatches in RA)
The one thing I'm not so happy with here is how we're lowering `impl Trait` types to variables; since `TypeRef`s don't have an identity currently, we just count how many of them we have seen while going through the function signature. That's quite fragile though, since we have to do it while desugaring generics and while lowering the type signature, and in the exact same order in both cases. We could consider either giving only `TypeRef::ImplTrait` a local id, or maybe just giving all `TypeRef`s an identity after all (we talked about this before)...
Follow-up tasks:
- handle return position impl trait; we basically need to create a variable and some trait obligations for that variable
- rename `Param` to `Placeholder`
Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
Co-authored-by: Florian Diebold <flodiebold@gmail.com>
3047: Update async unsafe fn ordering in parser r=matklad a=kiljacken
As of rust-lang/rust#61319 the correct order for functions that are both unsafe and async is: `async unsafe fn` and not `unsafe async fn`.
This commit updates the parser tests to reflect this, and corrects parsing behavior to accept the correct ordering.
Fixes#3025
Co-authored-by: Emil Lauridsen <mine809@gmail.com>
3040: Rework value parameter parsing r=matklad a=tobz1000
Fixes#2847.
- `Fn__(...)` parameters with idents/patterns no longer parse
- Trait function parameters with arbitrary patterns parse
- Trait function parameters without idents/patterns no longer parse
- `fn(...)` parameters no longer parse with patterns other than a single ident
__Question__: The pre-existing test `param_list_opt_patterns` has been kept as-is, although the name no longer makes sense (it's testing `Fn__(...)` params, which aren't allowed patterns any more). What would be best to do about this?
Co-authored-by: Toby Dimmick <tobydimmick@pm.me>
As of rust-lang/rust#61319 the correct order for functions that are both
unsafe and async is: `async unsafe fn` and not `unsafe async fn`.
This commit updates the parser tests to reflect this, and corrects
parsing behavior to accept the correct ordering.
Fixes#3025
- `Fn__(...)` parameters with idents/patterns no longer parse
- Trait function parameters with arbitrary patterns parse
- Trait function parameters without idents/patterns no longer parse
- `fn(...)` parameters no longer parse with patterns other than a single ident
This intention is pretty slow for `impl Interator`, because it has a
ton of default methods which need to be substituted.
The proper fix here is to not compute the actual edit until the user
triggers the action, but that's awkward to do in the LSP right now, so
let's just put a profiling code for now.
2962: Differentiate underscore alias from named aliases r=matklad a=zombiefungus
pre for Fixing Issue 2736
edited to avoid autoclosing the issue
Co-authored-by: zombiefungus <divmermarlav@gmail.com>
2959: Rework how we send diagnostics to client r=matklad a=kiljacken
The previous way of sending from the thread pool suffered from stale diagnostics due to being canceled before we could clear the old ones.
The key change is moving to sending diagnostics from the main loop thread, but doing all the hard work in the thread pool. This should provide the best of both worlds, with little to no of the downsides.
This should hopefully fix a lot of issues, but we'll need testing in each individual issue to be sure.
Co-authored-by: Emil Lauridsen <mine809@gmail.com>
The previous way of sending from the thread pool suffered from stale
diagnostics due to being canceled before we could clear the old ones.
The key change is moving to sending diagnostics from the main loop
thread, but doing all the hard work in the thread pool. This should
provide the best of both worlds, with little to no of the downsides.
This should hopefully fix a lot of issues, but we'll need testing in
each individual issue to be sure.
The extra allocation for message should not matter here at all, but
using a static string is just as ergonomic, if not more, and there's
no reason to write deliberately slow code
By default, `spawn` inherits stderr/stdout/stderr of the parent
process, and so, if child, for example does fcntl(O_NONBLOCK), weird
stuff happens to us.
Closes https://github.com/rust-analyzer/lsp-server/pull/10
2920: Better handle illformed node id from metadata r=matklad a=edwin0cheng
In some rare cases, deps node-id from cargo-metadata do not match its version-id, which cause a panic in `cargo-workspace.rs`. This PR try to ignore these ill-formed node id from `cargo-metadata`. An alternative is return `Err` in these cases but I think make it resilience is a better choice here.
Related #2767
Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
2895: Rewrite ra_prof's profile printing r=michalt a=michalt
This changes the way we print things to first construct a mapping from
events to the children and uses that mapping to actually print things.
It should not change the actual output that we produce.
The new approach two benefits:
* It avoids a potential quadratic behavior of the previous approach.
For instance, for a vector of N elements:
```
[Message{level: (N - 1)}, ..., Message{level: 1}, Message{level: 0}]
```
we would first do a linear scan to find entry with level 0, then
another scan to find one with level 1, etc.
* It makes it much easier to improve the output in the future, because
we now pre-compute the children for each entry and can easily take
that into account when printing.
Signed-off-by: Michal Terepeta <michal.terepeta@gmail.com>
Co-authored-by: Michal Terepeta <michal.terepeta@gmail.com>
We previously used serde's stream deserializer to read json blobs from
the cargo output. It has an issue though: If the deserializer encounters
invalid input, it gets stuck reporting the same error again and again
because it is unable to foward over the input until it reaches a new
valid object.
Reading a line at a time and manually deserializing fixes this issue,
because cargo makes sure to only outpu one json blob per line, so should
we encounter invalid input, we can just skip a line and continue.
The main reason this would happen is stray printf-debugging in
procedural macros, so we still report that an error occured, but we
handle it gracefully now.
Fixes#2935
2931: Added documentation to test_utils r=matklad a=Veetaha
Added some doc comments to test_utils functions while studying this crate. They should be all stable enough to document them.
Also some minor code relocation in `parse_fixture()` closer to its usage according to the advice of @matklad.
Co-authored-by: Veetaha <gerzoh1@gmail.com>
2924: Modify ordering of drops in check watcher to only ever have one cargo r=matklad a=kiljacken
Due to the way drops are ordered when assigning to a mutable variable we
were launching a new cargo sub-process before letting the old one quite.
By explicitly replacing the original watcher with a dummy first, we
ensure it is dropped and the process is completed, before we start the
new process.
Co-authored-by: Emil Lauridsen <mine809@gmail.com>
Due to the way drops are ordered when assigning to a mutable variable we
were launching a new cargo sub-process before letting the old one quite.
By explicitly replacing the original watcher with a dummy first, we
ensure it is dropped and the process is completed, before we start the
new process.
2810: Improves reference search by StructLiteral r=mikhail-m1 a=mikhail-m1
Hey, I've made some changes to improve search for struct literals, now it works for `struct Foo<|> {`, `struct Foo <|>{`, `struct Foo<|>(`. Unfortunately tuple creation is represented as a call expression, so for tuples it works only is search is started in a tuple declaration. It leads to incorrect classification of function calls during search phase, but from user perspective it's not visible and works as expected. May be it worth to add a comment or rename it to remove this misleading classification. Issue #2549.
Co-authored-by: Mikhail Modin <mikhailm1@gmail.com>
2887: Initial auto import action implementation r=matklad a=SomeoneToIgnore
Closes https://github.com/rust-analyzer/rust-analyzer/issues/2180
Adds an auto import action implementation.
This implementation is not ideal and has a few limitations:
* The import search functionality should be moved into a separate crate accessible from ra_assists.
This requires a lot of changes and a preliminary design.
Currently the functionality is provided as a trait impl, more on that here: https://github.com/rust-analyzer/rust-analyzer/issues/2180#issuecomment-575690942
* Due to the design desicion from the previous item, no doctests are run for the new aciton (look for a new FIXME in the PR)
* For the same reason, I have to create the mock trait implementaion to test the assist
* Ideally, I think we should have this feature as a diagnostics (that detects an absense of an import) that has a corresponding quickfix action that gets evaluated on demand.
Curretly we perform the import search every time we resolve the import which looks suboptimal.
This requires `classify_name_ref` to be moved from ra_ide, so not done currently.
A few improvements to the imports mechanism to be considered later:
* Constants like `ra_syntax::SyntaxKind::NAME` are not imported, because they are not present in the database
* Method usages are not imported, they are found in the database, but `find_use_path` does not return any import paths for them
* Some import paths returned by the `find_use_path` method end up in `core::` or `alloc::` instead of `std:`, for example: `core::fmt::Debug` instead of `std::fmt::Debug`.
This is not an error techically, but still looks weird.
* No detection of cases where a trait should be imported in order to be able to call a method
* Improve `auto_import_text_edit` functionality: refactor it and move away from the place it is now, add better logic for merging the new import with already existing imports
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
2899: Provide more runners for potential tests r=matklad a=SomeoneToIgnore
Based on the https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Runners.20for.20custom.20test.20annotations discussion.
Adds a test runner for every method that has an annotation that contains `test` word in it, allowing to run tests annotated with custom testing annotations such as `#[tokio::test]`, `#[test_case(...)]` and others at costs of potentially emitting some false-positives.
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
@matklad mentioned this might be a good idea.
So the general idea is that we don't really need the lock, as we can
just clone the check watcher state when creating a snapshot. We can then
use `Arc::get_mut` to get mutable access to the state from `WorldState`
when needed.
Running with this it seems to improve responsiveness a bit while cargo
is running, but I have no hard numbers to prove it. In any case, a
serialization point less is always better when we're trying to be
responsive.
This changes the way we print things to first construct a mapping from
events to the children and uses that mapping to actually print things.
It should not change the actual output that we produce.
The new approach two benefits:
* It avoids a potential quadratic behavior of the previous approach.
For instance, for a vector of N elements:
```
[Message{level: (N - 1)}, ..., Message{level: 1}, Message{level: 0}]
```
we would first do a linear scan to find entry with level 0, then
another scan to find one with level 1, etc.
* It makes it much easier to improve the output in the future, because
we now pre-compute the children for each entry and can easily take
that into account when printing.
Signed-off-by: Michal Terepeta <michal.terepeta@gmail.com>