-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[red-knot] Add diagnostic for class-object access to pure instance variables #16036
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] Add diagnostic for class-object access to pure instance variables #16036
Conversation
|
@sharkdp first, sorry for taking so long, I got distracted by work ;-) second, sorry for a long read for such a small thing. However, since we can't just talk it over - I'll dump why I think it is a band aid and PR marked as draft. Disclaimer: by no means I am implying there is anything wrong with knot code. I totally understand that you are moving crazy fast and this is one huge undertaking, so I totally get it when something is not "perfect" or a temporary solution. The reason it took me multiple hours to understand what's happening is that I got confused by the fact that knot uses a notion of "Symbol" for both real symbols and unbound declarations, which are not symbols at runtime. They only end up in annotations: Even though I quickly found the passage rgd Further, confusing the matter was the fact that IdeasSymbol::TypeTbh and imho symbols and declarations should be split. At least in this context. But I felt like doing so would cause too many changes in too many places. Something I would only do if you confirm such an idea. There are multiple ways this can be done:
Split
|
|
well. here is one false-positive from this change: https://github.com/astral-sh/ruff/actions/runs/13212332102/job/36887424507?pr=16036#step:7:94 ClassVar in stubs/ABCs needs to be handled as bound... I'll look into it later |
|
As mentioned on Discord, I'll split my reply into a few comments
Commenting on this first. This should definitely be discussed elsewhere (ideally as a ticket first), but I don't think that we want either of these changes. Unlike mypy, we deliberately distinguish The difference between the two is:
More concretely, both class C: ...
class D(C): ...The union-type representation change would be more stylistic, but I don't see any argument for choosing |
Yeah, that's why put them in a separate commit. I had a hunch ;-) I just saw comments like "we want to improve the message". I'll drop this commit, no prob.
yes, I do understand that and I saw that you use generate
same here. I went "conventional" way (mypy). If you keep |
I should have described this better in the TODO comment: ruff/crates/red_knot_python_semantic/resources/mdtest/attributes.md Lines 53 to 56 in f7819e5
I didn't specifically want to talk about the |
It's completely fine to call this out. We know that the That said, I would appreciate if we could move this discussion into a new ticket, to discuss it separately from the change in question here. |
|
I now had a more detailed look at the ideas you proposed and they do look very interesting to me. They definitely go in the right direction. What I would prefer is if we could decouple any refactoring from this functional change here. Your "bandaid" solution doesn't look too bad to me, given our current API restrictions. It would be great if you could remove the second commit from this branch, then we could focus on the functional change here and try to understand the errors in stub files better. |
CodSpeed Performance ReportMerging #16036 will not alter performanceComparing Summary
|
|
@sharkdp first rdg the PR:
Am I right, that you also want me to create a separate diagnostic for this specific access patter with the message you suggested? Didn't have time for this yet. Also, I didn't do extensive validation that ABC's are properly caught in all possible scenarios. But at least based on two tests they do. Now back to the general design. Or should I move this to astral-sh/ty#229? I saw astral-sh/ty#229 and related comments, but not https://github.com/astral-sh/ruff/blob/main/crates/red_knot_python_semantic/resources/mdtest/boundness_declaredness/public.md - thanks for the link. I think the table is awesome, it literally suggest the perfect way to model this. I'd refactor symbol to: #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum BindingStatus<'db> {
Bound(Type<'db>),
PossiblyUnbound(Type<'db>),
Unbound,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum DeclarationStatus<'db> {
Declared(TypeAndQualifiers<'db>),
PossiblyDeclared(TypeAndQualifiers<'db>),
Undeclared,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Symbol<'db> {
Known(BindingStatus<'db>, DeclarationStatus<'db>),
/// Or Make Symbol a tuple since Unknown == BindingStatus::Unbound & DeclarationStatus::Undeclared
Unknown,
}return this from |
|
AlexWaygood
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.
Nice! I haven't done a full review, but I spotted a few things looking over quickly
carljm
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.
Thank you!
crates/red_knot_python_semantic/resources/mdtest/expression/attribute.md
Outdated
Show resolved
Hide resolved
|
I suspect the performance regression on the incremental benchmark here is not avoidable. We just need more cached query results now that we distinguish more ways to resolve symbols, and more cached query results means more re-validation cost in Salsa. |
Note that we haven't got up to date benchmark numbers on this PR right now, as the assertion in the benchmark regarding the number of diagnostics has been failing for the last few commits, so codspeed has not been running |
I'm also questioning this conclusion -- I think if we were able to make |
|
I haven't reviewed this PR yet because there are already a lot of folks involved. Feel free to ping me if or when a review from my side would be good. |
carljm
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 looks pretty good to me! I see your point about how it's sub-optimal until we address bound vs declared in Symbol, left an inline comment about that.
I think we need to get the benchmark running so we can see the perf impact of this, and evaluate the impact of tracking or not tracking symbol_by_id. But otherwise this looks good.
Sorry about the rebase conflicts; this was a particularly fast-moving week! Thanks for working on this!
ef20b41 to
5f0bff7
Compare
|
|
CodSpeed says this is a 1% cold and 3% incremental regression. That's improved from 5.5% incremental regression in the prior version. I think the current regression is acceptable and within the reasonable range for the added functionality here. It may be that we get some improvement from resolving the TODO around re-resolving bindings. |
AlexWaygood
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.
thanks again, and sorry we keep creating merge conflicts for you here!
crates/red_knot_python_semantic/resources/mdtest/expression/attribute.md
Outdated
Show resolved
Hide resolved
|
@mishamsk I can look into making the required changes to get this merged — thank you very much for your work! |
…for-pure-instance-variables-access-from-class
thanks. I was going to say that I am happy to apply the requested changes myself, but looks like it is too late ;-) |
sharkdp
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.
Thank you very much. The final benchmarks show a -1% regression on the incremental setup.
|
@sharkdp thanks for pushing this over the edge. YaY |
Summary
This is at best a band-aid solution for #15963 . See my first comment below for discussion.
As of time of writing:
[unresolved-attribute]diagnosticType::ClassLiteralrepresentation totype[ClassName]matching mypy (this was already the case forType::SubclassOf)types.UnionType[TypeOne, TypeTwo, ...]also matching mypyI didn't not add a separate new lint, despite the issue description. I am not sure why
[unresolved-attribute]is not appropriate. Unbound attributes indeed do not exist at runtime, so the language seems perfectly appropriate.Test Plan
cargo nextest run -p red_knot_python_semantic --no-fail-fast