Skip to content

Fix invalid-literal error when using Annotated Literal in a type alias#2634

Closed
fangyi-zhou wants to merge 5 commits intofacebook:mainfrom
fangyi-zhou:fix-annotated-literal
Closed

Fix invalid-literal error when using Annotated Literal in a type alias#2634
fangyi-zhou wants to merge 5 commits intofacebook:mainfrom
fangyi-zhou:fix-annotated-literal

Conversation

@fangyi-zhou
Copy link
Copy Markdown
Contributor

@fangyi-zhou fangyi-zhou commented Mar 3, 2026

Summary

Fixes #2633, a regression introduced by #2572, where we model Annotated in a separate constructor.

There are two issues here:

  1. Type aliases for Annotated types are not resolved (thus being an UntypedAlias): this is because Annotated is now its own type, which is not always a Type for triggering the type alias resolution. The fix is to handle Annotated type in the resolution processing, and removing the Annotated wrapper.
  2. Annotated types are not handled in Literal check: this is a straightforward fix to check the inner type when encountering an Annotated type.

Test Plan

Added a regression test.

@meta-cla meta-cla bot added the cla signed label Mar 3, 2026
@migeed-z migeed-z requested a review from stroxler March 3, 2026 23:55
@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 4, 2026

Primer Diff Classification

❌ 1 regression(s) | 1 project(s) total

1 regression(s) across prefect. error kinds: bad-assignment Annotated incompatibility, bad-argument-type Annotated incompatibility, bad-return Annotated incompatibility.

Project Verdict Changes Error Kinds Root Cause
prefect ❌ Regression +24, -1 bad-assignment Annotated incompatibility pyrefly/lib/alt/solve.rs
Detailed analysis

❌ Regression (1)

prefect (+24, -1)

bad-assignment Annotated incompatibility: Pyrefly incorrectly treats Annotated[str] as incompatible with str, violating PEP 593's equivalence requirement
bad-argument-type Annotated incompatibility: Same issue as bad-assignment - Annotated[str] arguments rejected where str parameters expected
bad-return Annotated incompatibility: Return type checking incorrectly rejects Annotated[str] | None where str is expected

Overall: The new errors are regressions. Pyrefly is now treating Annotated[str] and str as incompatible types, which violates the typing spec's requirement that Annotated[T, ...] should be equivalent to T for type checking purposes. Per PEP 593, 'Annotated[C, x]' is equivalent to 'C' in all contexts except when explicitly introspecting annotations. The PR fixed Annotated handling in some contexts but introduced stricter behavior elsewhere, causing false positives where Annotated[str] values are rejected when str is expected. The removed error appears to be correcting a previous false positive where a legitimate type mismatch was incorrectly flagged.

Attribution: The changes in pyrefly/lib/alt/solve.rs and pyrefly/lib/alt/specials.rs fixed how pyrefly handles Annotated types. The solve.rs change preserves Annotated wrappers during type alias resolution, while the specials.rs change allows Literal validation to look through Annotated wrappers to check the underlying type. This caused pyrefly to now see Annotated[str] as equivalent to str in type checking contexts.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (1 LLM)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 4, 2026

Diff from mypy_primer, showing the effect of this PR on open source code:

cloud-init (https://github.com/canonical/cloud-init)
- ERROR cloudinit/distros/ug_util.py:40:25-59: Object of class `NoneType` has no attribute `extend` [missing-attribute]
+ ERROR cloudinit/distros/ug_util.py:40:45-52: No matching overload found for function `typing.MutableMapping.setdefault` called with arguments: (Unknown, list[@_]) [no-matching-overload]

prefect (https://github.com/PrefectHQ/prefect)
- ERROR src/prefect/blocks/core.py:1046:16-51: Returned type `tuple[BlockDocument, Name | None]` is not assignable to declared return type `tuple[BlockDocument, str]` [bad-return]
+ ERROR src/prefect/blocks/core.py:1046:16-51: Returned type `tuple[BlockDocument, str | None]` is not assignable to declared return type `tuple[BlockDocument, str]` [bad-return]

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 4, 2026

Primer Diff Classification

❌ 1 regression(s) | ➖ 1 neutral | 2 project(s) total

1 regression(s) across cloud-init. error kinds: missing-attribute, no-matching-overload. caused by is_valid_literal().

Project Verdict Changes Error Kinds Root Cause
cloud-init ❌ Regression +1, -1 missing-attribute, no-matching-overload is_valid_literal()
prefect ➖ Neutral +1, -1 bad-return
Detailed analysis

❌ Regression (1)

cloud-init (+1, -1)

This is a regression. The new error shows list[@_] which indicates type inference failure - pyrefly is no longer correctly inferring that setdefault(k, []) returns a list. The removed error was a false positive claiming setdefault() returns None, which is incorrect since setdefault() always returns either the existing value or the provided default. The code is actually correct: c_grp_cfg.setdefault(k, []) returns a list (either existing or the empty list default), and calling .extend(v) on that list is valid. The PR changes to handle Annotated types seem to have broken type inference for this unrelated dictionary operation.
Attribution: The changes to is_valid_literal() in pyrefly/lib/alt/specials.rs and type alias resolution in pyrefly/lib/alt/solve.rs for handling Annotated types appear to have disrupted type inference for this unrelated code, causing pyrefly to infer @_ (unknown) types instead of concrete types.

➖ Neutral (1)

prefect (+1, -1)

Same errors at same locations with same error kinds — message wording changed, no behavioral impact.

Suggested Fix

Summary: The PR's changes to handle Annotated types in type alias resolution have disrupted type inference for dictionary operations, causing setdefault() return type inference to fail.

1. In the type alias resolution logic in solve.rs around line 1505, add a guard to ensure that when unwrapping Annotated types, the inference context is preserved. The issue is that Type::Annotated(inner) => *inner strips away type information too aggressively. Add logic to preserve inference hints when unwrapping Annotated types in dictionary method contexts.

Files: pyrefly/lib/alt/solve.rs
Confidence: high
Affected projects: cloud-init
Fixes: bad-assignment
The regression shows list[@_] indicating type inference failure for setdefault(k, []) which should return list. The new Annotated type handling is stripping away type information during alias resolution. Adding a guard to preserve inference context when unwrapping Annotated types would fix this. Expected outcome: eliminates the 1 bad-assignment error in cloud-init where setdefault() return type inference fails.

2. In is_valid_literal() in specials.rs, modify the Annotated case to preserve type inference context. Instead of just is_valid_literal(inner), ensure that when recursing into Annotated types, the original type context is maintained for subsequent inference operations.

Files: pyrefly/lib/alt/specials.rs
Confidence: medium
Affected projects: cloud-init
Fixes: bad-assignment
The is_valid_literal change for Annotated types may be contributing to the inference failure by not properly handling the interaction between Annotated type unwrapping and dictionary method type inference. This could be a secondary factor in the setdefault() inference regression.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (1 heuristic, 1 LLM)

@fangyi-zhou fangyi-zhou marked this pull request as ready for review March 4, 2026 01:41
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Mar 4, 2026

@rchen152 has imported this pull request. If you are a Meta employee, you can view this in D95167871.

Copy link
Copy Markdown
Contributor

@stroxler stroxler left a comment

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

Copy link
Copy Markdown
Contributor

@yangdanny97 yangdanny97 left a comment

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Mar 4, 2026

@rchen152 merged this pull request in 3ad801f.

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.

0.55.0 regression: false positive invalid-literal for Literal of union of Annotated[Literal[_], _]

4 participants