Skip to content

completions: Add rudimentary support for closure completions#21683

Open
osiewicz wants to merge 6 commits intorust-lang:masterfrom
osiewicz:closure-completions
Open

completions: Add rudimentary support for closure completions#21683
osiewicz wants to merge 6 commits intorust-lang:masterfrom
osiewicz:closure-completions

Conversation

@osiewicz
Copy link
Copy Markdown
Contributor

@osiewicz osiewicz commented Feb 20, 2026

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.

@osiewicz osiewicz force-pushed the closure-completions branch 2 times, most recently from 482555b to 815a349 Compare February 20, 2026 10:56
@osiewicz osiewicz marked this pull request as ready for review February 20, 2026 11:40
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 20, 2026
@rustbot

This comment has been minimized.

dinocosta and others added 4 commits February 20, 2026 12:42
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>
Co-authored-by: dino <dinojoaocosta@gmail.com>
@osiewicz osiewicz force-pushed the closure-completions branch from 4d5c11c to 1a36b43 Compare February 20, 2026 11:43
osiewicz and others added 2 commits February 20, 2026 13:01
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);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you consider using NameGenerator to generate parameters?
Just like a |x0, x1, items|

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could do that, yes.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 20, 2026

☔ The latest upstream changes (possibly #21768) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Copy Markdown
Contributor

@ChayimFriedman2 ChayimFriedman2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also use NameGenerator like @A4-Tacks has said.

View changes since this review

Comment thread crates/hir/src/lib.rs
}

/// Returns the generic substitution for this callable, if it is a function.
pub fn substitution(&self) -> Option<GenericSubstitution<'db>> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's that?

}

if trigger_character == Some('|') {
// 2026-02-13T11:30:41.704583Z ERROR CompletionAnalysis: Name(NameContext {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

}
return Some(completions.into());
}
tracing::error!("CompletionAnalysis: {:?}", &analysis);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this?

Comment on lines +248 to +251
// 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();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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.

Comment on lines +253 to +255
if !generic_param_ty.impls_fnonce(ctx.db) {
return None;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have stdx::format_to!().

@ChayimFriedman2
Copy link
Copy Markdown
Contributor

@osiewicz, What's the status of this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants