Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 2b1c1a9

Browse files
committed
feat: hide type inlay hints for initializations of closures
1 parent 44be090 commit 2b1c1a9

File tree

5 files changed

+90
-5
lines changed

5 files changed

+90
-5
lines changed

crates/ide/src/inlay_hints.rs

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct InlayHintsConfig {
2626
pub lifetime_elision_hints: LifetimeElisionHints,
2727
pub param_names_for_lifetime_elision_hints: bool,
2828
pub hide_named_constructor_hints: bool,
29+
pub hide_closure_initialization_hints: bool,
2930
pub max_length: Option<usize>,
3031
pub closing_brace_hints_min_lines: Option<usize>,
3132
}
@@ -467,10 +468,11 @@ fn closure_ret_hints(
467468
return None;
468469
}
469470

470-
let param_list = match closure.body() {
471-
Some(ast::Expr::BlockExpr(_)) => closure.param_list()?,
472-
_ => return None,
473-
};
471+
if !closure_has_block_body(&closure) {
472+
return None;
473+
}
474+
475+
let param_list = closure.param_list()?;
474476

475477
let closure = sema.descend_node_into_attributes(closure.clone()).pop()?;
476478
let ty = sema.type_of_expr(&ast::Expr::ClosureExpr(closure))?.adjusted();
@@ -693,7 +695,7 @@ fn bind_pat_hints(
693695
let desc_pat = descended.as_ref().unwrap_or(pat);
694696
let ty = sema.type_of_pat(&desc_pat.clone().into())?.original;
695697

696-
if should_not_display_type_hint(sema, pat, &ty) {
698+
if should_not_display_type_hint(sema, config, pat, &ty) {
697699
return None;
698700
}
699701

@@ -848,6 +850,7 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir
848850

849851
fn should_not_display_type_hint(
850852
sema: &Semantics<RootDatabase>,
853+
config: &InlayHintsConfig,
851854
bind_pat: &ast::IdentPat,
852855
pat_ty: &hir::Type,
853856
) -> bool {
@@ -863,6 +866,18 @@ fn should_not_display_type_hint(
863866
}
864867
}
865868

869+
if config.hide_closure_initialization_hints {
870+
if let Some(parent) = bind_pat.syntax().parent() {
871+
if let Some(it) = ast::LetStmt::cast(parent.clone()) {
872+
if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
873+
if closure_has_block_body(&closure) {
874+
return true;
875+
}
876+
}
877+
}
878+
}
879+
}
880+
866881
for node in bind_pat.syntax().ancestors() {
867882
match_ast! {
868883
match node {
@@ -889,6 +904,10 @@ fn should_not_display_type_hint(
889904
false
890905
}
891906

907+
fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
908+
matches!(closure.body(), Some(ast::Expr::BlockExpr(_)))
909+
}
910+
892911
fn should_hide_param_name_hint(
893912
sema: &Semantics<RootDatabase>,
894913
callable: &hir::Callable,
@@ -1083,6 +1102,7 @@ mod tests {
10831102
reborrow_hints: ReborrowHints::Always,
10841103
binding_mode_hints: false,
10851104
hide_named_constructor_hints: false,
1105+
hide_closure_initialization_hints: false,
10861106
param_names_for_lifetime_elision_hints: false,
10871107
max_length: None,
10881108
closing_brace_hints_min_lines: None,
@@ -2034,6 +2054,53 @@ fn main() {
20342054
);
20352055
}
20362056

2057+
#[test]
2058+
fn skip_closure_type_hints() {
2059+
check_with_config(
2060+
InlayHintsConfig {
2061+
type_hints: true,
2062+
hide_closure_initialization_hints: true,
2063+
..DISABLED_CONFIG
2064+
},
2065+
r#"
2066+
//- minicore: fn
2067+
fn main() {
2068+
let multiple_2 = |x: i32| { x * 2 };
2069+
2070+
let multiple_2 = |x: i32| x * 2;
2071+
// ^^^^^^^^^^ |i32| -> i32
2072+
2073+
let (not) = (|x: bool| { !x });
2074+
// ^^^ |bool| -> bool
2075+
2076+
let (is_zero, _b) = (|x: usize| { x == 0 }, false);
2077+
// ^^^^^^^ |usize| -> bool
2078+
// ^^ bool
2079+
2080+
let plus_one = |x| { x + 1 };
2081+
// ^ u8
2082+
foo(plus_one);
2083+
2084+
let add_mul = bar(|x: u8| { x + 1 });
2085+
// ^^^^^^^ impl FnOnce(u8) -> u8 + ?Sized
2086+
2087+
let closure = if let Some(6) = add_mul(2).checked_sub(1) {
2088+
// ^^^^^^^ fn(i32) -> i32
2089+
|x: i32| { x * 2 }
2090+
} else {
2091+
|x: i32| { x * 3 }
2092+
};
2093+
}
2094+
2095+
fn foo(f: impl FnOnce(u8) -> u8) {}
2096+
2097+
fn bar(f: impl FnOnce(u8) -> u8) -> impl FnOnce(u8) -> u8 {
2098+
move |x: u8| f(x) * 2
2099+
}
2100+
"#,
2101+
);
2102+
}
2103+
20372104
#[test]
20382105
fn hint_truncation() {
20392106
check_with_config(

crates/ide/src/static_index.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ impl StaticIndex<'_> {
113113
lifetime_elision_hints: crate::LifetimeElisionHints::Never,
114114
reborrow_hints: crate::ReborrowHints::Never,
115115
hide_named_constructor_hints: false,
116+
hide_closure_initialization_hints: false,
116117
param_names_for_lifetime_elision_hints: false,
117118
binding_mode_hints: false,
118119
max_length: Some(25),

crates/rust-analyzer/src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ config_data! {
281281
inlayHints_renderColons: bool = "true",
282282
/// Whether to show inlay type hints for variables.
283283
inlayHints_typeHints_enable: bool = "true",
284+
/// Whether to hide inlay type hints for `let` statements that initialize to a closure.
285+
/// Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
286+
inlayHints_typeHints_hideClosureInitialization: bool = "false",
284287
/// Whether to hide inlay type hints for constructors.
285288
inlayHints_typeHints_hideNamedConstructor: bool = "false",
286289

@@ -1000,6 +1003,9 @@ impl Config {
10001003
LifetimeElisionDef::SkipTrivial => ide::LifetimeElisionHints::SkipTrivial,
10011004
},
10021005
hide_named_constructor_hints: self.data.inlayHints_typeHints_hideNamedConstructor,
1006+
hide_closure_initialization_hints: self
1007+
.data
1008+
.inlayHints_typeHints_hideClosureInitialization,
10031009
reborrow_hints: match self.data.inlayHints_reborrowHints_enable {
10041010
ReborrowHintsDef::Always => ide::ReborrowHints::Always,
10051011
ReborrowHintsDef::Never => ide::ReborrowHints::Never,

docs/user/generated_config.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ Whether to render leading colons for type hints, and trailing colons for paramet
407407
--
408408
Whether to show inlay type hints for variables.
409409
--
410+
[[rust-analyzer.inlayHints.typeHints.hideClosureInitialization]]rust-analyzer.inlayHints.typeHints.hideClosureInitialization (default: `false`)::
411+
+
412+
--
413+
Whether to hide inlay type hints for `let` statements that initialize to a closure.
414+
Only applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.
415+
--
410416
[[rust-analyzer.inlayHints.typeHints.hideNamedConstructor]]rust-analyzer.inlayHints.typeHints.hideNamedConstructor (default: `false`)::
411417
+
412418
--

editors/code/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,11 @@
868868
"default": true,
869869
"type": "boolean"
870870
},
871+
"rust-analyzer.inlayHints.typeHints.hideClosureInitialization": {
872+
"markdownDescription": "Whether to hide inlay type hints for `let` statements that initialize to a closure.\nOnly applies to closures with blocks, same as `#rust-analyzer.inlayHints.closureReturnTypeHints.enable#`.",
873+
"default": false,
874+
"type": "boolean"
875+
},
871876
"rust-analyzer.inlayHints.typeHints.hideNamedConstructor": {
872877
"markdownDescription": "Whether to hide inlay type hints for constructors.",
873878
"default": false,

0 commit comments

Comments
 (0)