Skip to content

Fix printExpression output for slice expressions and set displays - #11598

Open
Henry Su (hsusul) wants to merge 1 commit into
microsoft:mainfrom
hsusul:fix/print-expression-slice-set
Open

Fix printExpression output for slice expressions and set displays#11598
Henry Su (hsusul) wants to merge 1 commit into
microsoft:mainfrom
hsusul:fix/print-expression-slice-set

Conversation

@hsusul

Copy link
Copy Markdown
Contributor

ParseTreeUtils.printExpression renders slice expressions and set literals as text that means something different from the source. The most visible symptom is reveal_type output, which is also used for hover text (tooltipUtils prints parameter default values) and completion-generated signatures.

This is the same class of defect as #6345 (reveal_type(not y) printing "noty"), but here the printed text is not merely misformatted — it parses as a different expression.

Reproduction

def f(x: list[int], y: set[int]):
    reveal_type(x[1:])
    reveal_type(x[::2])
    reveal_type(x[::-1])
    reveal_type(x[1::2])
    reveal_type({1, 2})

Current behavior (1.1.411)

information: Type of "x[1]" is "list[int]"
information: Type of "x[: 2]" is "list[int]"
information: Type of "x[: -1]" is "list[int]"
information: Type of "x[1: 2]" is "list[int]"
information: Type of "1, 2" is "set[int]"

x[1:] is reported as x[1] (a slice printed as an index), x[::2] as x[:2], x[::-1] as x[:-1], and x[1::2] as x[1:2] — every one of these names a different expression than the one in the source. A set display is printed without its braces, so {1, 2} reads as a tuple.

Corrected behavior

information: Type of "x[1:]" is "list[int]"
information: Type of "x[::2]" is "list[int]"
information: Type of "x[::-1]" is "list[int]"
information: Type of "x[1::2]" is "list[int]"
information: Type of "{1, 2}" is "set[int]"

Root cause

packages/pyright-internal/src/analyzer/parseTreeUtils.ts

  • Slice: the first colon was emitted only in the "all three sub-expressions absent" branch, and the remaining colons were attached as a prefix to the end and step expressions. So an omitted endValue swallowed the colon that separates it from stepValue, and an omitted endValue and stepValue dropped the trailing colon entirely.
  • Set: the case joined the elements but never wrapped them in braces.

Implementation

The slice case now always emits the first colon, emits startValue before it and endValue after it when present, and emits a second colon only when stepValue is present. This preserves the existing (correct) rendering of x[:], x[:1], x[1:2] and x[1:2:3], and it collapses x[::] to x[:] and x[:2:] to x[:2], which are the same slice.

The incidental space that used to follow each colon is dropped, so the output matches how slices are written in source (and in PEP 8). Keeping it would have produced x[: : -1] for x[::-1].

The set case wraps the joined elements in {}.

No behavior outside printExpression changes.

Regression coverage

packages/pyright-internal/src/tests/parseTreeUtils.test.ts gains two tests next to the existing printExpression test, covering the eight slice shapes (x[:], x[1:], x[:1], x[1:2], x[::2], x[1::2], x[::-1], x[1:2:3]) and single- and multi-element set displays.

Both fail on main:

● printExpression slice
    Expected: "x[1:]"
    Received: "x[1]"

● printExpression set
    Expected: "{1}"
    Received: "1"

Validation

Run from a clean worktree at dde0aae (main), Node 24.9.0:

Command Result
npx jest parseTreeUtils.test --forceExit (before fix) 2 failed, 1 passed — the two new tests
npx jest parseTreeUtils.test --forceExit (after fix) 21 passed, 21 total
npm test (packages/pyright-internal) 62 suites passed, 2551 tests passed, 200 s
npm run check (syncpack + eslint + prettier) exit 0, no findings
CLI smoke test on the reproduction above (npm run build:cli:dev) output matches the "corrected behavior" block
git diff --check clean

Compatibility

printExpression output is not part of the public API; it feeds reveal_type messages, hover tooltips, completion labels and internal tracing. Existing test expectations for slice or set text: none (the only occurrence of a[: -1] in the repo is a tokenizer input string, not an expected output).

printExpression rendered "x[1:]" as "x[1]", "x[::2]" as "x[: 2]" and
"x[::-1]" as "x[: -1]" because the colon separating the end and step
values was emitted as a prefix of those sub-expressions rather than as a
separator, so an omitted end or step value swallowed it. It also printed
a set display without its enclosing braces, so "{1, 2}" read as a tuple.

Because printExpression drives reveal_type messages, hover tooltips for
parameter default values and completion labels, these expressions were
reported to users under a name that parses as a different expression.

Failure classification: (B) Pyright limitation. No typeshed change is
involved and no test expectations were relaxed; type precision is
unaffected, since only the textual rendering of an expression changes.
@rchiodo

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) added the review-auto:approved Automated review: no blocking findings (approval posted). label Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@StellaHuang95

Stella Huang (StellaHuang95) commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

🔒 Automated review in progress — Stella Huang (@StellaHuang95) is auto-reviewing this PR.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

@rchiodo Rich Chiodo (rchiodo) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved via Review Center.

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

Labels

review-auto:approved Automated review: no blocking findings (approval posted).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants