bors[bot] [Thu, 26 Aug 2021 01:34:30 +0000 (01:34 +0000)]
Merge #10030
10030: fix: Fix multiple derives in one attribute not expanding all in expand_macro r=Veykril a=Veykril
It's probably better to only expand the exact derive the cursor is on(if possible) instead of all derives in the attribute the cursor is one.
follow up to #10029
bors r+
- Adds a few more newlines to the output making it more readable
- Fixes a bug with multiple derives not being expandable
There seems to be an issue with multiple derives in one attribute only showing the expansion of the last derive which I'll have to investigate.
bors r+
bors[bot] [Tue, 24 Aug 2021 14:58:02 +0000 (14:58 +0000)]
Merge #10014
10014: feat: Expand derive macros under cursor in `Expand Macro Recursively` r=Veykril a=Veykril
Expands the derive macros under the cursor if it is one a derive attribute, with this the feature should be basically feature complete I believe(except for the whitespace problem ofc)?
Actually this might interact a bit funky with items that have attributes ***and*** derives since we don't descend the cursor token into macro invocations first, for obvious reasons. So I expected trying to expand a derive in that case will either just expand the attributes on the item or fail in general.
bors[bot] [Mon, 23 Aug 2021 22:19:50 +0000 (22:19 +0000)]
Merge #10001
10001: Sort enum variant r=Veykril a=vsrs
A small fix to the problem noted by `@lnicola` :
> ![sort-fields](https://user-images.githubusercontent.com/308347/129513196-4ffc7937-be58-44d4-9ec7-ba8745dcb460.gif)
>
> (note the slight inconsistency here: to sort the variants of `Animal` I have to select the enum name, but to sort the fields of `Cat` I have to select the fields themselves)
Aleksey Kladov [Mon, 23 Aug 2021 18:07:23 +0000 (21:07 +0300)]
:arrow_up: rowan
This pulls in https://github.com/rust-analyzer/rowan/pull/111, which
fixes a bug in green node hash, making it more efficient.
On analysis stats, total memory goes from 1271mb to 1244mb, instructions
from 358ginstr to 353ginstr (not 100% clear on this one -- for some
reasons instruction counts are not stable for me anymore).
bors[bot] [Sun, 22 Aug 2021 12:25:18 +0000 (12:25 +0000)]
Merge #9979
9979: fix: Incorrect up-mapping for tokens in derive attributes r=Veykril a=Veykril
Merely detaching the attributes causes incorrect spans to appear when mapping tokens up as the token ids resolve to the ranges of the stripped item so all the text ranges of its tokens are actually lower than the non-stripped ones.
Same fix as with attributes can be applied here, just replace the derive attribute with an equal amount of whitespace.
Aleksey Kladov [Sun, 22 Aug 2021 10:32:00 +0000 (13:32 +0300)]
internal: reduce crate interdependence
I don't think there's anything wrong with project_model depending on
proc_macro_api directly -- fundamentally, both are about gluing our pure
data model to the messy outside world.
However, it's easy enough to avoid the dependency, so why not.
As an additional consideration, `proc_macro_api` now pulls in `base_db`.
project_model should definitely not depend on that!
bors[bot] [Sat, 21 Aug 2021 10:12:17 +0000 (10:12 +0000)]
Merge #9962
9962: Add empty-body check to replace_match_with_if_let and re-prioritize choices r=elkowar a=elkowar
This PR changes some behaviour of the `replace_match_with_if_let` ide-assist.
Concretely, it makes two changes:
it introduces a check for empty expression bodies. This means that checks of the shape
```rs
match x {
A => {}
B => {
println!("hi");
}
}
```
will prefer to use the B branch as the first (and only) variant.
It also reprioritizes the importance of "happy" and "sad" patterns.
Concretely, if there are reasons to prefer having the sad pattern be the first (/only) pattern,
it will follow these.
This means that in the case of
```rs
match x {
Ok(_) => {
println!("Success");
}
Err(e) => {
println!("Failure: {}", e);
}
}
```
the `Err` variant will correctly be used as the first expression in the generated if.
Up until now, the generated code was actually invalid, as it would generate
```rs
if let Ok(_) = x {
println!("Success");
} else {
println!("Failure: {}", e);
}
```
where `e` in the else branch is not defined.
bors[bot] [Fri, 20 Aug 2021 11:57:28 +0000 (11:57 +0000)]
Merge #9943
9943: fix: Do not replace items annotated with builtin attrs with the attr input r=Veykril a=Veykril
This causes runnables to work for paths that actually resolve to the `test` attribute now.
![Code_aUhX1KQfw3](https://user-images.githubusercontent.com/3757771/129917168-bd9ed3f8-3a08-49d2-930a-4b93efaa8acf.png)
Prior to this we replaced items annotated with builtin attributes by the attribute input instead of the item in our dummy expansion which is why the fully written path didn't work as we actually discarded the item while `test` was just ignored.
Part of #8673. This PR only handles tuples, not TupleStruct and RecordStruct.
Code Assist to destructure a tuple into its items:
![Destructure_Tuple_Assist](https://user-images.githubusercontent.com/15612932/129020107-775d7c94-dca7-4d1f-a0a2-cd63cabf4132.gif)
* Should work in nearly all pattern positions, like let assignment, function parameters, match arms, for loops, and nested variables (`if let Some($0t) = Some((1,2))`)
-> everywhere `IdentPat` is allowed
* Exception: If there's a sub-pattern (``@`):`
```rust
if let t @ (1..=3, 1..=3) = ... {}
// ^
```
-> `t` must be a `Name`; `TuplePat` (`(_0, _1)`) isn't allowed
* inside subpattern is ok:
```rust
let t @ (a, _) = ((1,2), 3);
// ^
```
->
```rust
let t @ ((_0, _1), _) = ((1,2), 3);
```
* Assist triggers only at tuple declaration, not tuple usage.
(might be useful especially when it creates a sub-pattern (after ``@`)` and only changes the usage under cursor -- but not part of this PR).
### References
References can be destructured:
```rust
let t = &(1,2);
// ^
let v = t.0;
```
->
```rust
let (_0, _1) = &(1,2);
let v = _0;
```
BUT: `t.0` and `_0` have different types (`i32` vs. `&i32`) -> `v` has now a different type.
I think that's acceptable: I think the destructure assist is mostly used in simple, immediate scopes and not huge existing code.
Additional Notes:
* `ref` has same behaviour (-> `ref` is kept for items)
```rust
let ref t = (1,2);
// ^
```
->
```rust
let (ref _0, ref _1) = (1,2);
```
* Rust IntelliJ Plugin: doesn't trigger with `&` or `ref` at all
### mutable
```rust
let mut t = (1,2);
// ^
```
->
```rust
let (mut _0, mut _1) = (1,2);
```
and
```rust
let t = &mut (1,2);
// ^
```
->
```rust
let (_0, _1) = &mut (1,2);
```
Again: with reference (`&mut`), `t.0` and `_0` have different types (`i32` vs `&mut i32`).
And there's an additional issue with `&mut` and assignment:
```rust
let t = &mut (1,2);
// ^
t.0 = 9;
```
->
```rust
let (_0, _1) = &mut (1,2);
_0 = 9;
// ^
// mismatched types
// expected `&mut {integer}`, found integer
// consider dereferencing here to assign to the mutable borrowed piece of memory
```
But I think that's quite a niche use case, so I don't catch that (`*_0 = 9;`)
Additional Notes:
* Rust IntelliJ Plugin: removes the `mut` (`let mut t = ...` -> `let (_0, _1) = ...`), doesn't trigger with `&mut`
### Binding after ``@``
Destructure tuple in sub-pattern is implemented:
```rust
let t = (1,2);
// ^
let v = t.0;
let f = t.into();
```
->
```rust
let t @ (_0, _1) = (1,2);
let v = _0;
let f = t.into();
```
BUT: Bindings after ``@`` aren't currently in stable and require `#![feature(bindings_after_at)]` (though should be generally [available quite soon](https://github.com/rust-lang/rust/pull/85305#event-5072889913) (with `1.56.0`)).
But I don't know how to check for an enabled feature -> Destructure tuple in sub-pattern [isn't enabled](https://github.com/Booksbaum/rust-analyzer/blob/a4ee6c7954f910da3ca74fc0e25edda9077ad184/crates/ide_assists/src/handlers/destructure_tuple_binding.rs#L32) yet.
* When Destructure in sub-pattern is enabled there are two assists:
* `Destructure tuple in place`:
```rust
let t = (1,2);
// ^
```
->
```rust
let (_0, _1) = (1,2);
let v = _0;
let f = /*t*/.into();
```
* `Destructure tuple in sub-pattern`:
```rust
let t = (1,2);
// ^
let v = t.0;
let f = t.into();
```
->
```rust
let t @ (_0, _1) = (1,2);
let v = _0;
let f = t.into();
```
* When Destructure in sub-pattern is disabled, only the first one is available and just named `Destructure tuple`
<br/>
<br/>
### Caveats
* Unlike in #8673 or IntelliJ rust plugin, I'm not leaving the previous tuple name at function calls.
**Reasoning**: It's not too unlikely the tuple variable shadows another variable. Destructuring the tuple while leaving the function call untouched, results in still a valid function call -- but now with another variable:
```rust
let t = (8,9);
let t = (1,2);
// ^
t.into()
```
=> Destructure Tuple
```rust
let t = (8,9);
let (_0, _1) = (1,2);
t.into()
```
`t.into()` is still valid -- using the first tuple.
Instead I comment out the tuple usage, which results in invalid code -> must be handled by user:
```rust
/*t*/.into()
```
* (though that might be a biased decision: For testing I just declared a lot of `t`s and quite ofen in lines next to each other...)
* Issue: there are some cases that results in still valid code:
* macro that accept the tuple as well as no arguments:
```rust
macro_rules! m {
() => { "foo" };
($e:expr) => { $e; "foo" };
}
let t = (1,2);
m!(t);
m!(/*t*/);
```
-> both calls are valid ([test](https://github.com/Booksbaum/rust-analyzer/blob/a4ee6c7954f910da3ca74fc0e25edda9077ad184/crates/ide_assists/src/handlers/destructure_tuple_binding.rs#L1474))
* Probably with tuple as return value. Changing the return value most likely results in an error -- but in another place; not where the tuple usage was.
-> not sure that's the best way....
Additional the tuple name surrounded by comment is more difficult to edit than just the name.
* Code Assists don't support snippet placeholder, and rust analyzer just the first `$0` -> unfortunately no editing of generated tuple item variables. Cursor (`$0`) is placed on first generated item.
<br/>
<br/>
### Issues
* Tuple index usage in macro calls aren't converted:
```rust
let t = (1,2);
// ^
let v = t.0;
println!("{}", t.0);
```
->
```rust
let (_0, _1) = (1,2);
let v = _0;
println!("{}", /*t*/.0);
```
([tests](https://github.com/Booksbaum/rust-analyzer/blob/a4ee6c7954f910da3ca74fc0e25edda9077ad184/crates/ide_assists/src/handlers/destructure_tuple_binding.rs#L1294))
* Issue is:
[name.syntax()](https://github.com/Booksbaum/rust-analyzer/blob/a4ee6c7954f910da3ca74fc0e25edda9077ad184/crates/ide_assists/src/handlers/destructure_tuple_binding.rs#L242-L244) in each [usage](https://github.com/Booksbaum/rust-analyzer/blob/a4ee6c7954f910da3ca74fc0e25edda9077ad184/crates/ide_assists/src/handlers/destructure_tuple_binding.rs#L108-L113) of a tuple is syntax & text_range in its file.
EXCEPT when tuple usage is in a macro call (`m!(t.0)`), the macro is expanded and syntax (and range) is based on that expanded macro, not in actual file.
That leads to several things:
* I cannot differentiate between calling the macro with the tuple or with tuple item:
```rust
macro_rules! m {
($t:expr, $i:expr) => { $t.0 + $i };
}
let t = (1,2);
m!(t, t.0);
```
-> both `t` usages are resolved as tuple index usage
* Range of resolved tuple index usage is in expanded macro, not in actual file
-> don't know where to replace index usage
-> tuple items passed into a macro are ignored, and only the tuple name itself is handled (uncommented)
* I'm not checking if the generated names conflict with already existing variables.
```rust
let _0 = 42; // >-|
let t = (1,2); // |
let v = _0; // <-|
// ^ 42
```
=> deconstruct tuple
```rust
let _0 = 42;
let (_0, _1) = (1,2); // >-|
let v = _0; // <-|
// ^ now 1
```
* I tried to get the scope at tuple declaration and its usages. And then iterate all names with [`process_all_names`](https://github.com/rust-analyzer/rust-analyzer/blob/145b51f9daf5371f1754c09eb2e3a77e0a24a0dc/crates/hir/src/semantics.rs#L935). But that doesn't find all local names for declarations (`let t = (1,2)`) (for usages it does)
* This isn't unique to this Code Assist, but happen in others too (like `extract into variable` or `extract into function`). But here a name conflict is more likely (when destructuring multiple tuples, for examples nested ones (`let t = ((1,2),3)` -> `let (_0, _1) = ...` -> `let ((_0, _1), _1) = ...` -> error))
* IntelliJ rust plugin does handle this (-> name is `_00`)
bors[bot] [Thu, 19 Aug 2021 11:31:46 +0000 (11:31 +0000)]
Merge #9950
9950: Fix codegen for is_method documentation r=yoshuawuyts a=yoshuawuyts
While authoring https://github.com/rust-lang/rust/pull/88154 I realized that the codegen for the `enum_generate_is_method` assist currently generates invalid paths, and used snake case instead of spaces for the docs description. This fixes both issues. Thanks!