Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/signature_help.rs')
-rw-r--r--crates/ide/src/signature_help.rs66
1 files changed, 45 insertions, 21 deletions
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 6dc8b3046c..2ca933ec3e 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -110,10 +110,12 @@ fn signature_help_for_call(
SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter };
let db = sema.db;
+ let mut fn_params = None;
match callable.kind() {
hir::CallableKind::Function(func) => {
res.doc = func.docs(db).map(|it| it.into());
format_to!(res.signature, "fn {}", func.name(db));
+ fn_params = Some(func.assoc_fn_params(db));
}
hir::CallableKind::TupleStruct(strukt) => {
res.doc = strukt.docs(db).map(|it| it.into());
@@ -137,7 +139,7 @@ fn signature_help_for_call(
format_to!(res.signature, "{}", self_param)
}
let mut buf = String::new();
- for (pat, ty) in callable.params(db) {
+ for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
buf.clear();
if let Some(pat) = pat {
match pat {
@@ -145,7 +147,15 @@ fn signature_help_for_call(
Either::Right(pat) => format_to!(buf, "{}: ", pat),
}
}
- format_to!(buf, "{}", ty.display(db));
+ // APITs (argument position `impl Trait`s) are inferred as {unknown} as the user is
+ // in the middle of entering call arguments.
+ // In that case, fall back to render definition of the argument.
+ // This is overly conservative: we do not substitute known type vars
+ // (see FIXME in tests::impl_trait).
+ match (ty.contains_unknown(), fn_params.as_deref()) {
+ (true, Some(fn_params)) => format_to!(buf, "{}", fn_params[idx].ty().display(db)),
+ _ => format_to!(buf, "{}", ty.display(db)),
+ }
res.push_call_param(&buf);
}
}
@@ -420,8 +430,8 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
fn bar() { foo($03, ); }
"#,
expect![[r#"
- fn foo(x: i32, y: {unknown}) -> u32
- ^^^^^^ ------------
+ fn foo(x: i32, y: U) -> u32
+ ^^^^^^ ----
"#]],
);
}
@@ -633,26 +643,21 @@ pub fn do_it() {
fn test_fn_signature_with_docs_from_actix() {
check(
r#"
-struct WriteHandler<E>;
-
-impl<E> WriteHandler<E> {
- /// Method is called when writer emits error.
- ///
- /// If this method returns `ErrorAction::Continue` writer processing
- /// continues otherwise stream processing stops.
- fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
- Running::Stop
- }
-
+trait Actor {
+ /// Actor execution context type
+ type Context;
+}
+trait WriteHandler<E>
+where
+ Self: Actor
+{
/// Method is called when writer finishes.
///
/// By default this method stops actor's `Context`.
- fn finished(&mut self, ctx: &mut Self::Context) {
- ctx.stop()
- }
+ fn finished(&mut self, ctx: &mut Self::Context) {}
}
-pub fn foo(mut r: WriteHandler<()>) {
+fn foo(mut r: impl WriteHandler<()>) {
r.finished($0);
}
"#,
@@ -661,8 +666,8 @@ pub fn foo(mut r: WriteHandler<()>) {
By default this method stops actor's `Context`.
------
- fn finished(&mut self, ctx: &mut {unknown})
- ^^^^^^^^^^^^^^^^^^^
+ fn finished(&mut self, ctx: &mut <impl WriteHandler<()> as Actor>::Context)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"#]],
);
}
@@ -1055,4 +1060,23 @@ fn f() {
"#]],
);
}
+
+ #[test]
+ fn impl_trait() {
+ // FIXME: Substitute type vars in impl trait (`U` -> `i8`)
+ check(
+ r#"
+trait Trait<T> {}
+struct Wrap<T>(T);
+fn foo<U>(x: Wrap<impl Trait<U>>) {}
+fn f() {
+ foo::<i8>($0)
+}
+"#,
+ expect![[r#"
+ fn foo(x: Wrap<impl Trait<U>>)
+ ^^^^^^^^^^^^^^^^^^^^^^
+ "#]],
+ );
+ }
}