fix Support inline namedtuple definition #2811#2815
fix Support inline namedtuple definition #2811#2815asukaminato0721 wants to merge 1 commit intofacebook:mainfrom
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR extends pyrefly’s handling of functional namedtuple definitions so that collections.namedtuple(...) / typing.NamedTuple(...) used inline in expression position (not just assigned to a name or used as a base class) synthesize an anonymous class that the solver can type correctly, addressing issue #2811.
Changes:
- Add binding-time synthesis for inline functional namedtuple calls (
collections.namedtuple/typing.NamedTuple) when the first argument is a string literal. - Add solver support to recognize and return the synthesized class type for these functional namedtuple call expressions.
- Add a regression test covering the inline-constructor pattern from #2811.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
pyrefly/lib/test/named_tuple.rs |
Adds regression test for inline collections.namedtuple(...)(...) constructor usage. |
pyrefly/lib/binding/expr.rs |
Synthesizes anonymous namedtuple classes during expression binding when functional namedtuple calls appear inline. |
pyrefly/lib/alt/expr.rs |
Returns synthesized class types during call expression inference when a matching anonymous class binding exists. |
pyrefly/lib/alt/class/class_field.rs |
Adjusts override-consistency checking to avoid treating namedtuple elements as regular override targets. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| fn synthesized_functional_class_type(&self, call: &ExprCall) -> Option<Type> { | ||
| let anon_key = match call.arguments.args.first()? { | ||
| Expr::StringLiteral(name) => Key::Anon(name.range()), | ||
| _ => Key::Anon(call.range), | ||
| }; | ||
| let idx = self | ||
| .bindings() | ||
| .key_to_idx_hashed_opt(Hashed::new(&anon_key))?; | ||
| matches!(self.bindings().get(idx), Binding::ClassDef(..)) | ||
| .then(|| self.get_hashed(Hashed::new(&anon_key)).ty().clone()) | ||
| } |
| self.insert_binding( | ||
| Key::Anon(call.range), | ||
| Binding::ClassDef(class_idx, Box::new([])), | ||
| ); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@yangdanny97 has imported this pull request. If you are a Meta employee, you can view this in D97669871. |
|
Diff from mypy_primer, showing the effect of this PR on open source code: rotki (https://github.com/rotki/rotki)
- ERROR rotkehlchen/tests/utils/mock.py:74:16-50: Expected a callable, got `NamedTuple` [not-callable]
- ERROR rotkehlchen/tests/utils/mock.py:74:38-49: Expected 1 positional argument, got 2 in function `tuple.__new__` [bad-argument-count]
+ ERROR rotkehlchen/tests/utils/mock.py:74:27-36: Expected valid functional named tuple definition [bad-class-definition]
+ ERROR rotkehlchen/tests/utils/mock.py:74:51-58: Unexpected keyword argument `version` in function `Version.__new__` [unexpected-keyword]
dd-trace-py (https://github.com/DataDog/dd-trace-py)
- ERROR ddtrace/vendor/psutil/_pslinux.py:274:61-64: Argument `float` is not assignable to parameter `iterable` with type `Iterable[Any]` in function `tuple.__new__` [bad-argument-type]
- ERROR ddtrace/vendor/psutil/_pslinux.py:274:66-69: Expected 1 positional argument, got 3 in function `tuple.__new__` [bad-argument-count]
scipy (https://github.com/scipy/scipy)
- ERROR scipy/stats/_mstats_basic.py:311:48-55: Class member `ModeResult.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
- ERROR scipy/stats/_stats_py.py:471:48-55: Class member `ModeResult.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
- ERROR scipy/stats/_stats_py.py:2234:31-38: Class member `HistogramResult.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
cloud-init (https://github.com/canonical/cloud-init)
- ERROR tests/unittests/analyze/test_show.py:13:64-71: Expected 1 positional argument, got 2 in function `tuple.__new__` [bad-argument-count]
- ERROR tests/unittests/config/test_cc_install_hotplug.py:29:9-24: Expected 1 positional argument, got 6 in function `tuple.__new__` [bad-argument-count]
vision (https://github.com/pytorch/vision)
- ERROR torchvision/datasets/celeba.py:13:36-43: Class member `CSV.index` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
mypy (https://github.com/python/mypy)
- ERROR mypy/typeshed/stdlib/platform.pyi:55:13-22: Class member `uname_result.processor` overrides parent class `_uname_result_base` in an inconsistent manner [bad-override]
core (https://github.com/home-assistant/core)
- ERROR homeassistant/components/modbus/validators.py:72:9-16: Class member `PARM_IS_LEGAL.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
paasta (https://github.com/yelp/paasta)
- ERROR paasta_tools/mesos_tools.py:67:48-55: Class member `SlaveTaskCount.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
spack (https://github.com/spack/spack)
- ERROR lib/spack/spack/util/timer.py:21:72-79: Class member `TimeTracker.count` overrides parent class `NamedTupleFallback` in an inconsistent manner [bad-override]
spark (https://github.com/apache/spark)
- ERROR python/pyspark/tests/test_context.py:291:72-76: Argument `None` is not assignable to parameter `iterable` with type `Iterable[Any]` in function `tuple.__new__` [bad-argument-type]
scipy-stubs (https://github.com/scipy/scipy-stubs)
+ ERROR scipy-stubs/stats/_mstats_basic.pyi:123:1-2: Unused `# pyrefly: ignore` comment for code(s): bad-override [unused-ignore]
+ ERROR scipy-stubs/stats/_stats_py.pyi:219:1-2: Unused `# pyrefly: ignore` comment for code(s): bad-override [unused-ignore]
+ ERROR scipy-stubs/stats/_stats_py.pyi:223:1-2: Unused `# pyrefly: ignore` comment for code(s): bad-override [unused-ignore]
|
Primer Diff Classification❌ 1 regression(s) | ✅ 9 improvement(s) | ➖ 1 neutral | 11 project(s) total | +5, -15 errors 1 regression(s) across scipy-stubs. error kinds:
Detailed analysis❌ Regression (1)scipy-stubs (+3)
✅ Improvement (9)dd-trace-py (-2)
scipy (-3)
cloud-init (-2)
vision (-1)
mypy (-1)
core (-1)
paasta (-1)
spack (-1)
spark (-1)
➖ Neutral (1)rotki (+2, -2)
Suggested fixesSummary: The 1. In the override checking loop in
Was this helpful? React with 👍 or 👎 Classification by primer-classifier (11 LLM) |
grievejia
left a comment
There was a problem hiding this comment.
Review automatically exported from Phabricator review in Meta.
|
@yangdanny97 merged this pull request in 9832cb7. |
Summary
Fixes #2811
now synthesizes anonymous functional namedtuple classes when collections.namedtuple(...) or typing.NamedTuple(...) appears inline in expression position, instead of only when bound to a name or used as a base class.
Test Plan
add test