-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[red-knot] Add a test to ensure that KnownClass::try_from_file_and_name() is kept up to date
#16326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use strum::EnumString https://github.com/Peternator7/strum/wiki/Derive-EnumString if we're adding a strum dependency anyway?
This PR currently only adds strum as a dev-dependency. But I can make that change if we're happy to have the extra dependency in production as well. |
I also played around a bit with a solution to this TODO on the weekend. One thing that makes this more complicated are branches like this, where we have additional logic in the enum->string function: Self::EllipsisType => {
// Exposed as `types.EllipsisType` on Python >=3.10;
// backported as `builtins.ellipsis` by typeshed on Python <=3.9
if Program::get(db).python_version(db) >= PythonVersion::PY310 {
"EllipsisType"
} else {
"ellipsis"
}
} |
There shouldn't really be any difference. |
MichaReiser
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. Thank you (and sorry for the merge conflict :()
e6e8545 to
7455a2f
Compare
…deriving `EnumIter` fix test and add a similar one for `KnownModule` add a test for `KnownFunction` too Simplify by deriving `EnumString` where possible revert renamings of `KnownFunction` variants
7455a2f to
59f828e
Compare
* main: (38 commits) [red-knot] Use arena-allocated association lists for narrowing constraints (#16306) [red-knot] Rewrite `Type::try_iterate()` to improve type inference and diagnostic messages (#16321) Add issue templates (#16213) Normalize inconsistent markdown headings in docstrings (#16364) [red-knot] Better diagnostics for method calls (#16362) [red-knot] Add argfile and windows glob path support (#16353) [red-knot] Handle pipe-errors gracefully (#16354) Rename `venv-path` to `python` (#16347) [red-knot] Fixup some formatting in `infer.rs` (#16348) [red-knot] Restrict visibility of more things in `class.rs` (#16346) [red-knot] Add diagnostic for class-object access to pure instance variables (#16036) Add `per-file-target-version` option (#16257) [PLW1507] Mark fix unsafe (#16343) [red-knot] Add a test to ensure that `KnownClass::try_from_file_and_name()` is kept up to date (#16326) Extract class and instance types (#16337) Re-order changelog entries for 0.9.7 (#16344) [red-knot] Add support for `@classmethod`s (#16305) Update Salsa (#16338) Update Salsa part 1 (#16340) Upgrade Rust toolchain to 1.85.0 (#16339) ...
Summary
We keep on adding new variants to the
KnownClassenum but forgetting to update this method, because the Rust compiler only enforces exhaustiveness over enums when the enum variants appear on the left-hand side of thematchstatement:ruff/crates/red_knot_python_semantic/src/types.rs
Lines 3183 to 3231 in b312b53
That leads to subtle and confusing bugs that can be hard to debug, and that sometimes go unnoticed for several weeks.
This PR adds a test that will fail if we add a variant to the
KnownClassenum and forget to add a case toKnownClass::try_from_file_and_name(). It also adds tests for the similar methods on theKnownModuleandKnownFunctionenums.How it works
strumandstrum_macrosare added as test-only dependencies for red-knot (they are added to thedev-dependenciestable in thered_knot_python_semanticcrate'sCargo.toml). If thetestfeature is enabled, we derive theEnumItertrait for theKnownClassenum. In the tests forKnownClass, we then use the generatediter()method to iterate over allKnownClassvariants and verify that each variant has its own branch in theKnownClass::try_from_file_and_name()function.Following review, this has been changed:
strumandstrum_macrosare now just regular dependencies for red-knot, in production as well as if thetestfeature is enabled.KnownFunctionandKnownModule, we use theEnumStringmacro fromstrum_macrosto simplify the deserialization constructors and ensure that they are exhaustive over the right-hand side. (This unfortunately doesn't work forKnownClassbecause of the fact that theEllipsisTypebranch deserializes dynamically depending on the target Python version.)EnumItermacro.Limitations
Unfortunately, this approach doesn't work for the
KnownInstanceTypeenum.KnownInstanceTypeis generic over a lifetime, and theEnumItertrait cannot be derived for enums generic over a lifetime. I therefore haven't touched that enum in this PR.This approach also necessitated some small refactoring of the
KnownFunctionenum.EnumIterandEnumStringcouldn't be derived for the enum as-is because of the fact that theConstraintFunctionvariant wrapped inner data. I solved this by replacing theConstraintFunctionvariant (which wrapped an inner enum) with two variants (KnownFunction::IsSubclassandKnownFunction::IsInstance), and slightly reworking theKnownFunction::constraint_function()method (which is renamed toKnownFunction::into_constraint_function())