Skip to content

solve generic function converters against the field type#4158

Closed
shobhitmehro wants to merge 1 commit into
facebook:mainfrom
shobhitmehro:export-D112165450
Closed

solve generic function converters against the field type#4158
shobhitmehro wants to merge 1 commit into
facebook:mainfrom
shobhitmehro:export-D112165450

Conversation

@shobhitmehro

Copy link
Copy Markdown
Contributor

Summary:
Goal: A generic function used as an attrs converter, such as copy.deepcopy, no longer produces a spurious error when you construct the class.

Background: attrs lets a field declare a converter that transforms the constructor argument before it is stored, and pyrefly types the generated __init__ parameter as the converter's input type. When the converter is a generic function like, whose type is (_T) -> _T, that input is a bare type variable _T that escapes its function scope, so every argument was rejected with a message about a parameter of type _T.

How: We add a parallel arm that recognizes a generic function converter and solves it the same way the class path does, by instantiating the function with fresh variables, constraining its return type against the declared field type, and reading back the solved input as the __init__ parameter. A variable that cannot be solved is finalized to a gradual type so uncertain cases fall back instead of erroring.

fixes #4155

Differential Revision: D112165450

Summary:
Goal: A generic function used as an attrs converter, such as copy.deepcopy, no longer produces a spurious error when you construct the class.

Background: attrs lets a field declare a converter that transforms the constructor argument before it is stored, and pyrefly types the generated `__init__` parameter as the converter's input type. When the converter is a generic function like, whose type is `(_T) -> _T`, that input is a bare type variable `_T` that escapes its function scope, so every argument was rejected with a message about a parameter of type `_T`. 

How: We add a parallel arm that recognizes a generic function converter and solves it the same way the class path does, by instantiating the function with fresh variables, constraining its return type against the declared field type, and reading back the solved input as the `__init__` parameter. A variable that cannot be solved is finalized to a gradual type so uncertain cases fall back instead of erroring.

fixes facebook#4155

Differential Revision: D112165450
@meta-cla meta-cla Bot added the cla signed label Jul 15, 2026
@meta-codesync

meta-codesync Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@shobhitmehro has exported this pull request. If you are a Meta employee, you can view the originating Diff in D112165450.

@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. ✅

@yangdanny97 yangdanny97 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.

Review automatically exported from Phabricator review in Meta.

@meta-codesync meta-codesync Bot closed this in e8017ac Jul 16, 2026
@meta-codesync

meta-codesync Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

This pull request has been merged in e8017ac.

@meta-codesync meta-codesync Bot added the Merged label Jul 16, 2026
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.

Unbound TypeVar leak into synthesized __init__ from generic attrs converter

2 participants