Skip to content

Conversation

@Renkai
Copy link
Contributor

@Renkai Renkai commented Sep 7, 2025

It's a TODO clean of PR #20164 that solved issue astral-sh/ty#939

@sharkdp
Copy link
Contributor

sharkdp commented Sep 8, 2025

Thank you for your contribution. It looks like a better format here would be a GitHub issue on the https://github.com/astral-sh/ty repo? Or is there a particular reason that you are opening a PR at this stage?

@Renkai
Copy link
Contributor Author

Renkai commented Sep 8, 2025

Hi, @sharkdp I want to clean some todos added in this PR:#20164
It's not finished yet so I mark this as draft in github. do you think we shall create an issue first? I'm not quite familiar with the best practice yet.

@sharkdp
Copy link
Contributor

sharkdp commented Sep 8, 2025

If you plan to do more changes in this draft PR, that's totally fine. I just thought you were looking for feedback on that document you added here. In that case, I'll assume that we wait for this to move to in-review.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 8, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@Renkai Renkai marked this pull request as ready for review September 8, 2025 11:28
@Renkai Renkai changed the title [ty][WIP]Create narrow_enum_pan.md [ty]reate narrow_enum_pan.md Sep 8, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Sep 8, 2025

mypy_primer results

Changes were detected when running on open source projects
isort (https://github.com/pycqa/isort)
- isort/api.py:573:12: warning[possibly-unresolved-reference] Name `key` used when possibly not defined
- isort/api.py:573:20: warning[possibly-unresolved-reference] Name `key` used when possibly not defined
- isort/api.py:574:22: warning[possibly-unresolved-reference] Name `key` used when possibly not defined
- Found 37 diagnostics
+ Found 34 diagnostics

rotki (https://github.com/rotki/rotki)
+ rotkehlchen/exchanges/kraken.py:960:57: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- rotkehlchen/exchanges/utils.py:201:37: warning[possibly-unresolved-reference] Name `url` used when possibly not defined
+ rotkehlchen/history/events/structures/swap.py:170:43: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 1589 diagnostics
+ Found 1590 diagnostics
No memory usage changes detected ✅

@AlexWaygood
Copy link
Member

Thanks! Could you possibly update your PR description to describe this change a little better?

Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

This is looking really good! I think it gets the correct semantics. A few comments on the implementation.

Comment on lines 755 to 774
let check_dunder = |dunder_name, allowed_return_value| {
// Note that we do explicitly exclude dunder methods on `object`, `int` and `str` here.
// The reason for this is that we know that these dunder methods behave in a predictable way.
// Only custom dunder methods need to be examined here, as they might break single-valuedness
// by always returning `False`, for example.
let call_result = self.try_call_dunder_with_policy(
db,
dunder_name,
&mut CallArguments::positional([Type::unknown()]),
MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK
| MemberLookupPolicy::MRO_NO_INT_OR_STR_LOOKUP,
);
let call_result = call_result.as_ref();
call_result.is_ok_and(|bindings| {
bindings.return_type(db) == Type::BooleanLiteral(allowed_return_value)
}) || call_result
.is_err_and(|err| matches!(err, CallDunderError::MethodNotAvailable))
};

check_dunder("__eq__", true) && check_dunder("__ne__", false)
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't duplicate all this code from is_single_valued; we should extract it as a separate method, e.g. Type::overrides_equality. (It doesn't even have to be specific to enums, even if we only call it for enums currently.)

/// Return true if this is an enum literal or enum class instance that doesn't override __eq__ or __ne__
fn is_simple_enum(&self, db: &'db dyn Db) -> bool {
let is_enum = match self {
Type::EnumLiteral(_) => true,
Copy link
Contributor

Choose a reason for hiding this comment

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

No mdtests fail if we remove this arm. I think that's because we only use this method as an additional check beyond is_single_valued, and enum literals are already always single-valued.

I think we can probably remove this is_simple_enum method altogether in favor of an is_enum method, and use ty.is_enum() && !ty.overrides_equality() everywhere the PR currently uses ty.is_simple_enum(). This isn't quite as concise but I think it's clearer, as its meaning is more self-evident, where the meaning of "simple enum" is not.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the review! I fixed it followed by your instruction, but cargo clippy forced me to use !element.is_enum(self.db) || element.overrides_equality(self.db) instead, hope it's still good to you.

@carljm carljm changed the title [ty]reate narrow_enum_pan.md [ty] equality narrowing on enums that don't override __eq__ or __ne__ Sep 8, 2025
@Renkai Renkai requested a review from carljm September 8, 2025 23:40
@carljm carljm merged commit 61f906d into astral-sh:main Sep 8, 2025
38 checks passed
second-ed pushed a commit to second-ed/ruff that referenced this pull request Sep 9, 2025
…e__` (astral-sh#20285)

Add equality narrowing for enums, if they don't override `__eq__` or `__ne__` in an unsafe way.

Follow-up to PR astral-sh#20164

Fixes astral-sh/ty#939
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants