Skip to content

Fix: Resolve HIR display length issues and improve adjustment tooltips #20031

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 75 additions & 33 deletions crates/ide/src/inlay_hints/adjustment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,50 +109,90 @@ pub(super) fn hints(
}
has_adjustments = true;

// FIXME: Add some nicer tooltips to each of these
let (text, coercion) = match kind {
let (text, coercion, detailed_tooltip) = match kind {
Adjust::NeverToAny if config.adjustment_hints == AdjustmentHints::Always => {
allow_edit = false;
("<never-to-any>", "never to any")
}
Adjust::Deref(None) => ("*", "dereference"),
Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => {
("*", "`Deref` dereference")
}
Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => {
("*", "`DerefMut` dereference")
}
Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => ("&", "borrow"),
Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => ("&mut ", "unique borrow"),
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => {
("&raw const ", "const pointer borrow")
}
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => {
("&raw mut ", "mut pointer borrow")
(
"<never-to-any>",
"never to any",
"Coerces the never type `!` into any other type. This happens in code paths that never return, like after `panic!()` or `return`.",
)
}
Adjust::Deref(None) => (
"*",
"dereference",
"Built-in dereference of a reference to access the underlying value. The compiler inserts `*` to get the value from `&T`.",
),
Adjust::Deref(Some(OverloadedDeref(Mutability::Shared))) => (
"*",
"`Deref` dereference",
"Dereference via the `Deref` trait. Used for types like `Box<T>` or `Rc<T>` so they act like plain `T`.",
),
Adjust::Deref(Some(OverloadedDeref(Mutability::Mut))) => (
"*",
"`DerefMut` dereference",
"Mutable dereference using the `DerefMut` trait. Enables smart pointers to give mutable access to their inner values.",
),
Adjust::Borrow(AutoBorrow::Ref(Mutability::Shared)) => (
"&",
"shared borrow",
"Inserts `&` to create a shared reference. Lets you use a value without moving or cloning it.",
),
Adjust::Borrow(AutoBorrow::Ref(Mutability::Mut)) => (
"&mut ",
"mutable borrow",
"Inserts `&mut` to create a unique, mutable reference. Lets you modify a value without taking ownership.",
),
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Shared)) => (
"&raw const ",
"const raw pointer",
"Converts a reference to a raw const pointer `*const T`. Often used when working with FFI or unsafe code.",
),
Adjust::Borrow(AutoBorrow::RawPtr(Mutability::Mut)) => (
"&raw mut ",
"mut raw pointer",
"Converts a mutable reference to a raw mutable pointer `*mut T`. Allows mutation in unsafe contexts.",
),
// some of these could be represented via `as` casts, but that's not too nice and
// handling everything as a prefix expr makes the `(` and `)` insertion easier
Adjust::Pointer(cast) if config.adjustment_hints == AdjustmentHints::Always => {
allow_edit = false;
match cast {
PointerCast::ReifyFnPointer => {
("<fn-item-to-fn-pointer>", "fn item to fn pointer")
}
PointerCast::ReifyFnPointer => (
"<fn-item-to-fn-pointer>",
"fn item to fn pointer",
"Converts a named function to a function pointer `fn()`. Useful when passing functions as values.",
),
PointerCast::UnsafeFnPointer => (
"<safe-fn-pointer-to-unsafe-fn-pointer>",
"safe fn pointer to unsafe fn pointer",
"Coerces a safe function pointer to an unsafe one. Allows calling it in an unsafe context.",
),
PointerCast::ClosureFnPointer(Safety::Unsafe) => (
"<closure-to-unsafe-fn-pointer>",
"closure to unsafe fn pointer",
"Converts a non-capturing closure to an unsafe function pointer. Required for use in `extern` or unsafe APIs.",
),
PointerCast::ClosureFnPointer(Safety::Safe) => (
"<closure-to-fn-pointer>",
"closure to fn pointer",
"Converts a non-capturing closure to a function pointer. Lets closures behave like plain functions.",
),
PointerCast::MutToConstPointer => (
"<mut-ptr-to-const-ptr>",
"mut ptr to const ptr",
"Coerces `*mut T` to `*const T`. Safe because const pointers restrict what you can do.",
),
PointerCast::ArrayToPointer => (
"<array-ptr-to-element-ptr>",
"array to pointer",
"Converts an array to a pointer to its first element. Similar to how arrays decay to pointers in C.",
),
PointerCast::Unsize => (
"<unsize>",
"unsize coercion",
"Converts a sized type to an unsized one. Used for things like turning arrays into slices or concrete types into trait objects.",
),
PointerCast::ClosureFnPointer(Safety::Unsafe) => {
("<closure-to-unsafe-fn-pointer>", "closure to unsafe fn pointer")
}
PointerCast::ClosureFnPointer(Safety::Safe) => {
("<closure-to-fn-pointer>", "closure to fn pointer")
}
PointerCast::MutToConstPointer => {
("<mut-ptr-to-const-ptr>", "mut ptr to const ptr")
}
PointerCast::ArrayToPointer => ("<array-ptr-to-element-ptr>", ""),
PointerCast::Unsize => ("<unsize>", "unsize"),
}
}
_ => continue,
Expand All @@ -162,9 +202,11 @@ pub(super) fn hints(
linked_location: None,
tooltip: Some(config.lazy_tooltip(|| {
InlayTooltip::Markdown(format!(
"`{}` → `{}` ({coercion} coercion)",
"`{}` → `{}`\n\n**{}**\n\n{}",
source.display(sema.db, display_target),
target.display(sema.db, display_target),
coercion,
detailed_tooltip
))
})),
};
Expand Down
2 changes: 0 additions & 2 deletions crates/ide/src/inlay_hints/closing_brace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ pub(super) fn hints(
match_ast! {
match parent {
ast::Fn(it) => {
// FIXME: this could include parameters, but `HirDisplay` prints too much info
// and doesn't respect the max length either, so the hints end up way too long
(format!("fn {}", it.name()?), it.name().map(name))
},
ast::Static(it) => (format!("static {}", it.name()?), it.name().map(name)),
Expand Down