avoid promoting invariant generics during literal promotion

This commit is contained in:
Ibraheem Ahmed 2025-10-17 16:12:52 -04:00
parent 8ca2b5555d
commit e73d73b0f7
2 changed files with 25 additions and 1 deletions

View File

@ -38,6 +38,21 @@ reveal_type(x[0].__name__) # revealed: Unknown | str
reveal_type([1, (1, 2), (1, 2, 3)])
```
## Invariant generic elements
We take care not to promote invariant generics:
```py
from typing import Literal
def _(a: list[Literal[1]], b: Literal[2]):
c = [a]
reveal_type(c) # revealed: list[Unknown | list[Literal[1]]]
d = [(a, b)]
reveal_type(d) # revealed: list[Unknown | tuple[list[Literal[1]], int]]
```
## List comprehensions
```py

View File

@ -6648,7 +6648,7 @@ impl<'db> Type<'db> {
tcx: TypeContext<'db>,
visitor: &ApplyTypeMappingVisitor<'db>,
) -> Type<'db> {
match self {
let ty = match self {
Type::TypeVar(bound_typevar) => match type_mapping {
TypeMapping::Specialization(specialization) => {
specialization.get(db, bound_typevar).unwrap_or(self)
@ -6837,6 +6837,15 @@ impl<'db> Type<'db> {
| Type::BoundSuper(_)
| Type::SpecialForm(_)
| Type::KnownInstance(_) => self,
};
match type_mapping {
TypeMapping::PromoteLiterals => {
// It is only sound to promote to a supertype (i.e. it is unsound to promote
// invariant generics).
if self.is_subtype_of(db, ty) { ty } else { self }
}
_ => ty,
}
}