diff --git a/crates/ty_python_semantic/resources/mdtest/async.md b/crates/ty_python_semantic/resources/mdtest/async.md index 0d57f4d8f8..1c01d9dcf2 100644 --- a/crates/ty_python_semantic/resources/mdtest/async.md +++ b/crates/ty_python_semantic/resources/mdtest/async.md @@ -43,9 +43,7 @@ async def main(): loop = asyncio.get_event_loop() with concurrent.futures.ThreadPoolExecutor() as pool: result = await loop.run_in_executor(pool, blocking_function) - - # TODO: should be `int` - reveal_type(result) # revealed: Unknown + reveal_type(result) # revealed: int ``` ### `asyncio.Task` diff --git a/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md b/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md index 28a69081e5..2912adb049 100644 --- a/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md +++ b/crates/ty_python_semantic/resources/mdtest/dataclasses/fields.md @@ -82,8 +82,7 @@ def get_default() -> str: reveal_type(field(default=1)) # revealed: dataclasses.Field[Literal[1]] reveal_type(field(default=None)) # revealed: dataclasses.Field[None] -# TODO: this could ideally be `dataclasses.Field[str]` with a better generics solver -reveal_type(field(default_factory=get_default)) # revealed: dataclasses.Field[Unknown] +reveal_type(field(default_factory=get_default)) # revealed: dataclasses.Field[str] ``` ## dataclass_transform field_specifiers diff --git a/crates/ty_python_semantic/resources/mdtest/decorators.md b/crates/ty_python_semantic/resources/mdtest/decorators.md index f92eca8003..075a80ecf2 100644 --- a/crates/ty_python_semantic/resources/mdtest/decorators.md +++ b/crates/ty_python_semantic/resources/mdtest/decorators.md @@ -144,11 +144,8 @@ from functools import cache def f(x: int) -> int: return x**2 -# TODO: Should be `_lru_cache_wrapper[int]` -reveal_type(f) # revealed: _lru_cache_wrapper[Unknown] - -# TODO: Should be `int` -reveal_type(f(1)) # revealed: Unknown +reveal_type(f) # revealed: _lru_cache_wrapper[int] +reveal_type(f(1)) # revealed: int ``` ## Lambdas as decorators diff --git a/crates/ty_python_semantic/src/types/generics.rs b/crates/ty_python_semantic/src/types/generics.rs index df15fdafc0..480c1a7741 100644 --- a/crates/ty_python_semantic/src/types/generics.rs +++ b/crates/ty_python_semantic/src/types/generics.rs @@ -17,11 +17,12 @@ use crate::types::signatures::{Parameter, Parameters, Signature}; use crate::types::tuple::{TupleSpec, TupleType, walk_tuple_type}; use crate::types::visitor::{TypeCollector, TypeVisitor, walk_type_with_recursion_guard}; use crate::types::{ - ApplyTypeMappingVisitor, BoundTypeVarIdentity, BoundTypeVarInstance, ClassLiteral, - FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor, - KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, Type, TypeContext, - TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarIdentity, TypeVarInstance, - TypeVarKind, TypeVarVariance, UnionType, declaration_type, walk_bound_type_var_type, + ApplyTypeMappingVisitor, BoundTypeVarIdentity, BoundTypeVarInstance, CallableTypes, + ClassLiteral, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, + IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor, + Type, TypeContext, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarIdentity, + TypeVarInstance, TypeVarKind, TypeVarVariance, UnionType, declaration_type, + walk_bound_type_var_type, }; use crate::{Db, FxOrderMap, FxOrderSet}; @@ -1667,6 +1668,28 @@ impl<'db> SpecializationBuilder<'db> { } } + (Type::Callable(formal_callable), _) => { + if let Some(actual_callable) = actual + .try_upcast_to_callable(self.db) + .and_then(CallableTypes::exactly_one) + { + for formal_signature in &formal_callable.signatures(self.db).overloads { + for actual_signature in &actual_callable.signatures(self.db).overloads { + if let Some(formal_return_ty) = formal_signature.return_ty + && let Some(actual_return_ty) = actual_signature.return_ty + { + self.infer_map_impl( + formal_return_ty, + actual_return_ty, + polarity, + &mut f, + )?; + } + } + } + } + } + // TODO: Add more forms that we can structurally induct into: type[C], callables _ => {} }