mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 05:14:52 +00:00
[ty] add doc-comments for some variance stuff (#20189)
This commit is contained in:
parent
fdfb51b595
commit
eb6154f792
2 changed files with 31 additions and 1 deletions
|
@ -6551,6 +6551,7 @@ impl<'db> VarianceInferable<'db> for Type<'db> {
|
|||
}
|
||||
Type::GenericAlias(generic_alias) => generic_alias.variance_of(db, typevar),
|
||||
Type::Callable(callable_type) => callable_type.signatures(db).variance_of(db, typevar),
|
||||
// A type variable is always covariant in itself.
|
||||
Type::TypeVar(other_typevar) | Type::NonInferableTypeVar(other_typevar)
|
||||
if other_typevar == typevar =>
|
||||
{
|
||||
|
@ -6560,11 +6561,19 @@ impl<'db> VarianceInferable<'db> for Type<'db> {
|
|||
Type::ProtocolInstance(protocol_instance_type) => {
|
||||
protocol_instance_type.variance_of(db, typevar)
|
||||
}
|
||||
// unions are covariant in their disjuncts
|
||||
Type::Union(union_type) => union_type
|
||||
.elements(db)
|
||||
.iter()
|
||||
.map(|ty| ty.variance_of(db, typevar))
|
||||
.collect(),
|
||||
|
||||
// Products are covariant in their conjuncts. For negative
|
||||
// conjuncts, they're contravariant. To see this, suppose we have
|
||||
// `B` a subtype of `A`. A value of type `~B` could be some non-`B`
|
||||
// `A`, and so is not assignable to `~A`. On the other hand, a value
|
||||
// of type `~A` excludes all `A`s, and thus all `B`s, and so _is_
|
||||
// assignable to `~B`.
|
||||
Type::Intersection(intersection_type) => intersection_type
|
||||
.positive(db)
|
||||
.iter()
|
||||
|
|
|
@ -108,9 +108,30 @@ impl std::iter::FromIterator<Self> for TypeVarVariance {
|
|||
}
|
||||
|
||||
pub(crate) trait VarianceInferable<'db>: Sized {
|
||||
/// The variance of `typevar` in `self`
|
||||
///
|
||||
/// Generally, one will implement this by traversing any types within `self`
|
||||
/// in which `typevar` could occur, and calling `variance_of` recursively on
|
||||
/// them.
|
||||
///
|
||||
/// Sometimes the recursive calls will be in positions where you need to
|
||||
/// specify a non-covariant polarity. See `with_polarity` for more details.
|
||||
fn variance_of(self, db: &'db dyn Db, typevar: BoundTypeVarInstance<'db>) -> TypeVarVariance;
|
||||
|
||||
fn with_polarity(self, polarity: TypeVarVariance) -> WithPolarity<Self> {
|
||||
/// Creates a `VarianceInferable` that applies `polarity` (see
|
||||
/// `TypeVarVariance::compose`) to the result of variance inference on the
|
||||
/// underlying value.
|
||||
///
|
||||
/// In some cases, we need to apply a polarity to the recursive call.
|
||||
/// You can do this with `ty.with_polarity(polarity).variance_of(typevar)`.
|
||||
/// Generally, this will be whenever the type occurs in argument-position,
|
||||
/// in which case you will want `TypeVarVariance::Contravariant`, or
|
||||
/// `TypeVarVariance::Invariant` if the value(s) being annotated is known to
|
||||
/// be mutable, such as `T` in `list[T]`. See the [typing spec][typing-spec]
|
||||
/// for more details.
|
||||
///
|
||||
/// [typing-spec]: https://typing.python.org/en/latest/spec/generics.html#variance
|
||||
fn with_polarity(self, polarity: TypeVarVariance) -> impl VarianceInferable<'db> {
|
||||
WithPolarity {
|
||||
variance_inferable: self,
|
||||
polarity,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue