Skip to content

Commit c924644

Browse files
committed
move never checking down to TupleType
1 parent 236dc3b commit c924644

File tree

5 files changed

+45
-27
lines changed

5 files changed

+45
-27
lines changed

crates/ty_python_semantic/src/types.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,7 @@ impl<'db> Type<'db> {
721721
.map(|ty| ty.materialize(db, variance.flip())),
722722
)
723723
.build(),
724-
Type::Tuple(tuple_type) => {
725-
Type::tuple(db, tuple_type.tuple(db).materialize(db, variance))
726-
}
724+
Type::Tuple(tuple_type) => Type::tuple(db, tuple_type.materialize(db, variance)),
727725
Type::TypeVar(type_var) => Type::TypeVar(type_var.materialize(db, variance)),
728726
Type::TypeIs(type_is) => {
729727
type_is.with_type(db, type_is.return_type(db).materialize(db, variance))
@@ -1131,7 +1129,7 @@ impl<'db> Type<'db> {
11311129
match self {
11321130
Type::Union(union) => Type::Union(union.normalized(db)),
11331131
Type::Intersection(intersection) => Type::Intersection(intersection.normalized(db)),
1134-
Type::Tuple(tuple_type) => Type::tuple(db, tuple_type.tuple(db).normalized(db)),
1132+
Type::Tuple(tuple) => Type::tuple(db, tuple.normalized(db)),
11351133
Type::Callable(callable) => Type::Callable(callable.normalized(db)),
11361134
Type::ProtocolInstance(protocol) => protocol.normalized(db),
11371135
Type::NominalInstance(instance) => Type::NominalInstance(instance.normalized(db)),
@@ -5314,7 +5312,7 @@ impl<'db> Type<'db> {
53145312
}
53155313
builder.build()
53165314
}
5317-
Type::Tuple(tuple_type) => Type::tuple(db, tuple_type.tuple(db).apply_type_mapping(db, type_mapping)),
5315+
Type::Tuple(tuple) => Type::tuple(db, tuple.apply_type_mapping(db, type_mapping)),
53185316

53195317
Type::TypeIs(type_is) => type_is.with_type(db, type_is.return_type(db).apply_type_mapping(db, type_mapping)),
53205318

crates/ty_python_semantic/src/types/generics.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,13 @@ impl<'db> Specialization<'db> {
283283
return tuple;
284284
}
285285
if let [element_type] = self.types(db) {
286-
return TupleType::new(db, TupleSpec::homogeneous(*element_type)).tuple(db);
286+
if let Some(tuple) = TupleType::new(db, TupleSpec::homogeneous(*element_type)) {
287+
return tuple.tuple(db);
288+
}
287289
}
288-
TupleType::new(db, TupleSpec::homogeneous(Type::unknown())).tuple(db)
290+
TupleType::new(db, TupleSpec::homogeneous(Type::unknown()))
291+
.expect("tuple[Unknown, ...] should never contain Never")
292+
.tuple(db)
289293
}
290294

291295
/// Returns the type that a typevar is mapped to, or None if the typevar isn't part of this
@@ -327,7 +331,7 @@ impl<'db> Specialization<'db> {
327331
.collect();
328332
let tuple_inner = self
329333
.tuple_inner(db)
330-
.map(|tuple| tuple.apply_type_mapping(db, type_mapping));
334+
.and_then(|tuple| tuple.apply_type_mapping(db, type_mapping));
331335
Specialization::new(db, self.generic_context(db), types, tuple_inner)
332336
}
333337

@@ -371,7 +375,7 @@ impl<'db> Specialization<'db> {
371375

372376
pub(crate) fn normalized(self, db: &'db dyn Db) -> Self {
373377
let types: Box<[_]> = self.types(db).iter().map(|ty| ty.normalized(db)).collect();
374-
let tuple_inner = self.tuple_inner(db).map(|tuple| tuple.normalized(db));
378+
let tuple_inner = self.tuple_inner(db).and_then(|tuple| tuple.normalized(db));
375379
Self::new(db, self.generic_context(db), types, tuple_inner)
376380
}
377381

@@ -391,7 +395,7 @@ impl<'db> Specialization<'db> {
391395
vartype.materialize(db, variance)
392396
})
393397
.collect();
394-
let tuple_inner = self.tuple_inner(db).map(|tuple| {
398+
let tuple_inner = self.tuple_inner(db).and_then(|tuple| {
395399
// Tuples are immutable, so tuple element types are always in covariant position.
396400
tuple.materialize(db, variance)
397401
});

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6452,7 +6452,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
64526452

64536453
(Type::Tuple(lhs), Type::Tuple(rhs), ast::Operator::Add) => Some(Type::tuple(
64546454
self.db(),
6455-
lhs.tuple(self.db()).concat(self.db(), rhs.tuple(self.db())),
6455+
TupleType::new(
6456+
self.db(),
6457+
lhs.tuple(self.db()).concat(self.db(), rhs.tuple(self.db())),
6458+
),
64566459
)),
64576460

64586461
// We've handled all of the special cases that we support for literals, so we need to
@@ -8818,7 +8821,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
88188821
let ty = if return_todo {
88198822
todo_type!("PEP 646")
88208823
} else {
8821-
Type::tuple(self.db(), element_types)
8824+
Type::tuple(self.db(), TupleType::new(self.db(), element_types))
88228825
};
88238826

88248827
// Here, we store the type for the inner `int, str` tuple-expression,

crates/ty_python_semantic/src/types/instance.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl<'db> Type<'db> {
1919
TupleType::homogeneous(db, Type::unknown())
2020
}
2121
(ClassType::Generic(alias), Some(KnownClass::Tuple)) => {
22-
Self::tuple(db, alias.specialization(db).tuple(db))
22+
Self::tuple(db, TupleType::new(db, alias.specialization(db).tuple(db)))
2323
}
2424
_ if class.class_literal(db).0.is_protocol(db) => {
2525
Self::ProtocolInstance(ProtocolInstanceType::from_class(class))

crates/ty_python_semantic/src/types/tuple.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,24 @@ impl TupleLength {
7171
/// # Ordering
7272
/// Ordering is based on the tuple's salsa-assigned id and not on its elements.
7373
/// The id may change between runs, or when the tuple was garbage collected and recreated.
74-
#[salsa::interned(debug)]
74+
#[salsa::interned(debug, constructor=new_internal)]
7575
#[derive(PartialOrd, Ord)]
7676
pub struct TupleType<'db> {
7777
#[returns(ref)]
7878
pub(crate) tuple: TupleSpec<'db>,
7979
}
8080

8181
impl<'db> Type<'db> {
82-
pub(crate) fn tuple<T>(db: &'db dyn Db, tuple_key: T) -> Self
82+
pub(crate) fn tuple(_db: &'db dyn Db, tuple: Option<TupleType<'db>>) -> Self {
83+
let Some(tuple) = tuple else {
84+
return Type::Never;
85+
};
86+
Self::Tuple(tuple)
87+
}
88+
}
89+
90+
impl<'db> TupleType<'db> {
91+
pub(crate) fn new<T>(db: &'db dyn Db, tuple_key: T) -> Option<Self>
8392
where
8493
T: Borrow<TupleSpec<'db>> + Hash + salsa::plumbing::interned::Lookup<TupleSpec<'db>>,
8594
TupleSpec<'db>: salsa::plumbing::interned::HashEqLike<T>,
@@ -88,7 +97,7 @@ impl<'db> Type<'db> {
8897
// possible to instantiate the tuple as a whole.
8998
let tuple = tuple_key.borrow();
9099
if tuple.fixed_elements().any(Type::is_never) {
91-
return Type::Never;
100+
return None;
92101
}
93102

94103
// If the variable-length portion is Never, it can only be instantiated with zero elements.
@@ -98,24 +107,25 @@ impl<'db> Type<'db> {
98107
let tuple = TupleSpec::Fixed(FixedLengthTuple::from_elements(
99108
tuple.prefix.iter().chain(&tuple.suffix).copied(),
100109
));
101-
return Self::Tuple(TupleType::new::<_, TupleSpec<'db>>(db, tuple));
110+
return Some(TupleType::new_internal::<_, TupleSpec<'db>>(db, tuple));
102111
}
103112
}
104113

105-
Self::Tuple(TupleType::new(db, tuple_key))
114+
Some(TupleType::new_internal(db, tuple_key))
106115
}
107-
}
108116

109-
impl<'db> TupleType<'db> {
110117
pub(crate) fn empty(db: &'db dyn Db) -> Type<'db> {
111-
Type::tuple(db, TupleSpec::from(FixedLengthTuple::empty()))
118+
Type::tuple(
119+
db,
120+
TupleType::new(db, TupleSpec::from(FixedLengthTuple::empty())),
121+
)
112122
}
113123

114124
pub(crate) fn from_elements(
115125
db: &'db dyn Db,
116126
types: impl IntoIterator<Item = Type<'db>>,
117127
) -> Type<'db> {
118-
Type::tuple(db, TupleSpec::from_elements(types))
128+
Type::tuple(db, TupleType::new(db, TupleSpec::from_elements(types)))
119129
}
120130

121131
#[cfg(test)]
@@ -125,11 +135,14 @@ impl<'db> TupleType<'db> {
125135
variable: Type<'db>,
126136
suffix: impl IntoIterator<Item = Type<'db>>,
127137
) -> Type<'db> {
128-
Type::tuple(db, VariableLengthTuple::mixed(prefix, variable, suffix))
138+
Type::tuple(
139+
db,
140+
TupleType::new(db, VariableLengthTuple::mixed(prefix, variable, suffix)),
141+
)
129142
}
130143

131144
pub(crate) fn homogeneous(db: &'db dyn Db, element: Type<'db>) -> Type<'db> {
132-
Type::tuple(db, TupleSpec::homogeneous(element))
145+
Type::tuple(db, TupleType::new(db, TupleSpec::homogeneous(element)))
133146
}
134147

135148
pub(crate) fn to_class_type(self, db: &'db dyn Db) -> Option<ClassType<'db>> {
@@ -149,19 +162,19 @@ impl<'db> TupleType<'db> {
149162
///
150163
/// See [`Type::normalized`] for more details.
151164
#[must_use]
152-
pub(crate) fn normalized(self, db: &'db dyn Db) -> Self {
165+
pub(crate) fn normalized(self, db: &'db dyn Db) -> Option<Self> {
153166
TupleType::new(db, self.tuple(db).normalized(db))
154167
}
155168

156-
pub(crate) fn materialize(self, db: &'db dyn Db, variance: TypeVarVariance) -> Self {
169+
pub(crate) fn materialize(self, db: &'db dyn Db, variance: TypeVarVariance) -> Option<Self> {
157170
TupleType::new(db, self.tuple(db).materialize(db, variance))
158171
}
159172

160173
pub(crate) fn apply_type_mapping<'a>(
161174
self,
162175
db: &'db dyn Db,
163176
type_mapping: &TypeMapping<'a, 'db>,
164-
) -> Self {
177+
) -> Option<Self> {
165178
TupleType::new(db, self.tuple(db).apply_type_mapping(db, type_mapping))
166179
}
167180

0 commit comments

Comments
 (0)