[ty] Improve support for Callable type context#23888
[ty] Improve support for Callable type context#23888ibraheemdev wants to merge 1 commit intomainfrom
Callable type context#23888Conversation
| return_ty: self | ||
| .return_ty | ||
| .apply_type_mapping_impl(db, type_mapping, tcx, visitor), | ||
| if let TypeMapping::UniqueSpecialization { specialization } = type_mapping { |
Typing conformance resultsNo changes detected ✅Current numbersThe percentage of diagnostics emitted that were expected errors held steady at 85.05%. The percentage of expected errors that received a diagnostic held steady at 78.05%. The number of fully passing files held steady at 63/132. |
|
Memory usage reportSummary
Significant changesClick to expand detailed breakdownflake8
trio
sphinx
prefect
|
|
| Lint rule | Added | Removed | Changed |
|---|---|---|---|
invalid-argument-type |
0 | 1 | 0 |
| Total | 0 | 1 | 0 |
b229936 to
7c2c8ee
Compare
Merging this PR will improve performance by 4.95%
Performance Changes
Comparing Footnotes
|
| /// This is the case for any type which may contain types in non-covariant position within it, | ||
| /// e.g., nominal instances of a generic class, or callables. | ||
| pub(crate) fn may_prefer_declared_type(self, db: &'db dyn Db) -> bool { | ||
| self.class_specialization(db).is_some() || self.is_callable_type() |
There was a problem hiding this comment.
I think we'd better resolve type aliases here? Otherwise a type alias to a callable type as type context won't be recognized. (Let's add a test).
| // Note that unique specializations are typically applied to type context, so we only | ||
| // care about the standard `Callable` form here. |
There was a problem hiding this comment.
A normal Callable annotation can result in a ParametersKind::Gradual (Callable[..., int]) or a ParametersKind::ParamSpec (Callable[P, R] where P is a ParamSpec). So I'm not sure this rationale makes sense as written?
I think ignoring Gradual still makes sense, since it can't contribute any useful type context, but ignoring ParamSpec I think means we won't handle ParamSpec-using wrappers correctly, e.g.
def wrap[**P, T](f: Callable[P, T]) -> Callable[P, T]: ...
y: Callable[[Any], int] = wrap(takes_int) # still reveals `(x: int) -> int`|
|
||
| f(parameter.annotated_type(), variance); | ||
|
|
||
| visitor.visit(self, || { |
There was a problem hiding this comment.
We can't make repeated calls using visitor.visit(self, ...) like this, because CycleDetector caches repeat visits, based on the first-argument key. So only the first visit here will actually run. This causes us to lose later non-covariant occurrences, e.g. def make[T](x: T) -> Callable[[int], list[T]] reveals (int, /) -> list[Literal[1]].
Improves literal promotion and generic call inference that involve
Callabletype context. Resolves astral-sh/ty#3016.