Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/hover/render.rs')
-rw-r--r--crates/ide/src/hover/render.rs113
1 files changed, 73 insertions, 40 deletions
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 53226db7cc..c2b9222cb9 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -35,11 +35,11 @@ pub(super) fn type_info_of(
_config: &HoverConfig,
expr_or_pat: &Either<ast::Expr, ast::Pat>,
) -> Option<HoverResult> {
- let TypeInfo { original, adjusted } = match expr_or_pat {
+ let ty_info = match expr_or_pat {
Either::Left(expr) => sema.type_of_expr(expr)?,
Either::Right(pat) => sema.type_of_pat(pat)?,
};
- type_info(sema, _config, original, adjusted)
+ type_info(sema, _config, ty_info)
}
pub(super) fn closure_expr(
@@ -47,41 +47,8 @@ pub(super) fn closure_expr(
config: &HoverConfig,
c: ast::ClosureExpr,
) -> Option<HoverResult> {
- let ty = &sema.type_of_expr(&c.into())?.original;
- 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 c = ty.as_closure()?;
- let mut captures = 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.trim().is_empty() {
- captures = "This closure captures nothing".to_string();
- }
- let mut res = HoverResult::default();
- 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,
- )
- .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(
@@ -522,10 +489,13 @@ pub(super) fn definition(
fn type_info(
sema: &Semantics<'_, RootDatabase>,
- _config: &HoverConfig,
- original: hir::Type,
- adjusted: Option<hir::Type>,
+ config: &HoverConfig,
+ ty: TypeInfo,
) -> Option<HoverResult> {
+ 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| {
@@ -555,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}]");