mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Fall back to parameter definitions on error types in signature help
This commit is contained in:
parent
55824021e1
commit
fae9049ccd
1 changed files with 45 additions and 21 deletions
|
@ -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.
|
|
||||||
///
|
|
||||||
/// 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 WriteHandler<E>
|
||||||
|
where
|
||||||
|
Self: Actor
|
||||||
|
{
|
||||||
/// 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>>)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue