Skip to content

fix [Docs+feature] Consider how Var should be represented in reveal_type and hover #280#2589

Open
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:280
Open

fix [Docs+feature] Consider how Var should be represented in reveal_type and hover #280#2589
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:280

Conversation

@asukaminato0721
Copy link
Contributor

Summary

Fixes #280

Added a non‑pinning usage mode in bindings and wired reveal_type calls to use it, so calling reveal_type(x) doesn’t count as a “first use” that pins partial types. This preserves the intended behavior where later real usage (like x.append(1)) still pins the partial.

Updated special‑export handling to recognize typing.reveal_type/typing_extensions.reveal_type, enabling special handling in the binder.

Implemented reveal_type display overrides for empty list/dict assignments so that, when the variable is still unpinned, the printed type shows @_ rather than Unknown. This is display‑only and doesn’t mutate solver state.

Test Plan

Added a regression test that matches the docs example (initial reveal shows list[@_], subsequent reveal after append(1) shows list[int]) and updated the docs to explain @_.

@meta-cla meta-cla bot added the cla signed label Feb 28, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review February 28, 2026 14:27
Copilot AI review requested due to automatic review settings February 28, 2026 14:27
@asukaminato0721 asukaminato0721 marked this pull request as draft February 28, 2026 14:27
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates Pyrefly’s reveal_type behavior and documentation to better reflect unpinned partial types (showing @_) and to prevent reveal_type(...) from counting as a “first use” that pins partial container types.

Changes:

  • Add a non-pinning usage mode in the binder and route typing.reveal_type/typing_extensions.reveal_type argument evaluation through it.
  • Add special-export recognition for reveal_type and implement display-only overrides so empty []/{} reveals print @_ when still unpinned.
  • Add regression coverage and update docs to explain @_ in revealed types and hovers.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
website/docs/error-kinds.mdx Documents @_ placeholder semantics with a reveal_type example.
pyrefly/lib/test/simple.rs Adds regression test ensuring reveal_type doesn’t pin partial types.
pyrefly/lib/export/special.rs Adds RevealType to SpecialExport and recognizes it from typing/typing_extensions.
pyrefly/lib/binding/expr.rs Introduces Usage::NonPinningRead and uses it for RevealType calls.
pyrefly/lib/binding/bindings.rs Ensures NonPinningRead lookups don’t consume first-use inference.
pyrefly/lib/alt/special_calls.rs Implements reveal display override logic for unpinned empty list/dict assignments.
Comments suppressed due to low confidence (3)

pyrefly/lib/binding/expr.rs:670

  • This non-pinning special-case only triggers when the callee resolves to SpecialExport::RevealType (i.e., typing.reveal_type / typing_extensions.reveal_type). However, the typechecker also treats an unimported bare reveal_type(...) as a pseudo-builtin in alt/call.rs; in that case this branch won’t run and the argument will be ensured under the normal usage, which can still consume first-use inference and pin partial types. Consider extending this handling to also recognize the bare name reveal_type so the non-pinning behavior is consistent with the solver’s pseudo-builtin support.
                node_index: _,
                range: _,
                func,
                arguments,
            }) if self.as_special_export(func) == Some(SpecialExport::RevealType) => {

pyrefly/lib/alt/special_calls.rs:151

  • This Forward-chain walk uses an arbitrary remaining = 100 cutoff to avoid infinite loops. That makes reveal_type behavior depend on chain length and can silently stop resolving to the underlying Key::Definition for legitimately deep chains. Prefer using a visited set (as done elsewhere in bindings) to break cycles deterministically without a magic limit.
                    if let Some(mut idx) = self.bindings().key_to_idx_hashed_opt(Hashed::new(&key))
                    {
                        let mut remaining = 100usize;
                        let def_ident = loop {
                            if remaining == 0 {
                                break None;
                            }

pyrefly/lib/alt/special_calls.rs:238

  • When reveal_partial is true, this transforms all AnyStyle::Implicit occurrences in the displayed type into Var::ZERO (@_). That can misrepresent legitimate implicit Any that are unrelated to the empty-container placeholder (e.g., PartialTypeWithUpstreamsCompleted intentionally introduces Any to prevent upstream Vars from leaking). Consider restricting the Any(Implicit) -> @_ substitution to the specific override types you synthesize for empty []/{} (e.g., only when reveal_override is Some) so real Any remains Any in the reveal output.
                if reveal_partial {
                    display_ty.transform_mut(&mut |t| {
                        if matches!(t, Type::Any(AnyStyle::Implicit)) {
                            *t = Var::ZERO.to_type(self.heap);
                        }
                    });

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

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

- reveal_type now detects when its argument comes from a partial
assignment and rewrites Implicit Any to @_ for display only.
- Non‑pinning reads still bypass upstream pin forcing.
- The test now expects list[@_] for a pure partial use.
@asukaminato0721 asukaminato0721 marked this pull request as ready for review February 28, 2026 17:32
@github-actions
Copy link

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

@github-actions
Copy link

No diffs to classify.

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.

[Docs+feature] Consider how Var should be represented in reveal_type and hover

3 participants