diff --git a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md index 6a3a9ad37d..aec5dad0fd 100644 --- a/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/implicit_type_aliases.md @@ -392,8 +392,8 @@ TransparentAlias = T MyOptional = T | None # TODO: Consider displaying this as ``, … instead? (and similar for some others below) -reveal_type(MyList) # revealed: -reveal_type(MyDict) # revealed: +reveal_type(MyList) # revealed: +reveal_type(MyDict) # revealed: reveal_type(MyType) # revealed: GenericAlias reveal_type(IntAndType) # revealed: reveal_type(Pair) # revealed: @@ -445,7 +445,7 @@ U = TypeVar("U") DictStrTo = MyDict[str, U] -reveal_type(DictStrTo) # revealed: +reveal_type(DictStrTo) # revealed: def _( dict_str_to_int: DictStrTo[int], @@ -480,7 +480,7 @@ A generic implicit type alias can also be used in another generic implicit type ```py MyOtherList = MyList[T] -reveal_type(MyOtherList) # revealed: +reveal_type(MyOtherList) # revealed: def _( list_of_ints: MyOtherList[int], @@ -498,9 +498,9 @@ def _( my_callable: MyCallable, ): # TODO: Should be `list[Unknown]` - reveal_type(my_list) # revealed: list[typing.TypeVar] + reveal_type(my_list) # revealed: list[T] # TODO: Should be `dict[Unknown, Unknown]` - reveal_type(my_dict) # revealed: dict[typing.TypeVar, typing.TypeVar] + reveal_type(my_dict) # revealed: dict[T, U] # TODO: Should be `(...) -> Unknown` reveal_type(my_callable) # revealed: (...) -> typing.TypeVar ``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 0edf2e9725..5ef05ec75c 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -7250,6 +7250,8 @@ impl<'db> Type<'db> { instance.apply_type_mapping_impl(db, type_mapping, tcx, visitor) }, + Type::NewTypeInstance(_) if matches!(type_mapping, TypeMapping::BindLegacyTypevars(_)) => self, + Type::NewTypeInstance(newtype) => visitor.visit(self, || { Type::NewTypeInstance(newtype.map_base_class_type(db, |class_type| { class_type.apply_type_mapping_impl(db, type_mapping, tcx, visitor) @@ -7328,6 +7330,8 @@ impl<'db> Type<'db> { // TODO(jelle): Materialize should be handled differently, since TypeIs is invariant Type::TypeIs(type_is) => type_is.with_type(db, type_is.return_type(db).apply_type_mapping(db, type_mapping, tcx)), + Type::TypeAlias(_) if matches!(type_mapping, TypeMapping::BindLegacyTypevars(_)) => self, + Type::TypeAlias(alias) => { // Do not call `value_type` here. `value_type` does the specialization internally, so `apply_type_mapping` is performed without `visitor` inheritance. // In the case of recursive type aliases, this leads to infinite recursion. diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index e3f6da22f6..27ca88ce25 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -101,14 +101,14 @@ use crate::types::typed_dict::{ }; use crate::types::visitor::any_over_type; use crate::types::{ - CallDunderError, CallableBinding, CallableType, ClassLiteral, ClassType, DataclassParams, - DynamicType, InternedType, IntersectionBuilder, IntersectionType, KnownClass, + BindingContext, CallDunderError, CallableBinding, CallableType, ClassLiteral, ClassType, + DataclassParams, DynamicType, InternedType, IntersectionBuilder, IntersectionType, KnownClass, KnownInstanceType, LintDiagnosticGuard, MemberLookupPolicy, MetaclassCandidate, PEP695TypeAliasType, Parameter, ParameterForm, Parameters, SpecialFormType, SubclassOfType, TrackedConstraintSet, Truthiness, Type, TypeAliasType, TypeAndQualifiers, TypeContext, - TypeQualifiers, TypeVarBoundOrConstraintsEvaluation, TypeVarDefaultEvaluation, TypeVarIdentity, - TypeVarInstance, TypeVarKind, TypeVarVariance, TypedDictType, UnionBuilder, UnionType, - UnionTypeInstance, binding_type, todo_type, + TypeMapping, TypeQualifiers, TypeVarBoundOrConstraintsEvaluation, TypeVarDefaultEvaluation, + TypeVarIdentity, TypeVarInstance, TypeVarKind, TypeVarVariance, TypedDictType, UnionBuilder, + UnionType, UnionTypeInstance, binding_type, todo_type, }; use crate::types::{ClassBase, add_inferred_python_version_hint_to_diagnostic}; use crate::unpack::{EvaluationMode, UnpackPosition}; @@ -11051,6 +11051,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { value_ty, generic_context, specialize, + true, ) } @@ -11075,6 +11076,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { value_ty, generic_context, specialize, + false, ) } @@ -11084,12 +11086,30 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { value_ty: Type<'db>, generic_context: GenericContext<'db>, specialize: impl FnOnce(&[Option>]) -> Type<'db>, + bind_legacy_typevars: bool, ) -> Type<'db> { let slice_node = subscript.slice.as_ref(); + + let db = self.db(); + let do_bind_legacy_typevars = |ty: Type<'db>| { + if bind_legacy_typevars { + ty.apply_type_mapping( + db, + &TypeMapping::BindLegacyTypevars(BindingContext::Synthetic), + TypeContext::default(), + ) + } else { + ty + } + }; + let call_argument_types = match slice_node { ast::Expr::Tuple(tuple) => { let arguments = CallArguments::positional( - tuple.elts.iter().map(|elt| self.infer_type_expression(elt)), + tuple + .elts + .iter() + .map(|elt| do_bind_legacy_typevars(self.infer_type_expression(elt))), ); self.store_expression_type( slice_node, @@ -11097,8 +11117,11 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { ); arguments } - _ => CallArguments::positional([self.infer_type_expression(slice_node)]), + _ => CallArguments::positional([do_bind_legacy_typevars( + self.infer_type_expression(slice_node), + )]), }; + let binding = Binding::single(value_ty, generic_context.signature(self.db())); let bindings = match Bindings::from(binding) .match_parameters(self.db(), &call_argument_types) diff --git a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs index dc12239682..39bed35e50 100644 --- a/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs +++ b/crates/ty_python_semantic/src/types/infer/builder/type_expression.rs @@ -755,6 +755,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> { value_ty, generic_context, specialize, + true, ) }