5846: Add references to fn args during completion r=matklad a=adamrk

When completing a function call, if there is an argument taken as a ref or mut ref which matches the name and type of a variable in scope, we will insert a `&` or `&mut` when filling in the function arguments. This addresses https://github.com/rust-analyzer/rust-analyzer/issues/5449.

E.g. 
```rust
fn foo(x: &i32) {}
fn main() {
  let x = 5;
  foo # completing foo here generates `foo(&x)` now instead of `foo(x)`
}
```

Co-authored-by: adamrk <ark.email@gmail.com>
This commit is contained in:
bors[bot] 2020-09-24 12:23:28 +00:00 committed by GitHub
commit 9d3483a74d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 161 additions and 8 deletions

View file

@ -709,11 +709,23 @@ impl Function {
}
pub fn params(self, db: &dyn HirDatabase) -> Vec<Param> {
let resolver = self.id.resolver(db.upcast());
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
let environment = TraitEnvironment::lower(db, &resolver);
db.function_data(self.id)
.params
.iter()
.skip(if self.self_param(db).is_some() { 1 } else { 0 })
.map(|_| Param { _ty: () })
.map(|type_ref| {
let ty = Type {
krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate,
ty: InEnvironment {
value: Ty::from_hir_ext(&ctx, type_ref).0,
environment: environment.clone(),
},
};
Param { ty }
})
.collect()
}
@ -742,15 +754,21 @@ impl From<Mutability> for Access {
}
}
pub struct Param {
ty: Type,
}
impl Param {
pub fn ty(&self) -> &Type {
&self.ty
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SelfParam {
func: FunctionId,
}
pub struct Param {
_ty: (),
}
impl SelfParam {
pub fn access(self, db: &dyn HirDatabase) -> Access {
let func_data = db.function_data(self.func);
@ -1276,6 +1294,14 @@ impl Type {
)
}
pub fn remove_ref(&self) -> Option<Type> {
if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(_), .. }) = self.ty.value {
self.ty.value.substs().map(|substs| self.derived(substs[0].clone()))
} else {
None
}
}
pub fn is_unknown(&self) -> bool {
matches!(self.ty.value, Ty::Unknown)
}