Compute closure captures

This commit is contained in:
hkalbasi 2023-04-06 16:14:38 +03:30
parent 51d5862caf
commit 59b6f2d9f2
42 changed files with 2537 additions and 433 deletions

View file

@ -225,7 +225,7 @@ fn main() {
*iter*
```rust
let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> Option<u32>, u32>>
let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, impl Fn(&mut u32, &u32, &mut u32) -> Option<u32>, u32>>
```
"#]],
);

View file

@ -5,7 +5,8 @@ use std::{
use either::Either;
use hir::{
known, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, ModuleDefId, Semantics,
known, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
ModuleDefId, Semantics,
};
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
use itertools::Itertools;
@ -45,6 +46,7 @@ pub struct InlayHintsConfig {
pub param_names_for_lifetime_elision_hints: bool,
pub hide_named_constructor_hints: bool,
pub hide_closure_initialization_hints: bool,
pub closure_style: ClosureStyle,
pub max_length: Option<usize>,
pub closing_brace_hints_min_lines: Option<usize>,
}
@ -291,6 +293,7 @@ fn label_of_ty(
mut max_length: Option<usize>,
ty: hir::Type,
label_builder: &mut InlayHintLabelBuilder<'_>,
config: &InlayHintsConfig,
) -> Result<(), HirDisplayError> {
let iter_item_type = hint_iterator(sema, famous_defs, &ty);
match iter_item_type {
@ -321,11 +324,14 @@ fn label_of_ty(
label_builder.write_str(LABEL_ITEM)?;
label_builder.end_location_link();
label_builder.write_str(LABEL_MIDDLE2)?;
rec(sema, famous_defs, max_length, ty, label_builder)?;
rec(sema, famous_defs, max_length, ty, label_builder, config)?;
label_builder.write_str(LABEL_END)?;
Ok(())
}
None => ty.display_truncated(sema.db, max_length).write_to(label_builder),
None => ty
.display_truncated(sema.db, max_length)
.with_closure_style(config.closure_style)
.write_to(label_builder),
}
}
@ -335,7 +341,7 @@ fn label_of_ty(
location: None,
result: InlayHintLabel::default(),
};
let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder);
let _ = rec(sema, famous_defs, config.max_length, ty, &mut label_builder, config);
let r = label_builder.finish();
Some(r)
}
@ -481,6 +487,7 @@ fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
#[cfg(test)]
mod tests {
use expect_test::Expect;
use hir::ClosureStyle;
use itertools::Itertools;
use test_utils::extract_annotations;
@ -504,6 +511,7 @@ mod tests {
binding_mode_hints: false,
hide_named_constructor_hints: false,
hide_closure_initialization_hints: false,
closure_style: ClosureStyle::ImplFn,
param_names_for_lifetime_elision_hints: false,
max_length: None,
closing_brace_hints_min_lines: None,

View file

@ -176,6 +176,7 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir
mod tests {
// This module also contains tests for super::closure_ret
use hir::ClosureStyle;
use syntax::{TextRange, TextSize};
use test_utils::extract_annotations;
@ -235,7 +236,7 @@ fn main() {
let zz_ref = &zz;
//^^^^^^ &Test<i32>
let test = || zz;
//^^^^ || -> Test<i32>
//^^^^ impl FnOnce() -> Test<i32>
}"#,
);
}
@ -753,7 +754,7 @@ fn main() {
let func = times2;
// ^^^^ fn times2(i32) -> i32
let closure = |x: i32| x * 2;
// ^^^^^^^ |i32| -> i32
// ^^^^^^^ impl Fn(i32) -> i32
}
fn fallible() -> ControlFlow<()> {
@ -821,7 +822,7 @@ fn main() {
//^^^^^^^^^ i32
let multiply =
//^^^^^^^^ |i32, i32| -> i32
//^^^^^^^^ impl Fn(i32, i32) -> i32
| a, b| a * b
//^ i32 ^ i32
@ -830,10 +831,10 @@ fn main() {
let _: i32 = multiply(1, 2);
//^ a ^ b
let multiply_ref = &multiply;
//^^^^^^^^^^^^ &|i32, i32| -> i32
//^^^^^^^^^^^^ &impl Fn(i32, i32) -> i32
let return_42 = || 42;
//^^^^^^^^^ || -> i32
//^^^^^^^^^ impl Fn() -> i32
|| { 42 };
//^^ i32
}"#,
@ -857,6 +858,94 @@ fn main() {
);
}
#[test]
fn closure_style() {
check_with_config(
InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
r#"
//- minicore: fn
fn main() {
let x = || 2;
//^ impl Fn() -> i32
let y = |t: i32| x() + t;
//^ impl Fn(i32) -> i32
let mut t = 5;
//^ i32
let z = |k: i32| { t += k; };
//^ impl FnMut(i32)
let p = (y, z);
//^ (impl Fn(i32) -> i32, impl FnMut(i32))
}
"#,
);
check_with_config(
InlayHintsConfig {
type_hints: true,
closure_style: ClosureStyle::RANotation,
..DISABLED_CONFIG
},
r#"
//- minicore: fn
fn main() {
let x = || 2;
//^ || -> i32
let y = |t: i32| x() + t;
//^ |i32| -> i32
let mut t = 5;
//^ i32
let z = |k: i32| { t += k; };
//^ |i32| -> ()
let p = (y, z);
//^ (|i32| -> i32, |i32| -> ())
}
"#,
);
check_with_config(
InlayHintsConfig {
type_hints: true,
closure_style: ClosureStyle::ClosureWithId,
..DISABLED_CONFIG
},
r#"
//- minicore: fn
fn main() {
let x = || 2;
//^ {closure#0}
let y = |t: i32| x() + t;
//^ {closure#1}
let mut t = 5;
//^ i32
let z = |k: i32| { t += k; };
//^ {closure#2}
let p = (y, z);
//^ ({closure#1}, {closure#2})
}
"#,
);
check_with_config(
InlayHintsConfig {
type_hints: true,
closure_style: ClosureStyle::Hide,
..DISABLED_CONFIG
},
r#"
//- minicore: fn
fn main() {
let x = || 2;
//^ …
let y = |t: i32| x() + t;
//^ …
let mut t = 5;
//^ i32
let z = |k: i32| { t += k; };
//^ …
let p = (y, z);
//^ (…, …)
}
"#,
);
}
#[test]
fn skip_closure_type_hints() {
check_with_config(
@ -871,13 +960,13 @@ fn main() {
let multiple_2 = |x: i32| { x * 2 };
let multiple_2 = |x: i32| x * 2;
// ^^^^^^^^^^ |i32| -> i32
// ^^^^^^^^^^ impl Fn(i32) -> i32
let (not) = (|x: bool| { !x });
// ^^^ |bool| -> bool
// ^^^ impl Fn(bool) -> bool
let (is_zero, _b) = (|x: usize| { x == 0 }, false);
// ^^^^^^^ |usize| -> bool
// ^^^^^^^ impl Fn(usize) -> bool
// ^^ bool
let plus_one = |x| { x + 1 };

View file

@ -1227,6 +1227,24 @@ fn main() {
)
}
#[test]
fn call_info_for_fn_def_over_reference() {
check(
r#"
struct S;
fn foo(s: S) -> i32 { 92 }
fn main() {
let bar = &&&&&foo;
bar($0);
}
"#,
expect![[r#"
fn foo(s: S) -> i32
^^^^
"#]],
)
}
#[test]
fn call_info_for_fn_ptr() {
check(

View file

@ -118,6 +118,7 @@ impl StaticIndex<'_> {
adjustment_hints_hide_outside_unsafe: false,
hide_named_constructor_hints: false,
hide_closure_initialization_hints: false,
closure_style: hir::ClosureStyle::ImplFn,
param_names_for_lifetime_elision_hints: false,
binding_mode_hints: false,
max_length: Some(25),