[ty] fix comparisons and arithmetic with NewTypes of float#22105
[ty] fix comparisons and arithmetic with NewTypes of float#22105oconnor663 merged 2 commits intomainfrom
NewTypes of float#22105Conversation
2f3e834 to
0aeee50
Compare
Diagnostic diff on typing conformance testsNo changes detected when running ty on typing conformance tests ✅ |
crates/ty_python_semantic/resources/mdtest/annotations/new_types.md
Outdated
Show resolved
Hide resolved
|
a2bb4c4 to
9cefff0
Compare
|
I've added support/tests for Edit: ChatGPT caught a real mistake below, which I think is responsible for the failing fuzz tests and the excessive new ecosystem errors. Will update. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
9cefff0 to
95cbec2
Compare
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-await |
0 | 2 | 6 |
invalid-return-type |
0 | 1 | 5 |
possibly-missing-attribute |
0 | 3 | 1 |
unresolved-attribute |
0 | 0 | 2 |
invalid-argument-type |
0 | 1 | 0 |
unused-ignore-comment |
1 | 0 | 0 |
| Total | 1 | 7 | 14 |
|
Minimal repro for these failures, new in this PR: from typing import NewType
Key = NewType("Key", object)
class ThingWithKeys:
def __contains__(self, refname: Key) -> bool:
return False
def _(key: Key, keys: ThingWithKeys):
key in keys # error[unsupported-operator]: Unsupported `in` operation |
|
Ok all of the added and removed diagnostics are gone. (Is there really nobody in the ecosystem report trying to do arithmetic on newtypes of float?) What remains is just unions that get printed differently. Some of them look like random ordering flakes, but others are cases where |
f3d440a to
94d22ea
Compare
There was a problem hiding this comment.
This all makes sense on paper. This special-case is only triggered by float/complex because NewType otherwise doesn't permit taking a union as an argument, right? Are there other cases where you can smuggle unions that we might not be checking for though? Type aliases (of various flavours)?
| reveal_type(Foo(3.14) + Bing()) # revealed: Foo | ||
| reveal_type(Bing() + Foo(42)) # revealed: Foo | ||
| reveal_type(Foo(3.14) < Bing()) # revealed: bool | ||
| reveal_type(Bing() < Foo(42)) # revealed: bool | ||
| reveal_type(Foo(3.14) in Bing()) # revealed: bool | ||
| ``` | ||
|
|
There was a problem hiding this comment.
Can you include the negative cases like you had for int? Those seemed important/valuable.
Right. That restriction is implemented here. Apart from the |
…king When calling a method on an instance of a generic class with bounded type parameters (e.g., `C[T: K]` where `K` is a NewType), ty was incorrectly reporting: "Argument type `C[K]` does not satisfy upper bound `C[T@C]` of type variable `Self`" The issue was introduced by PR #22105, which added a catch-all case for NewType assignments that falls back to the concrete base type. This case was placed before the TypeVar handling cases, so when checking `K <: T@C` (where K is a NewType and T@C is a TypeVar with upper bound K): 1. The NewType fallback matched first 2. It delegated to `int` (K's concrete base type) 3. Then checked `int <: T@C`, which checks if `int` satisfies bound `K` 4. But `int` is not assignable to `K` (NewTypes are distinct from their bases) The fix moves the NewType fallback case after the TypeVar cases, so TypeVar handling takes precedence. Now when checking `K <: T@C`, we use the TypeVar case at line 828 which returns `false` for non-inferable typevars - but this is correct because the *other* direction (`T@C <: K`) passes, and for the overall specialization comparison both directions are checked. Fixes astral-sh/ty#2467 Co-Authored-By: Carl Meyer <[email protected]>
…king When calling a method on an instance of a generic class with bounded type parameters (e.g., `C[T: K]` where `K` is a NewType), ty was incorrectly reporting: "Argument type `C[K]` does not satisfy upper bound `C[T@C]` of type variable `Self`" The issue was introduced by PR #22105, which added a catch-all case for NewType assignments that falls back to the concrete base type. This case was placed before the TypeVar handling cases, so when checking `K <: T@C` (where K is a NewType and T@C is a TypeVar with upper bound K): 1. The NewType fallback matched first 2. It delegated to `int` (K's concrete base type) 3. Then checked `int <: T@C`, which checks if `int` satisfies bound `K` 4. But `int` is not assignable to `K` (NewTypes are distinct from their bases) The fix moves the NewType fallback case after the TypeVar cases, so TypeVar handling takes precedence. Now when checking `K <: T@C`, we use the TypeVar case at line 828 which returns `false` for non-inferable typevars - but this is correct because the *other* direction (`T@C <: K`) passes, and for the overall specialization comparison both directions are checked. Fixes astral-sh/ty#2467 Co-Authored-By: Carl Meyer <[email protected]>
…king When calling a method on an instance of a generic class with bounded type parameters (e.g., `C[T: K]` where `K` is a NewType), ty was incorrectly reporting: "Argument type `C[K]` does not satisfy upper bound `C[T@C]` of type variable `Self`" The issue was introduced by PR #22105, which moved the catch-all case for NewType assignments that falls back to the concrete base type. This case was placed before the TypeVar handling cases, so when checking `K <: T@C` (where K is a NewType and T@C is a TypeVar with upper bound K): 1. The NewType fallback matched first 2. It delegated to `int` (K's concrete base type) 3. Then checked `int <: T@C`, which checks if `int` satisfies bound `K` 4. But `int` is not assignable to `K` (NewTypes are distinct from their bases) The fix moves the NewType fallback case after the TypeVar cases, so TypeVar handling takes precedence. Fixes astral-sh/ty#2467
) Fixes astral-sh/ty#2467 When calling a method on an instance of a generic class with bounded type parameters (e.g., `C[T: K]` where `K` is a NewType), ty was incorrectly reporting: "Argument type `C[K]` does not satisfy upper bound `C[T@C]` of type variable `Self`" The issue was introduced by PR #22105, which moved the catch-all case for NewType assignments that falls back to the concrete base type. This case was moved before the TypeVar handling cases, so when checking `K <: T@C` (where K is a NewType and T@C is a TypeVar with upper bound K): 1. The NewType fallback matched first 2. It delegated to `int` (K's concrete base type) 3. Then checked `int <: T@C`, which checks if `int` satisfies bound `K` 4. But `int` is not assignable to `K` (NewTypes are distinct from their bases) The fix moves the NewType fallback case after the TypeVar cases, so TypeVar handling takes precedence. Now when checking `K <: T@C`, we use the TypeVar case at line 828 which returns `false` for non-inferable typevars - but this is correct because the *other* direction (`T@C <: K`) passes, and for the overall specialization comparison both directions are checked.

Fixes astral-sh/ty#2077.