Skip to content

fix Inlay hint for attribute does not match inherited annotation #846 - #3021

Open
asukaminato0721 wants to merge 2 commits into
meta:mainfrom
asukaminato0721:846
Open

asukaminato0721 wants to merge 2 commits into
meta:mainfrom
asukaminato0721:846

Conversation

@asukaminato0721

@asukaminato0721 asukaminato0721 commented Apr 5, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Fixes #846

where class-body store hovers now resolve through the computed class field type instead of the raw assignment binding, and that resolution is wired into get_type_at.

Test Plan

add test

@meta-cla meta-cla Bot added the cla signed label Apr 5, 2026
@github-actions github-actions Bot added the size/m label Apr 5, 2026
@asukaminato0721
asukaminato0721 marked this pull request as ready for review April 5, 2026 14:43
Copilot AI review requested due to automatic review settings April 5, 2026 14:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to address Issue #846 (mismatched type display for inherited class attributes) by preferring the solver-resolved class field type when retrieving a type at an attribute definition site, and adds a regression test around the hover output.

Changes:

  • Added a hover regression test for an inherited ClassVar overridden in a subclass.
  • Updated Transaction::get_type_at to, for Store-context identifiers, prefer a class-attribute lookup (get_class_attribute) when the identifier is defined inside a class body.
  • Introduced class_attribute_type_at_definition helper to locate the enclosing class and resolve the field type via the solver.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
pyrefly/lib/test/lsp/hover_type.rs Adds a regression test asserting hover type uses the inherited resolved field type for a subclass attribute assignment.
pyrefly/lib/state/lsp.rs Adjusts hover/provide-type resolution on Store-context identifiers to prefer solver-resolved class attribute types at class attribute definition sites.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pyrefly/lib/state/lsp.rs Outdated
Comment on lines +594 to +605
for node in Ast::locate_node(&ast, identifier.range.start())
.into_iter()
.skip(1)
{
match node {
AnyNodeRef::StmtFunctionDef(_) | AnyNodeRef::ExprLambda(_) => return None,
AnyNodeRef::StmtClassDef(class_def) => {
enclosing_class = Some(class_def.name.clone());
break;
}
_ => {}
}

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

class_attribute_type_at_definition only treats function defs and lambdas as scope boundaries. Comprehensions/generator expressions also introduce their own scope, so a Store-context name inside a comprehension in a class body could be misinterpreted as a class attribute and incorrectly resolve to an inherited field type. Consider bailing out when Ast::locate_node includes AnyNodeRef::ExprListComp|ExprSetComp|ExprDictComp|ExprGenerator (and/or AnyNodeRef::Comprehension) similar to how other code treats these as disallowed scopes.

Copilot uses AI. Check for mistakes.
Comment thread pyrefly/lib/state/lsp.rs Outdated
Comment on lines +228 to +258
#[test]
fn inherited_classvar_hover_prefers_resolved_field_type() {
let code = r#"
from typing import ClassVar

class A:
x: ClassVar[tuple[str, ...]] = ("A",)

class B(A):
x = ("B",)
# ^

reveal = B.x
# ^
"#;
let report = get_batched_lsp_operations_report(&[("main", code)], get_test_report);
assert_eq!(
r#"
# main.py
8 | x = ("B",)
^
Hover Result: `tuple[str, ...]`

11 | reveal = B.x
^
Hover Result: `tuple[str, ...]`
"#
.trim(),
report.trim(),
);
}

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

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

This new test exercises hover behavior, but Issue #846 is about variable-type inlay hints showing an overly specific inferred type on inherited attributes. Since the inlay hint pipeline doesn’t use hover’s get_type_at path, it would be good to add/adjust a test in the inlay hint test suite to ensure the reported inlay hint output is fixed (and to prevent regressions).

Copilot uses AI. Check for mistakes.
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added size/m and removed size/m labels Jul 17, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@stroxler stroxler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks! This seems like a promising direction. A few suggestions of things to improve before we merge:

  • Respect comprehension scopes. Resolve class-field ownership from bindings, or stop lookup at comprehension boundaries. With C.x: str and [x for x in (1, 2)], the comprehension target incorrectly hovers as str instead of Literal[1, 2]. Add a regression test for this shadowing case.

  • Preserve Self at declarations. Use the resolved declaration field type rather than class-access lookup. Hovering x: Self | None = None inside C currently shows C | None, losing its subclass-relative meaning. Add hover and computed-type coverage.

  • Wire the fix into inlay hints. Share resolved field lookup with the inlay-hint path and test it directly using a nonliteral RHS. An override inheriting ClassVar[tuple[str, ...]] still receives a tuple[str] hint; the existing test covers hover only.

@github-actions

Copy link
Copy Markdown

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inlay hint for attribute does not match inherited annotation

4 participants