mirror of https://github.com/astral-sh/ruff
Same trick for tuples
This commit is contained in:
parent
be94796e6d
commit
a3f8f60e1e
|
|
@ -2583,6 +2583,23 @@ class C:
|
||||||
reveal_type(C().x) # revealed: Unknown | tuple[Divergent, Literal[1]]
|
reveal_type(C().x) # revealed: Unknown | tuple[Divergent, Literal[1]]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
That also works if the tuple is not constructed directly:
|
||||||
|
|
||||||
|
```py
|
||||||
|
# from typing import TypeVar, Literal
|
||||||
|
#
|
||||||
|
# T = TypeVar("T")
|
||||||
|
#
|
||||||
|
# def make_tuple(a: T) -> tuple[T, Literal[1]]:
|
||||||
|
# return (a, 1)
|
||||||
|
#
|
||||||
|
# class D:
|
||||||
|
# def f(self, other: "D"):
|
||||||
|
# self.x = make_tuple(other.x)
|
||||||
|
#
|
||||||
|
# reveal_type(D().x) # revealed: Unknown | tuple[Divergent, Literal[1]]
|
||||||
|
```
|
||||||
|
|
||||||
## Attributes of standard library modules that aren't yet defined
|
## Attributes of standard library modules that aren't yet defined
|
||||||
|
|
||||||
For attributes of stdlib modules that exist in future versions, we can give better diagnostics.
|
For attributes of stdlib modules that exist in future versions, we can give better diagnostics.
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,7 @@ fn expand_type<'db>(db: &'db dyn Db, ty: Type<'db>) -> Option<Vec<Type<'db>>> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.multi_cartesian_product()
|
.multi_cartesian_product()
|
||||||
.map(|types| Type::tuple(TupleType::heterogeneous(db, types)))
|
.map(|types| Type::heterogeneous_tuple(db, types))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if expanded.len() == 1 {
|
if expanded.len() == 1 {
|
||||||
|
|
|
||||||
|
|
@ -5968,16 +5968,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
let mut annotated_elt_tys = annotated_tuple.as_ref().map(Tuple::all_elements);
|
let mut annotated_elt_tys = annotated_tuple.as_ref().map(Tuple::all_elements);
|
||||||
|
|
||||||
let db = self.db();
|
let db = self.db();
|
||||||
let divergent = Type::divergent(Some(self.scope()));
|
|
||||||
let element_types = elts.iter().map(|element| {
|
let element_types = elts.iter().map(|element| {
|
||||||
let annotated_elt_ty = annotated_elt_tys.as_mut().and_then(Iterator::next).copied();
|
let annotated_elt_ty = annotated_elt_tys.as_mut().and_then(Iterator::next).copied();
|
||||||
let element_type = self.infer_expression(element, TypeContext::new(annotated_elt_ty));
|
self.infer_expression(element, TypeContext::new(annotated_elt_ty))
|
||||||
|
|
||||||
if element_type.has_divergent_type(self.db(), divergent) {
|
|
||||||
divergent
|
|
||||||
} else {
|
|
||||||
element_type
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Type::heterogeneous_tuple(db, element_types)
|
Type::heterogeneous_tuple(db, element_types)
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,7 @@ impl<'db> Type<'db> {
|
||||||
{
|
{
|
||||||
Type::tuple(TupleType::heterogeneous(
|
Type::tuple(TupleType::heterogeneous(
|
||||||
db,
|
db,
|
||||||
elements.into_iter().map(Into::into).map(|ty| {
|
elements.into_iter().map(Into::into),
|
||||||
if specialization_depth(db, ty) > MAX_SPECIALIZATION_DEPTH {
|
|
||||||
Type::divergent(None)
|
|
||||||
} else {
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,11 @@ use crate::subscript::{Nth, OutOfBoundsError, PyIndex, PySlice, StepSizeZeroErro
|
||||||
use crate::types::class::{ClassType, KnownClass};
|
use crate::types::class::{ClassType, KnownClass};
|
||||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||||
use crate::types::generics::InferableTypeVars;
|
use crate::types::generics::InferableTypeVars;
|
||||||
|
use crate::types::visitor::MAX_SPECIALIZATION_DEPTH;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
|
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
|
||||||
IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, Type, TypeMapping, TypeRelation,
|
IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, Type, TypeMapping, TypeRelation,
|
||||||
UnionBuilder, UnionType,
|
UnionBuilder, UnionType, specialization_depth,
|
||||||
};
|
};
|
||||||
use crate::types::{Truthiness, TypeContext};
|
use crate::types::{Truthiness, TypeContext};
|
||||||
use crate::{Db, FxOrderSet, Program};
|
use crate::{Db, FxOrderSet, Program};
|
||||||
|
|
@ -178,7 +179,16 @@ impl<'db> TupleType<'db> {
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
types: impl IntoIterator<Item = Type<'db>>,
|
types: impl IntoIterator<Item = Type<'db>>,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
TupleType::new(db, &TupleSpec::heterogeneous(types))
|
TupleType::new(
|
||||||
|
db,
|
||||||
|
&TupleSpec::heterogeneous(types.into_iter().map(|ty| {
|
||||||
|
if specialization_depth(db, ty) > MAX_SPECIALIZATION_DEPTH {
|
||||||
|
Type::divergent(None)
|
||||||
|
} else {
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue