Fall back to parameter definitions on error types in signature help

This commit is contained in:
iDawer 2022-04-23 15:10:10 +05:00
parent 55824021e1
commit fae9049ccd

View file

@ -110,10 +110,12 @@ fn signature_help_for_call(
SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter }; SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter };
let db = sema.db; let db = sema.db;
let mut fn_params = None;
match callable.kind() { match callable.kind() {
hir::CallableKind::Function(func) => { hir::CallableKind::Function(func) => {
res.doc = func.docs(db).map(|it| it.into()); res.doc = func.docs(db).map(|it| it.into());
format_to!(res.signature, "fn {}", func.name(db)); format_to!(res.signature, "fn {}", func.name(db));
fn_params = Some(func.assoc_fn_params(db));
} }
hir::CallableKind::TupleStruct(strukt) => { hir::CallableKind::TupleStruct(strukt) => {
res.doc = strukt.docs(db).map(|it| it.into()); res.doc = strukt.docs(db).map(|it| it.into());
@ -137,7 +139,7 @@ fn signature_help_for_call(
format_to!(res.signature, "{}", self_param) format_to!(res.signature, "{}", self_param)
} }
let mut buf = String::new(); 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(); buf.clear();
if let Some(pat) = pat { if let Some(pat) = pat {
match pat { match pat {
@ -145,7 +147,15 @@ fn signature_help_for_call(
Either::Right(pat) => format_to!(buf, "{}: ", pat), 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); res.push_call_param(&buf);
} }
} }
@ -420,8 +430,8 @@ fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
fn bar() { foo($03, ); } fn bar() { foo($03, ); }
"#, "#,
expect![[r#" 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() { fn test_fn_signature_with_docs_from_actix() {
check( check(
r#" r#"
struct WriteHandler<E>; trait Actor {
/// Actor execution context type
impl<E> WriteHandler<E> { type Context;
/// Method is called when writer emits error. }
/// trait WriteHandler<E>
/// If this method returns `ErrorAction::Continue` writer processing where
/// continues otherwise stream processing stops. Self: Actor
fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running { {
Running::Stop
}
/// Method is called when writer finishes. /// Method is called when writer finishes.
/// ///
/// By default this method stops actor's `Context`. /// By default this method stops actor's `Context`.
fn finished(&mut self, ctx: &mut Self::Context) { fn finished(&mut self, ctx: &mut Self::Context) {}
ctx.stop()
}
} }
pub fn foo(mut r: WriteHandler<()>) { fn foo(mut r: impl WriteHandler<()>) {
r.finished($0); r.finished($0);
} }
"#, "#,
@ -661,8 +666,8 @@ pub fn foo(mut r: WriteHandler<()>) {
By default this method stops actor's `Context`. 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>>)
^^^^^^^^^^^^^^^^^^^^^^
"#]],
);
}
} }