Unnamed repository; edit this file 'description' to name the repository.
Fix expected type no strip deref
Example
---
```rust
fn main() {
let r = &2;
let _: fn() -> i32 = || *$0;
}
```
**Before this PR**
`ty: &'_ u32, name: x`
```rust
fn main() {
let r = &2;
let _: fn() -> i32 = || **r;
}
```
**After this PR**
`ty: &'_ &'_ u32, name: x`
```rust
fn main() {
let r = &2;
let _: fn() -> i32 = || *r;
}
```
| -rw-r--r-- | crates/ide-completion/src/context/analysis.rs | 18 | ||||
| -rw-r--r-- | crates/ide-completion/src/context/tests.rs | 12 |
2 files changed, 29 insertions, 1 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index add637a16f..b65c68a240 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -600,10 +600,26 @@ fn expected_type_and_name<'db>( Some(it) => it, None => return ty, }; - for _ in top_syn.ancestors().skip(1).map_while(ast::RefExpr::cast) { + let refs_level = top_syn + .ancestors() + .skip(1) + .map_while(Either::<ast::RefExpr, ast::PrefixExpr>::cast) + .take_while(|it| match it { + Either::Left(_) => true, + Either::Right(prefix) => prefix.op_kind() == Some(ast::UnaryOp::Deref), + }) + .fold(0i32, |level, expr| match expr { + Either::Left(_) => level + 1, + Either::Right(_) => level - 1, + }); + for _ in 0..refs_level { cov_mark::hit!(expected_type_fn_param_ref); ty = ty.strip_reference(); } + for _ in refs_level..0 { + cov_mark::hit!(expected_type_fn_param_deref); + ty = ty.add_reference(hir::Mutability::Shared); + } ty } _ => ty, diff --git a/crates/ide-completion/src/context/tests.rs b/crates/ide-completion/src/context/tests.rs index 41f0db3c52..b929d36ce6 100644 --- a/crates/ide-completion/src/context/tests.rs +++ b/crates/ide-completion/src/context/tests.rs @@ -147,6 +147,18 @@ fn bar(x: &u32) {} } #[test] +fn expected_type_fn_param_deref() { + cov_mark::check!(expected_type_fn_param_deref); + check_expected_type_and_name( + r#" +fn foo() { bar(*$0); } +fn bar(x: &u32) {} +"#, + expect!["ty: &'_ &'_ u32, name: x"], + ); +} + +#[test] fn expected_type_struct_field_without_leading_char() { cov_mark::check!(expected_type_struct_field_without_leading_char); check_expected_type_and_name( |