Skip to content

Commit 91d91ca

Browse files
authored
Merge 135b27a into 146340c
2 parents 146340c + 135b27a commit 91d91ca

12 files changed

Lines changed: 843 additions & 660 deletions

File tree

crates/ty_python_semantic/resources/mdtest/assignment/annotations.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,8 +615,7 @@ e: list[Any] | None = [1]
615615
reveal_type(e) # revealed: list[Any]
616616

617617
f: list[Any] | None = f2(1)
618-
# TODO: Better constraint solver.
619-
reveal_type(f) # revealed: list[int] | None
618+
reveal_type(f) # revealed: list[Any] | None
620619

621620
g: list[Any] | dict[Any, Any] = f3(1)
622621
# TODO: Better constraint solver.

crates/ty_python_semantic/resources/mdtest/promotion.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ x11: list[Literal[1] | Literal[2] | Literal[3]] = [1, 2, 3]
238238
reveal_type(x11) # revealed: list[Literal[1, 2, 3]]
239239

240240
x12: Y[Y[Literal[1]]] = [[1]]
241-
reveal_type(x12) # revealed: list[Y[Literal[1]]]
241+
reveal_type(x12) # revealed: list[list[Literal[1]]]
242242

243243
x13: list[tuple[Literal[1], Literal[2], Literal[3]]] = [(1, 2, 3)]
244244
reveal_type(x13) # revealed: list[tuple[Literal[1], Literal[2], Literal[3]]]

crates/ty_python_semantic/src/types.rs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use ruff_diagnostics::{Edit, Fix};
44
use rustc_hash::FxHashMap;
55

66
use std::borrow::Cow;
7-
use std::cell::RefCell;
87
use std::time::Duration;
98

109
use bitflags::bitflags;
@@ -51,7 +50,7 @@ use crate::types::bound_super::BoundSuperType;
5150
use crate::types::call::{Binding, Bindings, CallArguments, CallableBinding};
5251
pub(crate) use crate::types::callable::{CallableType, CallableTypes};
5352
pub(crate) use crate::types::class_base::ClassBase;
54-
use crate::types::constraints::ConstraintSetBuilder;
53+
use crate::types::constraints::{ConstraintSetBuilder, Solutions};
5554
use crate::types::context::{LintDiagnosticGuard, LintDiagnosticGuardBuilder};
5655
use crate::types::diagnostic::{INVALID_AWAIT, INVALID_TYPE_FORM};
5756
pub use crate::types::display::{DisplaySettings, TypeDetail, TypeDisplayDetails};
@@ -60,10 +59,10 @@ use crate::types::function::{
6059
DataclassTransformerFlags, DataclassTransformerParams, FunctionDecorators, FunctionSpans,
6160
FunctionType, KnownFunction,
6261
};
62+
pub(crate) use crate::types::generics::GenericContext;
6363
use crate::types::generics::{
6464
ApplySpecialization, InferableTypeVars, Specialization, bind_typevar,
6565
};
66-
pub(crate) use crate::types::generics::{GenericContext, SpecializationBuilder};
6766
use crate::types::infer::InferenceFlags;
6867
use crate::types::known_instance::{InternedConstraintSet, InternedType, UnionTypeInstance};
6968
pub use crate::types::method::{BoundMethodType, KnownBoundMethodType, WrapperDescriptorKind};
@@ -1902,17 +1901,38 @@ impl<'db> Type<'db> {
19021901
let generic_context = specialization.generic_context(db);
19031902

19041903
// Collect the type mappings used to narrow the type context.
1905-
let tcx_mappings = {
1906-
let mut builder =
1907-
SpecializationBuilder::new(db, generic_context.inferable_typevars(db));
1908-
1909-
if let Some(tcx) = tcx.annotation {
1904+
//
1905+
// We use a forward CSA check (`alias_instance ≤ tcx`) to infer what each typevar
1906+
// in the identity specialization maps to in the type context. For example, if
1907+
// `tcx = list[int]` and `alias_instance = list[T]`, the CSA produces `T = int`.
1908+
let tcx_mappings: FxHashMap<_, _> = tcx
1909+
.annotation
1910+
.and_then(|tcx| {
19101911
let alias_instance = Type::instance(db, class_literal.identity_specialization(db));
1911-
let _ = builder.infer_reverse(constraints, tcx, alias_instance);
1912-
}
1913-
1914-
builder.into_type_mappings()
1915-
};
1912+
let set = alias_instance.when_constraint_set_assignable_to(db, tcx, constraints);
1913+
match set.solutions(db, constraints) {
1914+
Solutions::Constrained(solutions) => {
1915+
let mut mappings = FxHashMap::default();
1916+
for solution in solutions.iter() {
1917+
for binding in solution {
1918+
mappings
1919+
.entry(binding.bound_typevar.identity(db))
1920+
.and_modify(|existing| {
1921+
*existing = UnionType::from_two_elements(
1922+
db,
1923+
*existing,
1924+
binding.solution,
1925+
);
1926+
})
1927+
.or_insert(binding.solution);
1928+
}
1929+
}
1930+
Some(mappings)
1931+
}
1932+
_ => None,
1933+
}
1934+
})
1935+
.unwrap_or_default();
19161936

19171937
for (type_var, ty) in generic_context.variables(db).zip(specialization.types(db)) {
19181938
let variance = type_var.variance_with_polarity(db, polarity);
@@ -5501,12 +5521,6 @@ impl<'db> Type<'db> {
55015521
match type_mapping {
55025522
TypeMapping::EagerExpansion => unreachable!("handled above"),
55035523

5504-
// For UniqueSpecialization, get raw value type, apply specialization, then apply mapping.
5505-
TypeMapping::UniqueSpecialization { .. } => {
5506-
let value_type = alias.raw_value_type(db);
5507-
alias.apply_function_specialization(db, value_type).apply_type_mapping_impl(db, type_mapping, tcx, visitor)
5508-
}
5509-
55105524
_ => {
55115525
let value_type = alias.raw_value_type(db).apply_type_mapping_impl(db, type_mapping, tcx, visitor);
55125526
alias.apply_function_specialization(db, value_type).apply_type_mapping_impl(db, type_mapping, tcx, visitor)
@@ -5531,7 +5545,6 @@ impl<'db> Type<'db> {
55315545
Type::LiteralValue(_) => match type_mapping {
55325546
TypeMapping::ApplySpecialization(_) |
55335547
TypeMapping::ApplySpecializationWithMaterialization { .. } |
5534-
TypeMapping::UniqueSpecialization { .. } |
55355548
TypeMapping::BindLegacyTypevars(_) |
55365549
TypeMapping::BindSelf { .. } |
55375550
TypeMapping::ReplaceSelf { .. } |
@@ -5547,7 +5560,6 @@ impl<'db> Type<'db> {
55475560
Type::Dynamic(_) => match type_mapping {
55485561
TypeMapping::ApplySpecialization(_) |
55495562
TypeMapping::ApplySpecializationWithMaterialization { .. } |
5550-
TypeMapping::UniqueSpecialization { .. } |
55515563
TypeMapping::BindLegacyTypevars(_) |
55525564
TypeMapping::BindSelf(..) |
55535565
TypeMapping::ReplaceSelf { .. } |
@@ -6328,11 +6340,6 @@ pub enum TypeMapping<'a, 'db> {
63286340
specialization: ApplySpecialization<'a, 'db>,
63296341
materialization_kind: MaterializationKind,
63306342
},
6331-
/// Resets any specializations to contain unique synthetic type variables.
6332-
UniqueSpecialization {
6333-
// A list of synthetic type variables, and the types they replaced.
6334-
specialization: RefCell<Vec<(BoundTypeVarInstance<'db>, Type<'db>)>>,
6335-
},
63366343
/// Replaces any literal types with their corresponding promoted type form (e.g. `Literal["string"]`
63376344
/// to `str`, or `def _() -> int` to `Callable[[], int]`).
63386345
Promote(PromotionMode, PromotionKind),
@@ -6384,8 +6391,7 @@ impl<'db> TypeMapping<'_, 'db> {
63846391
}),
63856392
)
63866393
}
6387-
TypeMapping::UniqueSpecialization { .. }
6388-
| TypeMapping::Promote(..)
6394+
TypeMapping::Promote(..)
63896395
| TypeMapping::BindLegacyTypevars(_)
63906396
| TypeMapping::Materialize(_)
63916397
| TypeMapping::ReplaceParameterDefaults
@@ -6430,7 +6436,6 @@ impl<'db> TypeMapping<'_, 'db> {
64306436
},
64316437
TypeMapping::Promote(mode, kind) => TypeMapping::Promote(mode.flip(), *kind),
64326438
TypeMapping::ApplySpecialization(_)
6433-
| TypeMapping::UniqueSpecialization { .. }
64346439
| TypeMapping::BindLegacyTypevars(_)
64356440
| TypeMapping::BindSelf(..)
64366441
| TypeMapping::ReplaceSelf { .. }

0 commit comments

Comments
 (0)