Skip to content

Conversation

MatthewMckee4
Copy link
Contributor

@MatthewMckee4 MatthewMckee4 commented Aug 22, 2025

Summary

Our internal inlay hints structure (ty_ide::InlayHint) now more closely resembles lsp_types::InlayHint.

This mainly allows us to convert to lsp_types::InlayHint with less hassle, but it also allows us to manage the different parts of the inlay hint better, which in the future will allow us to implement features like goto on the type part of the type inlay hint.

It also really isn't important to store a specific Type instance in the InlayHintContent. So we remove this and use InlayHintLabel instead which just shows the representation of the type (along with other information).

We see a similar structure used in rust-analyzer too.

@MatthewMckee4 MatthewMckee4 marked this pull request as ready for review August 22, 2025 21:24
Copy link
Contributor

github-actions bot commented Aug 22, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@AlexWaygood AlexWaygood removed their request for review August 22, 2025 21:26
@MatthewMckee4 MatthewMckee4 changed the title Refactor inlay hints [ty] Refactor ty_ide inlay hints Aug 22, 2025
"character": 1
},
"label": ": Literal[1]",
"label": [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These change because we now use InlayHintLabel::LabelParts instead of InlayHintLabel::String

Copy link
Contributor

github-actions bot commented Aug 22, 2025

mypy_primer results

No ecosystem changes detected ✅
No memory usage changes detected ✅

@AlexWaygood AlexWaygood added server Related to the LSP server ty Multi-file analysis & type inference labels Aug 22, 2025
@carljm carljm requested review from dhruvmanila and removed request for carljm August 22, 2025 23:12
@MatthewMckee4 MatthewMckee4 marked this pull request as draft August 22, 2025 23:17
Comment on lines 22 to 24
let mut label = InlayHintLabel::simple(ty.display(db).to_string(), None);

label.prepend_str(": ");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is roughly how rust analyzer does it and we need to separate these for the goto targets


#[derive(Debug, Clone)]
pub struct InlayHintLabel {
pub parts: SmallVec<[InlayHintLabelPart; 1]>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think i should change this to 2. @MichaReiser would you agree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ive done it, i think it makes sense for us.

Copy link
Contributor Author

@MatthewMckee4 MatthewMckee4 Aug 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay in this situation we only use 1 of the InlayHintLabelPart, but when we add the goto, we will use 2.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense today because all our usages have exactly two parts. But it's hard to tell, depending on how you plan to use this going forward.

A too-large number has the downside that InlayHintLabel becomes larger overall, wasting memory when we only need to store 1 or more than two elements. This is especially problematic if we create many InlayHintLabels. I don't think this is a big concern here.

I'm not even sure if it's worth using a SmallVec here. We'll need to serialize all that data later on, we might as well just store a Vec

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently because we don't use the target variable in InlayHintLabel. This means we just have one part so we will only use one of the elements in the small vec.

I'll change to vec for now anyway.

@MatthewMckee4 MatthewMckee4 marked this pull request as ready for review August 22, 2025 23:43
@MichaReiser
Copy link
Member

Could you extend the summary? I think I've an idea why we may want this but I'd rather be sure (and documenting this will also help a future reader who comes across this PR and wonders why it works the way it does)

Comment on lines 19 to 20
impl InlayHint {
pub fn type_hint(position: TextSize, ty: Type, db: &dyn Db) -> Self {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be useful to add basic documentation for all the pub items in this module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to make more things private

Comment on lines 71 to 73
match &mut *self.parts {
[InlayHintLabelPart { text, target: None }, ..] => text.insert_str(0, s),
_ => self.parts.insert(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first, I thought that the catch-all branch is for the empty vector ([]) but I don't think that's true, the branch that isn't covered here is an InlayHintLabelPart where target is Some. Can you expand on why does the string needs to be added only when navigation target is not present? Based on the method name, I would expect this to add the string regardless of whether target is present or not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ive just removed these methods, i think its better for us to just be more explicit with what the specific parts are anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this because that would allow us to have the navigation target that is relevant for that specific part of the label? For example, in : Type, it's just the "Type" part that's possible to do go to definition.

@dhruvmanila dhruvmanila self-assigned this Aug 25, 2025
@dhruvmanila
Copy link
Member

Feel free to re-request for review once it's ready.

@MatthewMckee4
Copy link
Contributor Author

could you re run that cargo test, looks like a flake

@dhruvmanila dhruvmanila added the internal An internal refactor or improvement label Aug 26, 2025
@dhruvmanila dhruvmanila changed the title [ty] Refactor ty_ide inlay hints [ty] Refactor inlay hints structure to use separate parts Aug 26, 2025
Copy link
Member

@dhruvmanila dhruvmanila left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@dhruvmanila
Copy link
Member

could you re run that cargo test, looks like a flake

I'm assuming that this was fixed?

@dhruvmanila dhruvmanila merged commit 8d6dc7d into astral-sh:main Aug 26, 2025
39 checks passed
carljm added a commit to leandrobbraga/ruff that referenced this pull request Aug 27, 2025
* main:
  [`ruff`] Preserve relative whitespace in multi-line expressions (`RUF033`) (astral-sh#19647)
  [ty] Optimize TDD atom ordering (astral-sh#20098)
  [`airflow`] Extend `AIR311` and `AIR312` rules (astral-sh#20082)
  [ty] Preserve qualifiers when accessing attributes on unions/intersections (astral-sh#20114)
  [ty] Fix the inferred interface of specialized generic protocols (astral-sh#19866)
  [ty] Infer slightly more precise types for comprehensions (astral-sh#20111)
  [ty] Add more tests for protocols (astral-sh#20095)
  [ty] don't eagerly unpack aliases in user-authored unions (astral-sh#20055)
  [`flake8-use-pathlib`] Update links to the table showing the correspondence between `os` and `pathlib` (astral-sh#20103)
  [`flake8-use-pathlib`] Make `PTH100` fix unsafe because it can change behavior (astral-sh#20100)
  [`flake8-use-pathlib`] Delete unused `Rule::OsSymlink` enabled check (astral-sh#20099)
  [ty] Add search paths info to unresolved import diagnostics (astral-sh#20040)
  [`flake8-logging-format`] Add auto-fix for f-string logging calls (`G004`) (astral-sh#19303)
  Add a `ScopeKind` for the `__class__` cell (astral-sh#20048)
  Fix incorrect D413 links in docstrings convention FAQ (astral-sh#20089)
  [ty] Refactor inlay hints structure to use separate parts (astral-sh#20052)
second-ed pushed a commit to second-ed/ruff that referenced this pull request Sep 9, 2025
…20052)

## Summary

Our internal inlay hints structure (`ty_ide::InlayHint`) now more
closely resembles `lsp_types::InlayHint`.

This mainly allows us to convert to `lsp_types::InlayHint` with less
hassle, but it also allows us to manage the different parts of the inlay
hint better, which in the future will allow us to implement features
like goto on the type part of the type inlay hint.

It also really isn't important to store a specific `Type` instance in
the `InlayHintContent`. So we remove this and use `InlayHintLabel`
instead which just shows the representation of the type (along with
other information).

We see a similar structure used in rust-analyzer too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal An internal refactor or improvement server Related to the LSP server ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants