about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-05-15 19:45:01 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-05-15 19:45:01 +0200
commitba8bcde4f5f0033752d772d4026468e7a8747072 (patch)
treeb3773c19280169d3382cdc3785e6a457a0d8e3a3
parent08dc0e21af8c3b7aeeac8cb428df02d83f514083 (diff)
downloadrust-ba8bcde4f5f0033752d772d4026468e7a8747072.tar.gz
rust-ba8bcde4f5f0033752d772d4026468e7a8747072.zip
Also render coercions for ranged type hover on closures
-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 4ab60c76ec1..c2b9222cb95 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 12beff3b900..0d8fc8a5f72 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#"