mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Render closure fn trait kind in siganture help
This commit is contained in:
parent
7c6f31a45b
commit
ff79903cf6
3 changed files with 79 additions and 27 deletions
|
@ -1,5 +1,6 @@
|
||||||
//! Trait solving using Chalk.
|
//! Trait solving using Chalk.
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
use std::env::var;
|
use std::env::var;
|
||||||
|
|
||||||
use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
|
use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
|
||||||
|
@ -209,6 +210,16 @@ pub enum FnTrait {
|
||||||
Fn,
|
Fn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FnTrait {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
FnTrait::FnOnce => write!(f, "FnOnce"),
|
||||||
|
FnTrait::FnMut => write!(f, "FnMut"),
|
||||||
|
FnTrait::Fn => write!(f, "Fn"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FnTrait {
|
impl FnTrait {
|
||||||
const fn lang_item(self) -> LangItem {
|
const fn lang_item(self) -> LangItem {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -2199,7 +2199,7 @@ impl Param {
|
||||||
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
|
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
|
||||||
let parent = match self.func {
|
let parent = match self.func {
|
||||||
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
|
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
|
||||||
Callee::Closure(closure) => db.lookup_intern_closure(closure.into()).0,
|
Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
let body = db.body(parent);
|
let body = db.body(parent);
|
||||||
|
@ -2237,7 +2237,7 @@ impl Param {
|
||||||
}
|
}
|
||||||
.map(|value| InFile { file_id, value })
|
.map(|value| InFile { file_id, value })
|
||||||
}
|
}
|
||||||
Callee::Closure(closure) => {
|
Callee::Closure(closure, _) => {
|
||||||
let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
|
let InternedClosure(owner, expr_id) = db.lookup_intern_closure(closure.into());
|
||||||
let (_, source_map) = db.body_with_source_map(owner);
|
let (_, source_map) = db.body_with_source_map(owner);
|
||||||
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
|
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
|
||||||
|
@ -4316,16 +4316,23 @@ impl Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
||||||
let mut the_ty = &self.ty;
|
|
||||||
let callee = match self.ty.kind(Interner) {
|
let callee = match self.ty.kind(Interner) {
|
||||||
TyKind::Ref(_, _, ty) if ty.as_closure().is_some() => {
|
TyKind::Closure(id, subst) => Callee::Closure(*id, subst.clone()),
|
||||||
the_ty = ty;
|
|
||||||
Callee::Closure(ty.as_closure().unwrap())
|
|
||||||
}
|
|
||||||
TyKind::Closure(id, _) => Callee::Closure(*id),
|
|
||||||
TyKind::Function(_) => Callee::FnPtr,
|
TyKind::Function(_) => Callee::FnPtr,
|
||||||
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
|
TyKind::FnDef(..) => Callee::Def(self.ty.callable_def(db)?),
|
||||||
_ => {
|
kind => {
|
||||||
|
// This branch shouldn't be necessary?
|
||||||
|
if let TyKind::Ref(_, _, ty) = kind {
|
||||||
|
if let TyKind::Closure(closure, subst) = ty.kind(Interner) {
|
||||||
|
let sig = ty.callable_sig(db)?;
|
||||||
|
return Some(Callable {
|
||||||
|
ty: self.clone(),
|
||||||
|
sig,
|
||||||
|
callee: Callee::Closure(*closure, subst.clone()),
|
||||||
|
is_bound_method: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
|
let sig = hir_ty::callable_sig_from_fnonce(&self.ty, self.env.clone(), db)?;
|
||||||
return Some(Callable {
|
return Some(Callable {
|
||||||
ty: self.clone(),
|
ty: self.clone(),
|
||||||
|
@ -4336,7 +4343,7 @@ impl Type {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sig = the_ty.callable_sig(db)?;
|
let sig = self.ty.callable_sig(db)?;
|
||||||
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
|
Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4953,13 +4960,13 @@ pub struct Callable {
|
||||||
sig: CallableSig,
|
sig: CallableSig,
|
||||||
callee: Callee,
|
callee: Callee,
|
||||||
/// Whether this is a method that was called with method call syntax.
|
/// Whether this is a method that was called with method call syntax.
|
||||||
pub(crate) is_bound_method: bool,
|
is_bound_method: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
enum Callee {
|
enum Callee {
|
||||||
Def(CallableDefId),
|
Def(CallableDefId),
|
||||||
Closure(ClosureId),
|
Closure(ClosureId, Substitution),
|
||||||
FnPtr,
|
FnPtr,
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
@ -4968,7 +4975,7 @@ pub enum CallableKind {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
TupleStruct(Struct),
|
TupleStruct(Struct),
|
||||||
TupleEnumVariant(Variant),
|
TupleEnumVariant(Variant),
|
||||||
Closure,
|
Closure(Closure),
|
||||||
FnPtr,
|
FnPtr,
|
||||||
/// Some other type that implements `FnOnce`.
|
/// Some other type that implements `FnOnce`.
|
||||||
Other,
|
Other,
|
||||||
|
@ -4976,14 +4983,17 @@ pub enum CallableKind {
|
||||||
|
|
||||||
impl Callable {
|
impl Callable {
|
||||||
pub fn kind(&self) -> CallableKind {
|
pub fn kind(&self) -> CallableKind {
|
||||||
use Callee::*;
|
|
||||||
match self.callee {
|
match self.callee {
|
||||||
Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
|
Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
|
||||||
Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
|
Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
|
||||||
Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
|
Callee::Def(CallableDefId::EnumVariantId(it)) => {
|
||||||
Closure(_) => CallableKind::Closure,
|
CallableKind::TupleEnumVariant(it.into())
|
||||||
FnPtr => CallableKind::FnPtr,
|
}
|
||||||
Other => CallableKind::Other,
|
Callee::Closure(id, ref subst) => {
|
||||||
|
CallableKind::Closure(Closure { id, subst: subst.clone() })
|
||||||
|
}
|
||||||
|
Callee::FnPtr => CallableKind::FnPtr,
|
||||||
|
Callee::Other => CallableKind::Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
|
pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
|
||||||
|
@ -5004,7 +5014,7 @@ impl Callable {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.skip(if self.is_bound_method { 1 } else { 0 })
|
.skip(if self.is_bound_method { 1 } else { 0 })
|
||||||
.map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
|
.map(|(idx, ty)| (idx, self.ty.derived(ty.clone())))
|
||||||
.map(|(idx, ty)| Param { func: self.callee, idx, ty })
|
.map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
pub fn return_type(&self) -> Type {
|
pub fn return_type(&self) -> Type {
|
||||||
|
|
|
@ -201,7 +201,10 @@ fn signature_help_for_call(
|
||||||
variant.name(db).display(db)
|
variant.name(db).display(db)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
hir::CallableKind::Closure | hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
|
hir::CallableKind::Closure(closure) => {
|
||||||
|
format_to!(res.signature, "impl {}", closure.fn_trait(db));
|
||||||
|
}
|
||||||
|
hir::CallableKind::FnPtr | hir::CallableKind::Other => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
res.signature.push('(');
|
res.signature.push('(');
|
||||||
|
@ -245,7 +248,7 @@ fn signature_help_for_call(
|
||||||
render(func.ret_type(db))
|
render(func.ret_type(db))
|
||||||
}
|
}
|
||||||
hir::CallableKind::Function(_)
|
hir::CallableKind::Function(_)
|
||||||
| hir::CallableKind::Closure
|
| hir::CallableKind::Closure(_)
|
||||||
| hir::CallableKind::FnPtr
|
| hir::CallableKind::FnPtr
|
||||||
| hir::CallableKind::Other => render(callable.return_type()),
|
| hir::CallableKind::Other => render(callable.return_type()),
|
||||||
hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
|
hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {}
|
||||||
|
@ -1348,15 +1351,43 @@ fn test() { S.foo($0); }
|
||||||
r#"
|
r#"
|
||||||
struct S;
|
struct S;
|
||||||
fn foo(s: S) -> i32 { 92 }
|
fn foo(s: S) -> i32 { 92 }
|
||||||
|
fn main() {
|
||||||
|
let _move = S;
|
||||||
|
(|s| {{_move}; foo(s)})($0)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
impl FnOnce(s: S) -> i32
|
||||||
|
^^^^
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct S;
|
||||||
|
fn foo(s: S) -> i32 { 92 }
|
||||||
fn main() {
|
fn main() {
|
||||||
(|s| foo(s))($0)
|
(|s| foo(s))($0)
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
(s: S) -> i32
|
impl Fn(s: S) -> i32
|
||||||
^^^^
|
^^^^
|
||||||
"#]],
|
"#]],
|
||||||
)
|
);
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
struct S;
|
||||||
|
fn foo(s: S) -> i32 { 92 }
|
||||||
|
fn main() {
|
||||||
|
let mut mutate = 0;
|
||||||
|
(|s| { mutate = 1; foo(s) })($0)
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
impl FnMut(s: S) -> i32
|
||||||
|
^^^^
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue