Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[ty] Emit a diagnostic for subclassing with order=True#21704

Merged
sharkdp merged 9 commits into
mainfrom
charlie/order
May 22, 2026
Merged

[ty] Emit a diagnostic for subclassing with order=True#21704
sharkdp merged 9 commits into
mainfrom
charlie/order

Conversation

@charliermarsh

Copy link
Copy Markdown
Member

Summary

Closes astral-sh/ty#1681.

@charliermarsh charliermarsh changed the title Emit a diagnostic for subclassing with order=True [ty] Emit a diagnostic for subclassing with order=True Nov 30, 2025
@charliermarsh charliermarsh added the ty Multi-file analysis & type inference label Nov 30, 2025
@astral-sh-bot

astral-sh-bot Bot commented Nov 30, 2025

Copy link
Copy Markdown

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 89.36%. The percentage of expected errors that received a diagnostic held steady at 85.49%. The number of fully passing files held steady at 88/134.

@charliermarsh

Copy link
Copy Markdown
Member Author

I believe those changes on the conformance tests are "correct" in-so-far as those are instances of the case we want to catch here.

@astral-sh-bot

astral-sh-bot Bot commented Nov 30, 2025

Copy link
Copy Markdown

ecosystem-analyzer results

No diagnostic changes detected ✅

Large timing changes:

Project Old Time New Time Change
pandas-stubs 8.57s 13.19s +54%

Full report with detailed diff (timing results)

@AlexWaygood AlexWaygood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment thread crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md Outdated
Comment thread crates/ty_python_semantic/resources/mdtest/liskov.md
Comment thread crates/ty_python_semantic/src/types/infer/builder.rs Outdated
Comment thread crates/ty_python_semantic/src/types/diagnostic.rs Outdated
Comment thread crates/ty_python_semantic/src/types/diagnostic.rs Outdated
@AlexWaygood

Copy link
Copy Markdown
Member

@charliermarsh are you still interested in getting this over the line?

@charliermarsh

Copy link
Copy Markdown
Member Author

Yes sir, sorry, lost track.

@charliermarsh charliermarsh force-pushed the charlie/order branch 2 times, most recently from 24d480b to 634765c Compare January 6, 2026 16:10
@charliermarsh

Copy link
Copy Markdown
Member Author

I think the Expression diagnostic is correct:

  Expression (Try inherits from Result)

  - Result is decorated with @tagged_union(frozen=True, order=True)
  - tagged_union is marked with @dataclass_transform(), so ty recognizes it as a dataclass-like decorator
  - When order=True is passed, the class gets ordering methods
  - Try inherits from Result without defining its own comparison methods
  - True positive: At runtime, Try(Success(1)) < Result(Success(2)) would raise TypeError

@AlexWaygood AlexWaygood self-assigned this Jan 16, 2026
@carljm carljm removed their request for review February 4, 2026 01:42
@astral-sh-bot

astral-sh-bot Bot commented Feb 11, 2026

Copy link
Copy Markdown

Memory usage report

Summary

Project Old New Diff Outcome
sphinx 256.67MB 256.70MB +0.01% (37.92kB)
prefect 688.02MB 688.05MB +0.01% (37.04kB)
trio 113.60MB 113.61MB +0.01% (8.07kB)
flake8 47.52MB 47.52MB +0.00% (720.00B)

Significant changes

Click to expand detailed breakdown

sphinx

Name Old New Diff Outcome
StaticClassLiteral<'db>::has_own_comparison_methods_ 0.00B 11.03kB +11.03kB (new)
infer_scope_types_impl 12.95MB 12.96MB +0.08% (10.96kB)
infer_definition_types 22.03MB 22.03MB +0.03% (7.70kB)
FunctionType 3.25MB 3.26MB +0.11% (3.72kB)
OverloadLiteral 1022.45kB 1.00MB +0.18% (1.86kB)
place_by_id 1.37MB 1.37MB +0.10% (1.46kB)
place_by_id::interned_arguments 1.03MB 1.03MB +0.11% (1.20kB)

prefect

Name Old New Diff Outcome
infer_scope_types_impl 48.05MB 48.07MB +0.04% (17.31kB)
StaticClassLiteral<'db>::has_own_comparison_methods_ 0.00B 15.05kB +15.05kB (new)
infer_definition_types 81.91MB 81.91MB +0.00% (2.27kB)
FunctionType 9.58MB 9.58MB +0.01% (1.09kB)
OverloadLiteral 3.82MB 3.82MB +0.01% (560.00B)
place_by_id 4.86MB 4.86MB +0.01% (440.00B)
place_by_id::interned_arguments 3.59MB 3.59MB +0.01% (360.00B)

trio

Name Old New Diff Outcome
StaticClassLiteral<'db>::has_own_comparison_methods_ 0.00B 3.27kB +3.27kB (new)
infer_scope_types_impl 4.00MB 4.00MB +0.07% (2.93kB)
infer_definition_types 7.24MB 7.24MB +0.01% (928.00B)
FunctionType 1.51MB 1.51MB +0.03% (448.00B)
OverloadLiteral 440.43kB 440.64kB +0.05% (224.00B)
place_by_id 546.38kB 546.55kB +0.03% (176.00B)
place_by_id::interned_arguments 407.74kB 407.88kB +0.03% (144.00B)

flake8

Name Old New Diff Outcome
StaticClassLiteral<'db>::has_own_comparison_methods_ 0.00B 420.00B +420.00B (new)
infer_scope_types_impl 822.42kB 822.71kB +0.04% (300.00B)

@charliermarsh charliermarsh force-pushed the charlie/order branch 2 times, most recently from ef4cee5 to 151ce7e Compare February 18, 2026 16:21
&class_node.bases()[i],
base_params,
);
if let Some(class_params) = class.dataclass_params(self.db()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will only for work standard library dataclasses. I haven't looked closer at this PR, but we should probably make sure that this works for dataclass_transformers as well. See #23366 for a related PR that expands the frozen/non-frozen-inheritance checks here in the same way.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I attempted to fix it...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I will get this PR merged once #23366 lands.

@charliermarsh charliermarsh force-pushed the charlie/order branch 2 times, most recently from a727348 to b2b1ccd Compare February 25, 2026 15:26
@sharkdp sharkdp marked this pull request as draft May 19, 2026 12:34
@sharkdp

sharkdp commented May 19, 2026

Copy link
Copy Markdown
Contributor

Charlie, sorry for the delay here. This is still low prio, and more complicated than it looks. Working on it...

@sharkdp

sharkdp commented May 19, 2026

Copy link
Copy Markdown
Contributor

My current problem is that I think inheriting from order=True is basically never safe? That is, except for edge cases where you don't add new fields in the child class? Even something like this fails:

>>> @dataclass(order=True)
... class C:
...     x: int
...
>>> @dataclass(order=True)
... class D(C):
...     y: str
...
>>> C(1) < D(2, "a")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'C' and 'D'

That means you can't safely use a D where a C is expected, and therefore this new rule here should flag the construction of D. Enforcing that would require us to emit this diagnostic in too many places, though. So I'm wondering if it's all that useful. Interested in @AlexWaygood's opinion, since you proposed this rule originally.

@charliermarsh

Copy link
Copy Markdown
Member Author

I'm fine to just close this and prioritize other work if you prefer, not a big deal and clearly more complicated than initially perceived.

@AlexWaygood

Copy link
Copy Markdown
Member

My current problem is that I think inheriting from order=True is basically never safe? That is, except for edge cases where you don't add new fields in the child class?

Even cases where you don't add new fields in the child class are unsafe, I believe -- see the example in the original issue I wrote up!

Enforcing that would require us to emit this diagnostic in too many places, though.

Not sure I follow... you just think it would be so many diagnostics that it would be overwhelming for users? Maybe, but I'm not sure order=True is a very popular feature, and subclassing order=True dataclasses is even rarer. And there's a pretty simple solution to the diagnostic: just use functools.total_ordering instead of using order=True if you intend to subclass the dataclass. functools.total_ordering doesn't have the same issue. We could even add an autofix that makes the change for you in the future.

@sharkdp

sharkdp commented May 19, 2026

Copy link
Copy Markdown
Contributor

Enforcing that would require us to emit this diagnostic in too many places, though.

Not sure I follow... you just think it would be so many diagnostics that it would be overwhelming for users?

As you can see from the ecosystem report, some dataclass-transformer libraries set order_default=True, and so you would basically have to set order=False on your model to enable any sort of subclassing. So yes, I assume this would be quite disruptive? Maybe there's a reason that no other type checker has implemented a rule like this?

But I guess we could make that rule opt-in?

@AlexWaygood

Copy link
Copy Markdown
Member

Ah I see. Sorry, I hadn't looked at the ecosystem report, and didn't consider the impact on third-party dataclass-transformer libraries.

Are we not able to distinguish between stdlib dataclasses and third-party libraries? Could we add that distinction? I'd be fine making this rule only apply to stdlib dataclasses.

We may need to add this distinction anyway, to fix issues like astral-sh/ty#3486, where third-party dataclass-transform libraries behave differently to stdlib dataclasses.

@sharkdp

sharkdp commented May 20, 2026

Copy link
Copy Markdown
Contributor

Are we not able to distinguish between stdlib dataclasses and third-party libraries? Could we add that distinction? I'd be fine making this rule only apply to stdlib dataclasses.

It's easy to distinguish between the two. In fact, the original version here only implemented the check for stdlib dataclasses, but I argued that we should treat dataclass transformers in the same way ("If dataclass_transform is applied to a class, dataclass-like semantics will be assumed [...]") 🙃

I'll leave it up to you to decide what we do here (I will make the changes accordingly):

  • flag both stdlib dataclasses and transformers, but make the rule opt-in
  • only flag stdlib dataclasses, keep the rule enabled by default
  • do not implement this rule at all (after all, there's only a single ecosystem hit for stdlib dataclasses, IIRC)

@charliermarsh

Copy link
Copy Markdown
Member Author

only flag stdlib dataclasses, keep the rule enabled by default

I'm cool with this, though also cool with just closing for now and calling this a non-priority for stable.

@AlexWaygood

Copy link
Copy Markdown
Member

I'd also go with

only flag stdlib dataclasses, keep the rule enabled by default

I think unfortunately it's pretty clear that third-party dataclass_transform libraries often differ from the stdlib dataclasses module in edge cases. So whereas we want to abide by this when it comes to synthesizing dataclass fields and methods, etc.:

If dataclass_transform is applied to a class, dataclass-like semantics will be assumed [...]"

...I'm less sure that we want to abide by that principle so strictly when it comes to things like "in this specific edge case, the stdlib dataclasses module is known to raise a TypeError, and we'll emit a diagnostic warning you about that" (which this feels closer to).

@astral-sh astral-sh deleted a comment from astral-sh-bot Bot May 20, 2026

@sharkdp sharkdp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is happening!

(very sorry this took so long)

@sharkdp sharkdp marked this pull request as ready for review May 22, 2026 08:50
@astral-sh-bot astral-sh-bot Bot requested a review from sharkdp May 22, 2026 08:50
@sharkdp sharkdp merged commit cebed58 into main May 22, 2026
90 of 91 checks passed
@sharkdp sharkdp deleted the charlie/order branch May 22, 2026 08:51
thejchap pushed a commit to thejchap/ruff that referenced this pull request May 23, 2026
anishgirianish pushed a commit to anishgirianish/ruff that referenced this pull request May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add diagnostic warning about unsound subclassing of order=True dataclasses

4 participants