-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[red-knot] Avoid undeclared path when raising conflicting declarations #14958
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.
Tests look great! I think we should move the fix inside declarations_ty
, and add a test for the "three paths, conflicting declarations in two of them" case.
if let Some(undeclared_ty) = undeclared_ty { | ||
if conflicting.iter().any(|ty| ty == &undeclared_ty) { | ||
return ty; | ||
} | ||
} |
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.
I think this has an issue: there could be three or more conflicting types, e.g. int
, str
, and Unknown
; this should still emit a diagnostic for the conflict between int
and str
.
It's also a little weird that we just search for Unknown
, because there could be an actual annotation x: Foo
in one path, where Foo
resolves to Unknown
(e.g. because it is imported from a module we can't find), and we would still treat this Unknown
the same as the undeclared-path Unknown
.
I think it would be easier to make a more correct fix if we do it inside declarations_ty
instead, so that in the cases where we don't want to emit the diagnostic, we don't even return an Err
result at all.
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.
Ah yes, thanks for pointing that out. I've pushed a commit that moves the logic to declarations_ty
which doesn't consider the undeclared_ty
when looking for conflicting types. It does add the type to the final declared type.
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:108:17 Conflicting declared types for `second_char`: Unknown, str | None", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:115:14 Name `char` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:126:12 Name `char` used when possibly not defined", | ||
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:267:9 Conflicting declared types for `char`: Unknown, str | None", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:348:20 Name `nest` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:353:5 Name `nest` used when possibly not defined", | ||
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:364:9 Conflicting declared types for `char`: Unknown, str | None", | ||
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:381:13 Conflicting declared types for `char`: Unknown, str | None", | ||
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:395:9 Conflicting declared types for `char`: Unknown, str | None", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:453:24 Name `nest` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:455:9 Name `nest` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:482:16 Name `char` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:566:12 Name `char` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:573:12 Name `char` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:579:12 Name `char` used when possibly not defined", | ||
"warning[lint:possibly-unresolved-reference] /src/tomllib/_parser.py:580:63 Name `char` used when possibly not defined", | ||
"error[lint:conflicting-declarations] /src/tomllib/_parser.py:590:9 Conflicting declared types for `char`: Unknown, str | None", |
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.
Love to see these go away!
e31db29
to
914389f
Compare
914389f
to
9967298
Compare
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.
Looks great, thank you!
* main: [red-knot] Explicitly test diagnostics are emitted for unresolvable submodule imports (#15035) Fix stale File status in tests (#15030) [red-knot] Basic support for other legacy `typing` aliases (#14998) feat(AIR302): extend the following rules (#15015) [`perflint`] Simplify finding the loop target in `PERF401` (#15025) [red-knot] Avoid undeclared path when raising conflicting declarations (#14958)
Summary
This PR updates the logic when raising conflicting declarations diagnostic to avoid the undeclared path if present.
The conflicting declaration diagnostics is added when there are two or more declarations in the control flow path of a definition whose type isn't equivalent to each other. This can be seen in the following example:
After this PR, we'd avoid considering "Unknown" as part of the conflicting declarations. This means we'd still flag it for the following case:
A solution that's local to the exception control flow was also explored which required updating the logic for merging the flow snapshot to avoid considering declarations using a flag. This is preserved here: https://github.com/astral-sh/ruff/compare/dhruv/control-flow-no-declarations?expand=1.
The main motivation to avoid that is we don't really understand what the user experience is w.r.t. the Unknown type and the conflicting-declaration diagnostics. This makes us unsure on what the right semantics are as to whether that diagnostics should be raised or not and when to raise them. For now, we've decided to move forward with this PR and could decide to adopt another solution or remove the conflicting-declaration diagnostics in the future.
Closes: #13966
Test Plan
Update the existing mdtest case. Add an additional case specific to exception control flow to verify that the diagnostic is not being raised now.