Skip to content

Split protected member diagnostics from no-access - #4537

Open
ting-hong-shieh wants to merge 1 commit into
facebook:mainfrom
ting-hong-shieh:fix/3659-private-usage
Open

Split protected member diagnostics from no-access#4537
ting-hong-shieh wants to merge 1 commit into
facebook:mainfrom
ting-hong-shieh:fix/3659-private-usage

Conversation

@ting-hong-shieh

Copy link
Copy Markdown

Summary

  • add a dedicated private-usage error kind for protected class members
  • allow single-underscore member access from the defining class and subclasses
  • keep double-underscore private attributes under no-access
  • map Pyright's reportPrivateUsage to private-usage and document the new diagnostic

Root cause

The Pyright migration mapped reportPrivateUsage to no-access, even though no-access only checked name-mangled double-underscore attributes. This made the migrated setting affect an unrelated diagnostic without enforcing protected-member access.

User impact

Projects migrating from Pyright can configure protected-member checks independently. Disabling no-access no longer disables reportPrivateUsage behavior.

Testing

  • cargo test protected_attribute
  • cargo test private_attribute
  • cargo test test_report_private_usage_mapping
  • formatter and Clippy through test.py
  • full Pyrefly library suite: 7,862 passed and 3 ignored; the sandbox-blocked IPC tests passed when rerun with IPC permissions

Fixes #3659

Map Pyright reportPrivateUsage to a dedicated error kind so disabling no-access no longer hides protected-member checks.
@meta-cla meta-cla Bot added the cla signed label Aug 13, 2026
@ting-hong-shieh
ting-hong-shieh marked this pull request as ready for review August 13, 2026 08:40
@meta-codesync

meta-codesync Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

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

@ting-hong-shieh

Copy link
Copy Markdown
Author

The Meta Builds & Tests check is currently failing, but the internal failure details are not accessible to external contributors. The local formatter, Clippy, targeted regressions, and Pyrefly library suite passed. Could someone with access share the failing test or log snippet so I can address it? Thanks!

@ting-hong-shieh

Copy link
Copy Markdown
Author

Following up on the internal Builds & Tests failure — I think I've found a likely cause, so this may not need anyone to dig out the log.

PrivateUsage isn't listed in default_severity, so it falls through to _ => Severity::Error, and parent_kind returns None for it. The new diagnostic is therefore an error by default for every project, and it fires on any obj._protected access from outside the defining class — ordinary practice inside a library's own internals.

Measured by checking polars 1.43.2's own source (207 files) as a project, building both sides from this checkout so the version is held constant:

main (1.3.0-dev.1) this branch
private-usage 0 350
bad-return 318 318
missing-import 163 163
invalid-annotation 6 6
total 487 837

Every other category is identical, so the 350 are entirely attributable to this change. They aren't false positives either — they're helper modules reaching into a sibling class, which is what the check is designed to catch:

ERROR Protected attribute `_ldf` cannot be accessed outside of its defining class or a subclass [private-usage]
  --> src/polars/_utils/cloud.py:39:15

If a 200-file library produces 350 of these, a large internal codebase would produce far more, which would explain the failure without anything being wrong with the check itself.

If that's right, the fix is to default it to Severity::Ignore and let people opt in, the way explicit-any and the implicit-any-* kinds already work. That also matches the setting it maps from — Pyright has reportPrivateUsage at "none" in off, basic, and standard, and only "error" in strict:

| reportPrivateUsage | "none" | "none" | "none" | "error" |

The migration path would be unaffected: test_report_private_usage_mapping in this PR already asserts that a Pyright config with reportPrivateUsage set maps onto PrivateUsage independently of NoAccess, so projects arriving from Pyright with the rule enabled would still get it. That was the point of #3659.

Happy to push that change. But the default severity of a new diagnostic is a product decision rather than mine to assume, so I'll wait for a maintainer to say which way you want it — and if the internal failure turns out to be something else, a log snippet would still be welcome.

Disclosure, per the AI Usage section of CONTRIBUTING.md: the measurements above and this comment were produced by an AI agent (Claude Code) working in my checkout. I reviewed them before posting.

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.

reportPrivateUsage from pyright is not covered by no-access

2 participants