Skip to content

Commit 4fcdc5a

Browse files
committed
avoid infinite recursion on type aliases & add tests
1 parent 897bd3e commit 4fcdc5a

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

crates/ty_python_semantic/src/types.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6792,7 +6792,19 @@ impl<'db> Type<'db> {
67926792
Type::TypeIs(type_is) => type_is.with_type(db, type_is.return_type(db).apply_type_mapping(db, type_mapping, tcx)),
67936793

67946794
Type::TypeAlias(alias) => {
6795-
visitor.visit(self, || alias.value_type(db).apply_type_mapping_impl(db, type_mapping, tcx, visitor))
6795+
// Do not call `value_type` here. `value_type` does the specialization internally, so `apply_type_mapping` is performed without `visitor` inheritance.
6796+
// In the case of recursive type aliases, this leads to infinite recursion.
6797+
// Instead, call `raw_value_type` and perform the specialization after the `visitor` cache has been created.
6798+
let value_type = visitor.visit(self, || alias.raw_value_type(db).apply_type_mapping_impl(db, type_mapping, tcx, visitor));
6799+
if let Some(generic_context) = alias.generic_context(db) {
6800+
let specialization = alias
6801+
.specialization(db)
6802+
.unwrap_or_else(|| generic_context.default_specialization(db, None));
6803+
6804+
value_type.apply_specialization(db, specialization)
6805+
} else {
6806+
value_type
6807+
}
67966808
}
67976809

67986810
Type::ModuleLiteral(_)
@@ -11836,6 +11848,9 @@ type CovariantAlias[T] = Covariant[T]
1183611848
type ContravariantAlias[T] = Contravariant[T]
1183711849
type InvariantAlias[T] = Invariant[T]
1183811850
type BivariantAlias[T] = Bivariant[T]
11851+
11852+
type RecursiveAlias[T] = None | list[RecursiveAlias[T]]
11853+
type RecursiveAlias2[T] = None | list[T] | list[RecursiveAlias2[T]]
1183911854
"#,
1184011855
)
1184111856
.unwrap();
@@ -11866,5 +11881,19 @@ type BivariantAlias[T] = Bivariant[T]
1186611881
.variance_of(&db, get_bound_typevar(&db, bivariant)),
1186711882
TypeVarVariance::Bivariant
1186811883
);
11884+
11885+
let recursive = get_type_alias(&db, "RecursiveAlias");
11886+
assert_eq!(
11887+
KnownInstanceType::TypeAliasType(TypeAliasType::PEP695(recursive))
11888+
.variance_of(&db, get_bound_typevar(&db, recursive)),
11889+
TypeVarVariance::Bivariant
11890+
);
11891+
11892+
let recursive2 = get_type_alias(&db, "RecursiveAlias2");
11893+
assert_eq!(
11894+
KnownInstanceType::TypeAliasType(TypeAliasType::PEP695(recursive2))
11895+
.variance_of(&db, get_bound_typevar(&db, recursive2)),
11896+
TypeVarVariance::Invariant
11897+
);
1186911898
}
1187011899
}

0 commit comments

Comments
 (0)