Skip to content

Diagnose instance methods missing a positional receiver - #5425

Open
mangeshraut712 wants to merge 5 commits into
meta:mainfrom
mangeshraut712:fix/5295-instance-method-missing-self
Open

mangeshraut712 wants to merge 5 commits into
meta:mainfrom
mangeshraut712:fix/5295-instance-method-missing-self

Conversation

@mangeshraut712

Copy link
Copy Markdown
Contributor

Summary

Instance methods with no positional parameter (and no *args) were accepted without a definition error. Classmethods without a receiver are covered separately in #5388 / #5294; this PR handles the instance-method case from #5295.

After decorator handling, if the method still looks like a normal instance method (self_type is set, not classmethod/staticmethod/@no_type_check, no remaining custom decorators) and has no posonly/args/*vararg, emit bad-function-definition.

Fixes #5295

  • I am a human, and I fully understand the code I am submitting.

Test Plan

  • Added test_instance_method_missing_receiver and test_instance_method_missing_receiver_decorators in attributes.rs (covers kwargs-only / keyword-only / recognized vs custom decorators).
  • Updated expected errors in existing fixtures that already defined bare instance methods (attributes, callable, class_overrides, constructors, abstract_methods, narrow, descriptors).
  • cargo test -p pyrefly --lib -- test::attributes:: test::descriptors::test_self_referential test::class_overrides::test_override_method_without_self test::constructors:: test::abstract_methods:: test::callable:: test::narrow::test_typeguard test::narrow::test_typeis test::decorators:: test::protocol:: — all passed.

Report bad-function-definition when a class instance method has no
positional parameter and no *args to accept the implicit self.
Skip classmethods, staticmethods, @no_type_check, and methods with
unresolved custom decorators that may reshape the signature.

Fixes meta#5295
@meta-codesync

meta-codesync Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D127981932. (Because this pull request was imported automatically, there will not be any future comments.)

Add self to hover_docstring and class-scope fixtures that used bare
def f(): (now bad-function-definition). Use Foo.f attribute access in
attribute_test to avoid MissingArgument. Bump nested_scopes bench
expected errors 20→23 for class-nested bare defs at depths 4/8/12.
@github-actions github-actions Bot added size/m and removed size/m labels Oct 28, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions Bot added size/m and removed size/m labels Nov 1, 2026
@github-actions

This comment has been minimized.

…ethod-missing-self

# Conflicts:
#	pyrefly/lib/alt/function.rs
@github-actions github-actions Bot added size/m and removed size/m labels Nov 2, 2026
@mangeshraut712

Copy link
Copy Markdown
Contributor Author

Merged main (dc690a8). Upstream's new classmethod receiver check sat in the same block, so both checks are kept, with the classmethod one first.

About the mypy_primer diff: 105 of the 107 new errors are zope.interface Interface classes (zope.interface itself, plus scrapy/interfaces.py). Those declare methods without self on purpose, because the interface describes the method as seen from an instance. The other two (pywin32 NotifyChanged, cvxpy _cylp_checks_isProvenInfeasible) look like real bugs. I can skip classes that inherit from zope.interface.Interface if you want that special case here, or keep the check plain and let zope users suppress it. Which do you prefer?

@github-actions

This comment has been minimized.

@rchen152 rchen152 added size/s and removed size/m labels Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

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

============================================================
SUMMARY
============================================================
Total: +107 new errors, -0 fixed errors
By preset: +107/-0 (default), +107/-0 (strict)

Projects with changes (4):
  zope.interface: +104 -0
  pywin32: +1 -0
  scrapy: +1 -0
  cvxpy: +1 -0
============================================================

FULL DIFF DETAILS
------------------------------------------------------------

zope.interface (https://github.com/zopefoundation/zope.interface)
+ ERROR src/zope/interface/common/idatetime.py:83:9-14: Instance method `today` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:139:9-18: Instance method `timetuple` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:148:9-18: Instance method `toordinal` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:155:9-16: Instance method `weekday` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:164:9-19: Instance method `isoweekday` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:173:9-20: Instance method `isocalendar` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:192:9-18: Instance method `isoformat` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:199:9-16: Instance method `__str__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:202:9-14: Instance method `ctime` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:234:9-14: Instance method `today` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:257:9-15: Instance method `utcnow` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:343:9-13: Instance method `date` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:346:9-13: Instance method `time` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:354:9-15: Instance method `timetz` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:402:9-18: Instance method `utcoffset` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:406:9-12: Instance method `dst` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:411:9-15: Instance method `tzname` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:414:9-18: Instance method `timetuple` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:417:9-21: Instance method `utctimetuple` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:420:9-18: Instance method `toordinal` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:426:9-16: Instance method `weekday` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:433:9-19: Instance method `isoweekday` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:441:9-20: Instance method `isocalendar` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:462:9-16: Instance method `__str__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:469:9-14: Instance method `ctime` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:535:9-18: Instance method `isoformat` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:544:9-16: Instance method `__str__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:553:9-18: Instance method `utcoffset` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:563:9-12: Instance method `dst` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/idatetime.py:573:9-15: Instance method `tzname` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:83:9-13: Instance method `keys` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:87:9-17: Instance method `__iter__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:91:9-15: Instance method `values` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:95:9-14: Instance method `items` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:117:9-13: Instance method `copy` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:136:9-14: Instance method `clear` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/mapping.py:156:9-16: Instance method `popitem` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/sequence.py:158:9-16: Instance method `reverse` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/common/tests/test_collections.py:132:13-41: Instance method `FrameLocalsProxy_constructor` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:113:9-27: Instance method `getTaggedValueTags` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:144:9-33: Instance method `getDirectTaggedValueTags` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:164:9-25: Instance method `getSignatureInfo` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:181:9-27: Instance method `getSignatureString` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:399:9-17: Instance method `__iter__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:423:9-17: Instance method `__iter__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:427:9-18: Instance method `flattened` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:464:9-20: Instance method `__nonzero__` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:1250:9-28: Instance method `registeredUtilities` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:1334:9-27: Instance method `registeredAdapters` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:1425:9-39: Instance method `registeredSubscriptionAdapters` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/interfaces.py:1503:9-27: Instance method `registeredHandlers` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:140:17-24: Instance method `aMethod` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:216:17-24: Instance method `aMethod` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:241:17-24: Instance method `method1` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:244:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:252:17-24: Instance method `method3` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:255:17-24: Instance method `method4` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:258:17-24: Instance method `method5` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:385:17-24: Instance method `aMethod` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:461:17-24: Instance method `aMethod` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:486:17-24: Instance method `method1` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:489:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:497:17-24: Instance method `method3` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:500:17-24: Instance method `method4` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_document.py:503:17-24: Instance method `method5` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1418:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1445:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1474:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1508:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1569:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1589:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1618:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1630:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1636:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1639:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1655:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1678:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1684:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1687:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1742:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1763:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1769:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1772:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1811:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1832:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1838:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1841:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1879:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1892:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1898:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1901:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1924:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1936:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1942:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1945:17-24: Instance method `method2` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_interface.py:1955:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:73:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:88:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:105:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:123:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:200:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:377:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:414:17-23: Instance method `method` must accept a positional argument [bad-function-definition]
+ ERROR src/zope/interface/tests/test_verify.py:448:17-23: Instance method `method` must accept a positional argument [bad-function-definition]

pywin32 (https://github.com/mhammond/pywin32)
+ ERROR com/win32comext/axdebug/test/host.py:105:9-22: Instance method `NotifyChanged` must accept a positional argument [bad-function-definition]

scrapy (https://github.com/scrapy/scrapy)
+ ERROR scrapy/interfaces.py:21:9-13: Instance method `list` must accept a positional argument [bad-function-definition]

cvxpy (https://github.com/cvxpy/cvxpy)
+ ERROR cvxpy/tests/test_conic_solvers.py:1579:9-40: Instance method `_cylp_checks_isProvenInfeasible` must accept a positional argument [bad-function-definition]

This branch has not been deployed

No deployments
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.

no error when instance method has no self parameter

3 participants