Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide/src/hover/render.rs126
-rw-r--r--crates/ide/src/hover/tests.rs7
2 files changed, 74 insertions, 59 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 4ab60c76ec..c2b9222cb9 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -47,60 +47,8 @@ pub(super) fn closure_expr(
config: &HoverConfig,
c: ast::ClosureExpr,
) -> Option<HoverResult> {
- let ty = sema.type_of_expr(&c.into())?;
- closure_ty(sema, config, &ty.original)
-}
-
-fn closure_ty(
- sema: &Semantics<'_, RootDatabase>,
- config: &HoverConfig,
- ty: &hir::Type,
-) -> Option<HoverResult> {
- let c = ty.as_closure()?;
- let layout = if config.memory_layout {
- ty.layout(sema.db)
- .map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
- .unwrap_or_default()
- } else {
- String::default()
- };
- let mut captures_rendered = c.captured_items(sema.db)
- .into_iter()
- .map(|it| {
- let borrow_kind = match it.kind() {
- CaptureKind::SharedRef => "immutable borrow",
- CaptureKind::UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
- CaptureKind::MutableRef => "mutable borrow",
- CaptureKind::Move => "move",
- };
- format!("* `{}` by {}", it.display_place(sema.db), borrow_kind)
- })
- .join("\n");
- if captures_rendered.trim().is_empty() {
- captures_rendered = "This closure captures nothing".to_string();
- }
- let mut targets: Vec<hir::ModuleDef> = Vec::new();
- let mut push_new_def = |item: hir::ModuleDef| {
- if !targets.contains(&item) {
- targets.push(item);
- }
- };
- walk_and_push_ty(sema.db, ty, &mut push_new_def);
- c.capture_types(sema.db).into_iter().for_each(|ty| {
- walk_and_push_ty(sema.db, &ty, &mut push_new_def);
- });
-
- let mut res = HoverResult::default();
- res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
- res.markup = format!(
- "```rust\n{}{}\n{}\n```\n\n## Captures\n{}",
- c.display_with_id(sema.db),
- layout,
- c.display_with_impl(sema.db),
- captures_rendered,
- )
- .into();
- Some(res)
+ let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?;
+ closure_ty(sema, config, &TypeInfo { original, adjusted: None })
}
pub(super) fn try_expr(
@@ -542,11 +490,12 @@ pub(super) fn definition(
fn type_info(
sema: &Semantics<'_, RootDatabase>,
config: &HoverConfig,
- TypeInfo { original, adjusted }: TypeInfo,
+ ty: TypeInfo,
) -> Option<HoverResult> {
- if let Some(res) = closure_ty(sema, config, &original) {
+ if let Some(res) = closure_ty(sema, config, &ty) {
return Some(res);
- }
+ };
+ let TypeInfo { original, adjusted } = ty;
let mut res = HoverResult::default();
let mut targets: Vec<hir::ModuleDef> = Vec::new();
let mut push_new_def = |item: hir::ModuleDef| {
@@ -576,6 +525,69 @@ fn type_info(
Some(res)
}
+fn closure_ty(
+ sema: &Semantics<'_, RootDatabase>,
+ config: &HoverConfig,
+ TypeInfo { original, adjusted }: &TypeInfo,
+) -> Option<HoverResult> {
+ let c = original.as_closure()?;
+ let layout = if config.memory_layout {
+ original
+ .layout(sema.db)
+ .map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
+ .unwrap_or_default()
+ } else {
+ String::default()
+ };
+ let mut captures_rendered = c.captured_items(sema.db)
+ .into_iter()
+ .map(|it| {
+ let borrow_kind = match it.kind() {
+ CaptureKind::SharedRef => "immutable borrow",
+ CaptureKind::UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
+ CaptureKind::MutableRef => "mutable borrow",
+ CaptureKind::Move => "move",
+ };
+ format!("* `{}` by {}", it.display_place(sema.db), borrow_kind)
+ })
+ .join("\n");
+ if captures_rendered.trim().is_empty() {
+ captures_rendered = "This closure captures nothing".to_string();
+ }
+ let mut targets: Vec<hir::ModuleDef> = Vec::new();
+ let mut push_new_def = |item: hir::ModuleDef| {
+ if !targets.contains(&item) {
+ targets.push(item);
+ }
+ };
+ walk_and_push_ty(sema.db, original, &mut push_new_def);
+ c.capture_types(sema.db).into_iter().for_each(|ty| {
+ walk_and_push_ty(sema.db, &ty, &mut push_new_def);
+ });
+
+ let adjusted = if let Some(adjusted_ty) = adjusted {
+ walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
+ format!(
+ "\nCoerced to: {}",
+ adjusted_ty.display(sema.db).with_closure_style(hir::ClosureStyle::ImplFn)
+ )
+ } else {
+ String::new()
+ };
+
+ let mut res = HoverResult::default();
+ res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
+ res.markup = format!(
+ "```rust\n{}{}\n{}\n```{adjusted}\n\n## Captures\n{}",
+ c.display_with_id(sema.db),
+ layout,
+ c.display_with_impl(sema.db),
+ captures_rendered,
+ )
+ .into();
+ Some(res)
+}
+
fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Markup> {
let name = attr.name(db);
let desc = format!("#[{name}]");
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 12beff3b90..0d8fc8a5f7 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -307,11 +307,12 @@ fn main() {
fn hover_ranged_closure() {
check_hover_range(
r#"
+//- minicore: fn
struct S;
struct S2;
fn main() {
let x = &S;
- let y = $0|| {x; S2}$0;
+ let y = ($0|| {x; S2}$0).call();
}
"#,
expect![[r#"
@@ -319,17 +320,19 @@ fn main() {
{closure#0} // size = 8, align = 8
impl FnOnce() -> S2
```
+ Coerced to: &impl FnOnce() -> S2
## Captures
* `x` by move"#]],
);
check_hover_range_actions(
r#"
+//- minicore: fn
struct S;
struct S2;
fn main() {
let x = &S;
- let y = $0|| {x; S2}$0;
+ let y = ($0|| {x; S2}$0).call();
}
"#,
expect![[r#"