Skip to content

fix Regression when using type alias on Enum #3042#3044

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

fix Regression when using type alias on Enum #3042#3044
asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
asukaminato0721:3042

Conversation

@asukaminato0721
Copy link
Copy Markdown
Contributor

Summary

Fixes #3042

narrowing now infers comparison RHS names from their underlying binding instead of the function-scope promoted view, so a module alias like a = E.X still behaves as the literal enum member during is/== narrowing.

keeps the existing promotion behavior out of the general expression path and only makes narrowing more precise where it matters.

Test Plan

add test

@meta-cla meta-cla bot added the cla signed label Apr 7, 2026
@github-actions github-actions bot added the size/s label Apr 7, 2026
@asukaminato0721 asukaminato0721 marked this pull request as ready for review April 7, 2026 10:05
Copilot AI review requested due to automatic review settings April 7, 2026 10:05
Copy link
Copy Markdown

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

Fixes a regression in narrowing for is/== comparisons where a name bound to an enum member literal (e.g. a = E.X) stopped behaving like the literal enum member during narrowing.

Changes:

  • Added a narrowing-only RHS inference path (narrow_expr_infer) that avoids using the promoted view for Expr::Name.
  • Updated multiple narrowing operations (is, is not, ==, !=, isinstance, issubclass, etc.) to use the new RHS inference.
  • Added a regression test covering is not narrowing against a module-level enum-member alias.

Reviewed changes

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

File Description
pyrefly/lib/alt/narrow.rs Introduces narrow_expr_infer and routes RHS inference for many narrowing ops through it to improve enum-literal alias precision.
pyrefly/lib/test/narrow.rs Adds a regression testcase ensuring is not a correctly narrows when a aliases an enum member literal.

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

Comment on lines +135 to +137
Expr::Name(name) if !Ast::is_synthesized_empty_name(name) => self
.get(&Key::BoundName(ShortIdentifier::expr_name(name)))
.arc_clone_ty(),
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

narrow_expr_infer duplicates the Expr::Name inference logic from expr_infer_type_info_with_hint, but it skips other name-specific handling (e.g., the SelfTypeLiteral interception used for typing.Self, plus any tracing/deprecation hooks that run in the normal expression path). To avoid behavioral drift for name expressions that are special-cased elsewhere, consider reusing the existing expression inference path with an explicit “no implicit-literal promotion” option, or at least mirroring the SelfTypeLiteral interception before falling back to Key::BoundName.

Suggested change
Expr::Name(name) if !Ast::is_synthesized_empty_name(name) => self
.get(&Key::BoundName(ShortIdentifier::expr_name(name)))
.arc_clone_ty(),
Expr::Name(name) if !Ast::is_synthesized_empty_name(name) => {
let bound_name_ty = self
.get(&Key::BoundName(ShortIdentifier::expr_name(name)))
.arc_clone_ty();
match self.expr_infer(expr, errors) {
Type::SelfTypeLiteral(_) as inferred_name_ty => inferred_name_ty,
_ => bound_name_ty,
}
}

Copilot uses AI. Check for mistakes.

def f1(x: Literal[E.X, E.Y]):
if x is not a:
assert_type(x, Literal[E.Y])
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This adds coverage for is not narrowing against a module-level alias to an enum literal, but the implementation change also affects ==/!= narrowing (switching those RHS inferences to narrow_expr_infer). Consider extending this testcase (or adding another) to cover x == a and x != a to prevent regressions in the equality paths.

Suggested change
assert_type(x, Literal[E.Y])
assert_type(x, Literal[E.Y])
if x == a:
assert_type(x, Literal[E.X])
if x != a:
assert_type(x, Literal[E.Y])

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

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

@kinto0
Copy link
Copy Markdown
Contributor

kinto0 commented Apr 7, 2026

do we understand which commit caused the regression? and why? I think that's an important step in understanding if this fix is the correct one or not

@stroxler
Copy link
Copy Markdown
Contributor

stroxler commented Apr 7, 2026

I commented on the original issue - the change was caused by us treating (lower-cased) globals as mutable

That was intentional, and I think we should consider our options for solutions carefully

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.

Regression when using type alias on Enum

4 participants