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

Commit ba8bcde

Browse files
committed
Also render coercions for ranged type hover on closures
1 parent 08dc0e2 commit ba8bcde

File tree

2 files changed

+74
-59
lines changed

2 files changed

+74
-59
lines changed

crates/ide/src/hover/render.rs

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -47,60 +47,8 @@ pub(super) fn closure_expr(
4747
config: &HoverConfig,
4848
c: ast::ClosureExpr,
4949
) -> Option<HoverResult> {
50-
let ty = sema.type_of_expr(&c.into())?;
51-
closure_ty(sema, config, &ty.original)
52-
}
53-
54-
fn closure_ty(
55-
sema: &Semantics<'_, RootDatabase>,
56-
config: &HoverConfig,
57-
ty: &hir::Type,
58-
) -> Option<HoverResult> {
59-
let c = ty.as_closure()?;
60-
let layout = if config.memory_layout {
61-
ty.layout(sema.db)
62-
.map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
63-
.unwrap_or_default()
64-
} else {
65-
String::default()
66-
};
67-
let mut captures_rendered = c.captured_items(sema.db)
68-
.into_iter()
69-
.map(|it| {
70-
let borrow_kind = match it.kind() {
71-
CaptureKind::SharedRef => "immutable borrow",
72-
CaptureKind::UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
73-
CaptureKind::MutableRef => "mutable borrow",
74-
CaptureKind::Move => "move",
75-
};
76-
format!("* `{}` by {}", it.display_place(sema.db), borrow_kind)
77-
})
78-
.join("\n");
79-
if captures_rendered.trim().is_empty() {
80-
captures_rendered = "This closure captures nothing".to_string();
81-
}
82-
let mut targets: Vec<hir::ModuleDef> = Vec::new();
83-
let mut push_new_def = |item: hir::ModuleDef| {
84-
if !targets.contains(&item) {
85-
targets.push(item);
86-
}
87-
};
88-
walk_and_push_ty(sema.db, ty, &mut push_new_def);
89-
c.capture_types(sema.db).into_iter().for_each(|ty| {
90-
walk_and_push_ty(sema.db, &ty, &mut push_new_def);
91-
});
92-
93-
let mut res = HoverResult::default();
94-
res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
95-
res.markup = format!(
96-
"```rust\n{}{}\n{}\n```\n\n## Captures\n{}",
97-
c.display_with_id(sema.db),
98-
layout,
99-
c.display_with_impl(sema.db),
100-
captures_rendered,
101-
)
102-
.into();
103-
Some(res)
50+
let TypeInfo { original, .. } = sema.type_of_expr(&c.into())?;
51+
closure_ty(sema, config, &TypeInfo { original, adjusted: None })
10452
}
10553

10654
pub(super) fn try_expr(
@@ -542,11 +490,12 @@ pub(super) fn definition(
542490
fn type_info(
543491
sema: &Semantics<'_, RootDatabase>,
544492
config: &HoverConfig,
545-
TypeInfo { original, adjusted }: TypeInfo,
493+
ty: TypeInfo,
546494
) -> Option<HoverResult> {
547-
if let Some(res) = closure_ty(sema, config, &original) {
495+
if let Some(res) = closure_ty(sema, config, &ty) {
548496
return Some(res);
549-
}
497+
};
498+
let TypeInfo { original, adjusted } = ty;
550499
let mut res = HoverResult::default();
551500
let mut targets: Vec<hir::ModuleDef> = Vec::new();
552501
let mut push_new_def = |item: hir::ModuleDef| {
@@ -576,6 +525,69 @@ fn type_info(
576525
Some(res)
577526
}
578527

528+
fn closure_ty(
529+
sema: &Semantics<'_, RootDatabase>,
530+
config: &HoverConfig,
531+
TypeInfo { original, adjusted }: &TypeInfo,
532+
) -> Option<HoverResult> {
533+
let c = original.as_closure()?;
534+
let layout = if config.memory_layout {
535+
original
536+
.layout(sema.db)
537+
.map(|x| format!(" // size = {}, align = {}", x.size.bytes(), x.align.abi.bytes()))
538+
.unwrap_or_default()
539+
} else {
540+
String::default()
541+
};
542+
let mut captures_rendered = c.captured_items(sema.db)
543+
.into_iter()
544+
.map(|it| {
545+
let borrow_kind = match it.kind() {
546+
CaptureKind::SharedRef => "immutable borrow",
547+
CaptureKind::UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))",
548+
CaptureKind::MutableRef => "mutable borrow",
549+
CaptureKind::Move => "move",
550+
};
551+
format!("* `{}` by {}", it.display_place(sema.db), borrow_kind)
552+
})
553+
.join("\n");
554+
if captures_rendered.trim().is_empty() {
555+
captures_rendered = "This closure captures nothing".to_string();
556+
}
557+
let mut targets: Vec<hir::ModuleDef> = Vec::new();
558+
let mut push_new_def = |item: hir::ModuleDef| {
559+
if !targets.contains(&item) {
560+
targets.push(item);
561+
}
562+
};
563+
walk_and_push_ty(sema.db, original, &mut push_new_def);
564+
c.capture_types(sema.db).into_iter().for_each(|ty| {
565+
walk_and_push_ty(sema.db, &ty, &mut push_new_def);
566+
});
567+
568+
let adjusted = if let Some(adjusted_ty) = adjusted {
569+
walk_and_push_ty(sema.db, &adjusted_ty, &mut push_new_def);
570+
format!(
571+
"\nCoerced to: {}",
572+
adjusted_ty.display(sema.db).with_closure_style(hir::ClosureStyle::ImplFn)
573+
)
574+
} else {
575+
String::new()
576+
};
577+
578+
let mut res = HoverResult::default();
579+
res.actions.push(HoverAction::goto_type_from_targets(sema.db, targets));
580+
res.markup = format!(
581+
"```rust\n{}{}\n{}\n```{adjusted}\n\n## Captures\n{}",
582+
c.display_with_id(sema.db),
583+
layout,
584+
c.display_with_impl(sema.db),
585+
captures_rendered,
586+
)
587+
.into();
588+
Some(res)
589+
}
590+
579591
fn render_builtin_attr(db: &RootDatabase, attr: hir::BuiltinAttr) -> Option<Markup> {
580592
let name = attr.name(db);
581593
let desc = format!("#[{name}]");

crates/ide/src/hover/tests.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,29 +307,32 @@ fn main() {
307307
fn hover_ranged_closure() {
308308
check_hover_range(
309309
r#"
310+
//- minicore: fn
310311
struct S;
311312
struct S2;
312313
fn main() {
313314
let x = &S;
314-
let y = $0|| {x; S2}$0;
315+
let y = ($0|| {x; S2}$0).call();
315316
}
316317
"#,
317318
expect![[r#"
318319
```rust
319320
{closure#0} // size = 8, align = 8
320321
impl FnOnce() -> S2
321322
```
323+
Coerced to: &impl FnOnce() -> S2
322324
323325
## Captures
324326
* `x` by move"#]],
325327
);
326328
check_hover_range_actions(
327329
r#"
330+
//- minicore: fn
328331
struct S;
329332
struct S2;
330333
fn main() {
331334
let x = &S;
332-
let y = $0|| {x; S2}$0;
335+
let y = ($0|| {x; S2}$0).call();
333336
}
334337
"#,
335338
expect![[r#"

0 commit comments

Comments
 (0)