completions: Add rudimentary support for closure completions#21683
completions: Add rudimentary support for closure completions#21683osiewicz wants to merge 6 commits intorust-lang:masterfrom
Conversation
482555b to
815a349
Compare
This comment has been minimized.
This comment has been minimized.
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
4d5c11c to
1a36b43
Compare
parameter Co-authored-by: dino <dinojoaocosta@gmail.com>
Co-authored-by: dino <dinojoaocosta@gmail.com>
| r#" | ||
| fn foo<T>(f: impl Fn(T) -> T) {} | ||
| fn main() { | ||
| foo(|${1:_}: ${2:T}| $0); |
There was a problem hiding this comment.
Don't you consider using NameGenerator to generate parameters?
Just like a |x0, x1, items|
There was a problem hiding this comment.
I guess we could do that, yes.
|
☔ The latest upstream changes (possibly #21768) made this pull request unmergeable. Please resolve the merge conflicts. |
There was a problem hiding this comment.
Please also use NameGenerator like @A4-Tacks has said.
| } | ||
|
|
||
| /// Returns the generic substitution for this callable, if it is a function. | ||
| pub fn substitution(&self) -> Option<GenericSubstitution<'db>> { |
There was a problem hiding this comment.
This should return the substitution for struct/enum constructors as well, even if not needed by this PR, for good measure.
| Some(items) => items, | ||
| }; | ||
|
|
||
| tracing::error!("{:?}", &items); |
| } | ||
|
|
||
| if trigger_character == Some('|') { | ||
| // 2026-02-13T11:30:41.704583Z ERROR CompletionAnalysis: Name(NameContext { |
| } | ||
| return Some(completions.into()); | ||
| } | ||
| tracing::error!("CompletionAnalysis: {:?}", &analysis); |
| // Use the absolute index (which includes self) to index into assoc_fn_params, | ||
| // so that method calls with self don't cause an off-by-one. | ||
| let abs_index = callable.params().into_iter().nth(index)?.index(); | ||
| let generic_param_ty = fun.assoc_fn_params(ctx.db).into_iter().nth(abs_index)?.ty().clone(); |
There was a problem hiding this comment.
| // Use the absolute index (which includes self) to index into assoc_fn_params, | |
| // so that method calls with self don't cause an off-by-one. | |
| let abs_index = callable.params().into_iter().nth(index)?.index(); | |
| let generic_param_ty = fun.assoc_fn_params(ctx.db).into_iter().nth(abs_index)?.ty().clone(); | |
| let generic_param_ty = fun.assoc_fn_params(ctx.db)[index + if is_method_call_syntax { 1 } else { 0 }].clone(); |
Simpler and more obvious, IMO.
| if !generic_param_ty.impls_fnonce(ctx.db) { | ||
| return None; | ||
| } |
There was a problem hiding this comment.
| if !generic_param_ty.impls_fnonce(ctx.db) { | |
| return None; | |
| } |
Can remove this, as_callable() will take care of that.
| let mut label = String::from("|"); | ||
| let mut snippet = String::new(); | ||
| let mut plain = String::new(); | ||
| let mut tab_stop = 1; |
There was a problem hiding this comment.
When I write a closure, I first write the param names then the body. This also makes more sense since the body depends on the param names. So I think this should start from 0.
|
|
||
| if needs_annotation { | ||
| if let Ok(ty_str) = ty.display_source_code(ctx.db, module, true) { | ||
| write!(label, "{sep}_: {ty_str}").unwrap(); |
There was a problem hiding this comment.
We have stdx::format_to!().
|
@osiewicz, What's the status of this? |
Related to #8676
Related to #9444
CleanShot.2026-02-20.at.11.35.29.mp4
Closure parameter names are a bit wacky, but they've been that way even before this PR; we should probably filter out suggestions for patterns that cannot actually be destructured.