mirror of https://github.com/astral-sh/ruff
add more comments
This commit is contained in:
parent
4f7ad7bbc9
commit
b1ede8885b
|
|
@ -556,6 +556,13 @@ impl<'db> GenericContext<'db> {
|
||||||
let partial = PartialSpecialization {
|
let partial = PartialSpecialization {
|
||||||
generic_context: self,
|
generic_context: self,
|
||||||
types: &types,
|
types: &types,
|
||||||
|
// Don't recursively substitute type[i] in itself. Ideally, we could instead
|
||||||
|
// check if the result is self-referential after we're done applying the
|
||||||
|
// partial specialization. But when we apply a paramspec, we don't use the
|
||||||
|
// callable that it maps to directly; we create a new callable that reuses
|
||||||
|
// parts of it. That means we can't look for the previous type directly.
|
||||||
|
// Instead we use this to skip specializing the type in itself in the first
|
||||||
|
// place.
|
||||||
skip: Some(i),
|
skip: Some(i),
|
||||||
};
|
};
|
||||||
let updated = types[i].apply_type_mapping(
|
let updated = types[i].apply_type_mapping(
|
||||||
|
|
@ -1362,6 +1369,8 @@ impl<'db> Specialization<'db> {
|
||||||
pub struct PartialSpecialization<'a, 'db> {
|
pub struct PartialSpecialization<'a, 'db> {
|
||||||
generic_context: GenericContext<'db>,
|
generic_context: GenericContext<'db>,
|
||||||
types: &'a [Type<'db>],
|
types: &'a [Type<'db>],
|
||||||
|
/// An optional typevar to _not_ substitute when applying the specialization. We use this to
|
||||||
|
/// avoid recursively substituting a type inside of itself.
|
||||||
skip: Option<usize>,
|
skip: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1471,6 +1480,14 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds all of the valid specializations of a constraint set, and adds their type mappings to
|
||||||
|
/// the specialization that this builder is building up.
|
||||||
|
///
|
||||||
|
/// TODO: This is a stopgap! Eventually, the builder will maintain a single constraint set for
|
||||||
|
/// the main specialization that we are building, and [`build`][Self::build] will build the
|
||||||
|
/// specialization directly from that constraint set. This method lets us migrate to that brave
|
||||||
|
/// new world incrementally, by using the new constraint set mechanism piecemeal for certain
|
||||||
|
/// type comparisons.
|
||||||
fn add_type_mappings_from_constraint_set(
|
fn add_type_mappings_from_constraint_set(
|
||||||
&mut self,
|
&mut self,
|
||||||
constraints: ConstraintSet<'db>,
|
constraints: ConstraintSet<'db>,
|
||||||
|
|
@ -1526,6 +1543,15 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
polarity: TypeVarVariance,
|
polarity: TypeVarVariance,
|
||||||
mut f: &mut dyn FnMut(TypeVarAssignment<'db>) -> Option<Type<'db>>,
|
mut f: &mut dyn FnMut(TypeVarAssignment<'db>) -> Option<Type<'db>>,
|
||||||
) -> Result<(), SpecializationError<'db>> {
|
) -> Result<(), SpecializationError<'db>> {
|
||||||
|
// TODO: Eventually, the builder will maintain a constraint set, instead of a hash-map of
|
||||||
|
// type mappings, to represent the specialization that we are building up. At that point,
|
||||||
|
// this method will just need to compare `actual ≤ formal`, using constraint set
|
||||||
|
// assignability, and AND the result into the constraint set we are building.
|
||||||
|
//
|
||||||
|
// To make progress on that migration, we use constraint set assignability whenever
|
||||||
|
// possible when adding any new heuristics here. See the `Callable` clause below for an
|
||||||
|
// example.
|
||||||
|
|
||||||
if formal == actual {
|
if formal == actual {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -443,6 +443,10 @@ impl<'db> CallableSignature<'db> {
|
||||||
let self_is_single_paramspec = Self::signatures_is_single_paramspec(self_signatures);
|
let self_is_single_paramspec = Self::signatures_is_single_paramspec(self_signatures);
|
||||||
let other_is_single_paramspec = Self::signatures_is_single_paramspec(other_signatures);
|
let other_is_single_paramspec = Self::signatures_is_single_paramspec(other_signatures);
|
||||||
|
|
||||||
|
// If either callable is a ParamSpec, the constraint set should bind the ParamSpec to
|
||||||
|
// the other callable's signature. We also need to compare the return types — for
|
||||||
|
// instance, to verify in `Callable[P, int]` that the return type is assignable to
|
||||||
|
// `int`, or in `Callable[P, T]` to bind `T` to the return type of the other callable.
|
||||||
match (self_is_single_paramspec, other_is_single_paramspec) {
|
match (self_is_single_paramspec, other_is_single_paramspec) {
|
||||||
(
|
(
|
||||||
Some((self_bound_typevar, self_return_type)),
|
Some((self_bound_typevar, self_return_type)),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue