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.rs | 113 |
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}]"); |