Conversation
Diagnostic diff on typing conformance testsChanges were detected when running ty on typing conformance tests--- old-output.txt 2025-08-12 00:50:16.219875316 +0000
+++ new-output.txt 2025-08-12 00:50:16.282875419 +0000
@@ -1,4 +1,5 @@
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
+fatal[panic] Panicked at /home/runner/.cargo/git/checkouts/salsa-e6f3bb7c2a062968/940f9c0/src/function/execute.rs:204:25 when checking `/home/runner/work/ruff/ruff/typing/conformance/tests/aliases_typealiastype.py`: `infer_definition_types(Id(dc1d)): execute: too many cycle iterations`
_directives_deprecated_library.py:15:31: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `int`
_directives_deprecated_library.py:30:26: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `str`
_directives_deprecated_library.py:36:41: error[invalid-return-type] Function always implicitly returns `None`, which is not assignable to return type `Self@__add__`
@@ -67,23 +68,6 @@
aliases_type_statement.py:48:23: error[invalid-type-form] Boolean operations are not allowed in type expressions
aliases_type_statement.py:49:23: error[fstring-type-annotation] Type expressions cannot use f-strings
aliases_type_statement.py:80:37: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
-aliases_typealiastype.py:32:7: error[unresolved-attribute] Type `typing.TypeAliasType` has no attribute `other_attrib`
-aliases_typealiastype.py:39:26: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
-aliases_typealiastype.py:52:40: error[invalid-type-form] Function calls are not allowed in type expressions
-aliases_typealiastype.py:53:40: error[invalid-type-form] List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
-aliases_typealiastype.py:54:42: error[invalid-type-form] Tuple literals are not allowed in this context in a type expression
-aliases_typealiastype.py:54:43: error[invalid-type-form] Tuple literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?
-aliases_typealiastype.py:55:42: error[invalid-type-form] List comprehensions are not allowed in type expressions
-aliases_typealiastype.py:56:42: error[invalid-type-form] Dict literals are not allowed in type expressions
-aliases_typealiastype.py:57:42: error[invalid-type-form] Function calls are not allowed in type expressions
-aliases_typealiastype.py:58:48: error[invalid-type-form] Int literals are not allowed in this context in a type expression
-aliases_typealiastype.py:59:42: error[invalid-type-form] `if` expressions are not allowed in type expressions
-aliases_typealiastype.py:60:42: error[invalid-type-form] Variable of type `Literal[3]` is not allowed in a type expression
-aliases_typealiastype.py:61:42: error[invalid-type-form] Boolean literals are not allowed in this context in a type expression
-aliases_typealiastype.py:62:42: error[invalid-type-form] Int literals are not allowed in this context in a type expression
-aliases_typealiastype.py:63:42: error[invalid-type-form] Boolean operations are not allowed in type expressions
-aliases_typealiastype.py:64:42: error[invalid-type-form] F-strings are not allowed in type expressions
-aliases_typealiastype.py:66:47: error[unresolved-reference] Name `BadAlias21` used when not defined
aliases_variance.py:18:24: error[non-subscriptable] Cannot subscript object of type `<class 'ClassA[typing.TypeVar("T_co")]'>` with no `__class_getitem__` method
aliases_variance.py:28:16: error[non-subscriptable] Cannot subscript object of type `<class 'ClassA[typing.TypeVar("T_co")]'>` with no `__class_getitem__` method
aliases_variance.py:44:16: error[non-subscriptable] Cannot subscript object of type `<class 'ClassB[typing.TypeVar("T_co"), typing.TypeVar("T_contra")]'>` with no `__class_getitem__` method
@@ -884,4 +868,5 @@
typeddicts_operations.py:60:1: error[type-assertion-failure] Argument does not have asserted type `str | None`
typeddicts_type_consistency.py:101:1: error[invalid-assignment] Object of type `Unknown | None` is not assignable to `str`
typeddicts_usage.py:40:24: error[invalid-type-form] The special form `typing.TypedDict` is not allowed in type expressions. Did you mean to use a concrete TypedDict or `collections.abc.Mapping[str, object]` instead?
-Found 885 diagnostics
+Found 869 diagnostics
+WARN A fatal error occurred while checking some files. Not all project files were analyzed. See the diagnostics list above for details. |
|
|
Converting back to draft while I look into the new panic on the conformance suite. |
|
Ok, the new panic in the conformance suite is for an invalid type alias, so it shouldn't be a case that affects much if any real code (as seen in the fact that there aren't new ecosystem panics). I have a plan for how to fix it (as well as fixing recursive legacy/bare type aliases), but it will be significant enough that I'd rather do it in a separate PR. So putting this back up for review as-is. |
|
Exciting! I assume this change is because we no longer normalize the argument union: I must say, I very much prefer the new output (but agree, that changing this in general is out of scope for this PR) |
| self.is_equivalent_to_impl(db, other, &mut visitor) | ||
| } | ||
|
|
||
| pub(crate) fn is_equivalent_to_impl( |
There was a problem hiding this comment.
Do the other recursive calls to is_equivalent_to in this method need to be updated to use is_equivalent_to_impl instead?
There was a problem hiding this comment.
Yes, at some point. There are also some places in has_relation_to_impl that need this update. I'd been debating whether to fully thread through the visitors everywhere in this PR, or do it as a follow-up PR, with added regression tests.
fff262d to
ab07975
Compare
CodSpeed WallTime Performance ReportMerging #19805 will not alter performanceComparing Summary
|
No, this change is because we no longer eagerly unpack type aliases. |
This reverts commit a7f5427.
| // `static-frame` as part of a mypy_primer run! This is because it's called | ||
| // from `NominalInstanceType::class()`, which is a very hot method. | ||
| #[salsa::tracked(heap_size=ruff_memory_usage::heap_size)] | ||
| #[salsa::tracked(cycle_fn=to_class_type_cycle_recover, cycle_initial=to_class_type_cycle_initial, heap_size=ruff_memory_usage::heap_size)] |
There was a problem hiding this comment.
the fact that static-frame is the most significant benchmark regression makes me suspect that this has something to do with the performance regressions. We know that this method is extremely hot when checking static-frame for some reason (#19811 (comment), #19811 (comment)), so if there's now a chance that we'll sometimes have to recover from cycles when calling this function, that seems likely to slow down static-frame quite a bit. This also means that the static-frame repo isn't necessarily representative of most real-world code, however; it seems like a pretty extreme case.
There was a problem hiding this comment.
Yeah, this was one thing I've looked into a bit. I've confirmed (via Salsa tracing) that in checking static frame, we don't ever actually hit a cycle on this query (which is not surprising; if we did, then we likely would have panicked on static-frame before this PR). It's possible that there is still some effect simply from having the cycle handlers in place (Salsa does go into a different path for executing such queries), though I don't recall seeing a visible effect from that when we've added cycle handling to queries in the past. Even if it's very hot, presumably most of those accesses are cached; in that case, cycle handling shouldn't cause any overhead at all.
If this is the cause, then I think we just have to eat it, pending generalized improvements to the efficiency of Salsa cycle handling.
|
Perf regression seems reduced to the 1-3% range. Possible causes are either overhead from adding cycle handling to a hot query, or overhead from passing around CycleDetector visitors through many more hot methods ( PR has changed somewhat, but mostly by removing |
|
Let's go! |
* main: Don't cache files with diagnostics (#19869) [ty] support recursive type aliases (#19805) [ty] Remove unsafe `salsa::Update` implementations in `tuple.rs` (#19880) [ty] Function argument inlay hints (#19269) [ty] Remove Salsa interning for `TypedDictType` (#19879) Fix `lint.future-annotations` link (#19876) [ty] Reduce memory usage of `TupleSpec` and `TupleType` (#19872) [ty] Track heap usage of salsa structs (#19790) Update salsa to pull in tracked struct changes (#19843) [ty] simplify CycleDetector::visit signature (#19873) [ty] use interior mutability in type visitors (#19871) [ty] Fix tool name is None when no ty path is given in ty_benchmark (#19870) [ty] Remove `Type::Tuple` (#19669) [ty] Short circuit `ReachabilityConstraints::analyze_single` for dynamic types (#19867)
…aints * dcreager/inferrable: (65 commits) this was right after all mark typevars inferrable as we go fix tests fix inference of constrained typevars [ty] Add precise inference for indexing, slicing and unpacking `NamedTuple` instances (#19560) Add rule code to GitLab description (#19896) [ty] render docstrings in hover (#19882) [ty] simplify return type of place_from_declarations (#19884) [ty] Various minor cleanups to tuple internals (#19891) [ty] Improve `sys.version_info` special casing (#19894) Don't cache files with diagnostics (#19869) [ty] support recursive type aliases (#19805) [ty] Remove unsafe `salsa::Update` implementations in `tuple.rs` (#19880) [ty] Function argument inlay hints (#19269) [ty] Remove Salsa interning for `TypedDictType` (#19879) Fix `lint.future-annotations` link (#19876) [ty] Reduce memory usage of `TupleSpec` and `TupleType` (#19872) [ty] Track heap usage of salsa structs (#19790) Update salsa to pull in tracked struct changes (#19843) [ty] simplify CycleDetector::visit signature (#19873) ...
Summary
Support recursive type aliases by adding a
Type::TypeAliastype variant, which allows referring to a type alias directly as a type without eagerly unpacking it to its value.We still unpack type aliases when they are added to intersections and unions, so that we can simplify the intersection/union appropriately based on the unpacked value of the type alias.
This introduces new possible recursive types, and so also requires expanding our usage of recursion-detecting visitors in Type methods. The use of these visitors is still not fully comprehensive in this PR, and will require further expansion to support recursion in more kinds of types (I already have further work on this locally), but I think it may be better to do this incrementally in multiple PRs.
Test Plan
Added some recursive type-alias tests and made them pass.