Compare commits

...

1 Commits

Author SHA1 Message Date
Micha Reiser
39b5c696e2 [ty] Experiment 2025-12-17 12:25:01 +01:00
13 changed files with 216 additions and 154 deletions

View File

@@ -615,7 +615,7 @@ impl<'db> PropertyInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.is_equivalent_to_impl(db, other, inferable, &IsEquivalentVisitor::default())
}
@@ -624,7 +624,7 @@ impl<'db> PropertyInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
let getter_equivalence = if let Some(getter) = self.getter(db) {
@@ -1486,7 +1486,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> Type<'db> {
self.filter_union(db, |elem| {
!elem
@@ -1952,7 +1952,7 @@ impl<'db> Type<'db> {
///
/// See [`TypeRelation::Subtyping`] for more details.
pub(crate) fn is_subtype_of(self, db: &'db dyn Db, target: Type<'db>) -> bool {
self.when_subtype_of(db, target, InferableTypeVars::None)
self.when_subtype_of(db, target, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -1960,7 +1960,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to(db, target, inferable, TypeRelation::Subtyping)
}
@@ -1974,7 +1974,7 @@ impl<'db> Type<'db> {
db: &'db dyn Db,
target: Type<'db>,
assuming: ConstraintSet<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to(
db,
@@ -1988,7 +1988,7 @@ impl<'db> Type<'db> {
///
/// See `TypeRelation::Assignability` for more details.
pub fn is_assignable_to(self, db: &'db dyn Db, target: Type<'db>) -> bool {
self.when_assignable_to(db, target, InferableTypeVars::None)
self.when_assignable_to(db, target, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -1998,7 +1998,7 @@ impl<'db> Type<'db> {
/// a constraint set and lets `satisfied_by_all_typevars` perform existential vs universal
/// reasoning depending on inferable typevars.
pub fn is_constraint_set_assignable_to(self, db: &'db dyn Db, target: Type<'db>) -> bool {
self.when_constraint_set_assignable_to(db, target, InferableTypeVars::None)
self.when_constraint_set_assignable_to(db, target, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -2006,7 +2006,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to(db, target, inferable, TypeRelation::Assignability)
}
@@ -2015,7 +2015,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to(
db,
@@ -2036,7 +2036,7 @@ impl<'db> Type<'db> {
other: Type<'db>,
) -> bool {
self_ty
.has_relation_to(db, other, InferableTypeVars::None, TypeRelation::Redundancy)
.has_relation_to(db, other, &InferableTypeVars::None, TypeRelation::Redundancy)
.is_always_satisfied(db)
}
@@ -2051,24 +2051,35 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to_impl(
db,
target,
inferable,
relation,
&HasRelationToVisitor::default(),
&IsDisjointVisitor::default(),
)
#[salsa::tracked(cycle_initial=has_relation_to_cycle_initial, heap_size=ruff_memory_usage::heap_size)]
fn has_relation_to_tracked<'db>(
db: &'db dyn Db,
source: Type<'db>,
target: Type<'db>,
inferable: InferableTypeVars<'db>,
relation: TypeRelation<'db>,
) -> ConstraintSet<'db> {
source.has_relation_to_impl(
db,
target,
&inferable,
relation,
&HasRelationToVisitor::default(),
&IsDisjointVisitor::default(),
)
}
has_relation_to_tracked(db, self, target, inferable.clone(), relation)
}
fn has_relation_to_impl(
self,
db: &'db dyn Db,
target: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -3093,7 +3104,7 @@ impl<'db> Type<'db> {
///
/// [equivalent to]: https://typing.python.org/en/latest/spec/glossary.html#term-equivalent
pub(crate) fn is_equivalent_to(self, db: &'db dyn Db, other: Type<'db>) -> bool {
self.when_equivalent_to(db, other, InferableTypeVars::None)
self.when_equivalent_to(db, other, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -3101,7 +3112,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.is_equivalent_to_impl(db, other, inferable, &IsEquivalentVisitor::default())
}
@@ -3110,7 +3121,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {
@@ -3224,7 +3235,7 @@ impl<'db> Type<'db> {
/// This function aims to have no false positives, but might return wrong
/// `false` answers in some cases.
pub(crate) fn is_disjoint_from(self, db: &'db dyn Db, other: Type<'db>) -> bool {
self.when_disjoint_from(db, other, InferableTypeVars::None)
self.when_disjoint_from(db, other, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -3232,7 +3243,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.is_disjoint_from_impl(
db,
@@ -3247,7 +3258,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -3255,7 +3266,7 @@ impl<'db> Type<'db> {
db: &'db dyn Db,
protocol: ProtocolInstanceType<'db>,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -8658,6 +8669,19 @@ fn is_redundant_with_cycle_initial<'db>(
true
}
fn has_relation_to_cycle_initial<'db>(
_db: &'db dyn Db,
_id: salsa::Id,
_source: Type<'db>,
_target: Type<'db>,
_inferable: InferableTypeVars<'db>,
_relation: TypeRelation<'db>,
) -> ConstraintSet<'db> {
// For recursive types, optimistically assume the relation holds.
// This matches the fallback behavior of HasRelationToVisitor::default().
ConstraintSet::from(true)
}
fn apply_specialization_cycle_recover<'db>(
db: &'db dyn Db,
cycle: &salsa::Cycle,
@@ -12288,7 +12312,7 @@ impl<'db> BoundMethodType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -12322,7 +12346,7 @@ impl<'db> BoundMethodType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
self.function(db)
@@ -12538,7 +12562,7 @@ impl<'db> CallableType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -12563,7 +12587,7 @@ impl<'db> CallableType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {
@@ -12629,7 +12653,7 @@ impl<'db> CallableTypes<'db> {
self,
db: &'db dyn Db,
other: CallableType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -12718,7 +12742,7 @@ impl<'db> KnownBoundMethodType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -12823,7 +12847,7 @@ impl<'db> KnownBoundMethodType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
match (self, other) {
@@ -14072,7 +14096,7 @@ impl<'db> UnionType<'db> {
self,
db: &'db dyn Db,
other: Self,
_inferable: InferableTypeVars<'_, 'db>,
_inferable: &InferableTypeVars<'db>,
_visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {
@@ -14276,7 +14300,7 @@ impl<'db> IntersectionType<'db> {
self,
db: &'db dyn Db,
other: Self,
_inferable: InferableTypeVars<'_, 'db>,
_inferable: &InferableTypeVars<'db>,
_visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {

View File

@@ -737,7 +737,7 @@ impl<'db> Bindings<'db> {
Some(KnownFunction::IsEquivalentTo) => {
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
let constraints =
ty_a.when_equivalent_to(db, *ty_b, InferableTypeVars::None);
ty_a.when_equivalent_to(db, *ty_b, &InferableTypeVars::None);
let tracked = TrackedConstraintSet::new(db, constraints);
overload.set_return_type(Type::KnownInstance(
KnownInstanceType::ConstraintSet(tracked),
@@ -748,7 +748,7 @@ impl<'db> Bindings<'db> {
Some(KnownFunction::IsSubtypeOf) => {
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
let constraints =
ty_a.when_subtype_of(db, *ty_b, InferableTypeVars::None);
ty_a.when_subtype_of(db, *ty_b, &InferableTypeVars::None);
let tracked = TrackedConstraintSet::new(db, constraints);
overload.set_return_type(Type::KnownInstance(
KnownInstanceType::ConstraintSet(tracked),
@@ -759,7 +759,7 @@ impl<'db> Bindings<'db> {
Some(KnownFunction::IsAssignableTo) => {
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
let constraints =
ty_a.when_assignable_to(db, *ty_b, InferableTypeVars::None);
ty_a.when_assignable_to(db, *ty_b, &InferableTypeVars::None);
let tracked = TrackedConstraintSet::new(db, constraints);
overload.set_return_type(Type::KnownInstance(
KnownInstanceType::ConstraintSet(tracked),
@@ -770,7 +770,7 @@ impl<'db> Bindings<'db> {
Some(KnownFunction::IsDisjointFrom) => {
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
let constraints =
ty_a.when_disjoint_from(db, *ty_b, InferableTypeVars::None);
ty_a.when_disjoint_from(db, *ty_b, &InferableTypeVars::None);
let tracked = TrackedConstraintSet::new(db, constraints);
overload.set_return_type(Type::KnownInstance(
KnownInstanceType::ConstraintSet(tracked),
@@ -1254,7 +1254,7 @@ impl<'db> Bindings<'db> {
db,
*ty_b,
tracked.constraints(db),
InferableTypeVars::None,
&InferableTypeVars::None,
);
let tracked = TrackedConstraintSet::new(db, result);
overload.set_return_type(Type::KnownInstance(
@@ -1314,7 +1314,7 @@ impl<'db> Bindings<'db> {
let result = tracked
.constraints(db)
.satisfied_by_all_typevars(db, InferableTypeVars::One(&inferable));
.satisfied_by_all_typevars(db, &InferableTypeVars::One(std::sync::Arc::new(inferable.clone())));
overload.set_return_type(Type::BooleanLiteral(result));
}
@@ -1732,7 +1732,7 @@ impl<'db> CallableBinding<'db> {
.annotated_type()
.unwrap_or(Type::unknown());
if argument_type
.when_assignable_to(db, parameter_type, overload.inferable_typevars)
.when_assignable_to(db, parameter_type, &overload.inferable_typevars)
.is_always_satisfied(db)
{
is_argument_assignable_to_any_overload = true;
@@ -1986,7 +1986,7 @@ impl<'db> CallableBinding<'db> {
.when_equivalent_to(
db,
current_parameter_type,
overload.inferable_typevars,
&overload.inferable_typevars,
)
.is_always_satisfied(db)
{
@@ -2134,7 +2134,7 @@ impl<'db> CallableBinding<'db> {
.when_equivalent_to(
db,
first_overload_return_type,
overload.inferable_typevars,
&overload.inferable_typevars,
)
.is_always_satisfied(db)
})
@@ -2925,7 +2925,7 @@ struct ArgumentTypeChecker<'a, 'db> {
return_ty: Type<'db>,
errors: &'a mut Vec<BindingError<'db>>,
inferable_typevars: InferableTypeVars<'db, 'db>,
inferable_typevars: InferableTypeVars<'db>,
specialization: Option<Specialization<'db>>,
}
@@ -2997,7 +2997,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
.zip(self.call_expression_tcx.annotation);
self.inferable_typevars = generic_context.inferable_typevars(self.db);
let mut builder = SpecializationBuilder::new(self.db, self.inferable_typevars);
let mut builder = SpecializationBuilder::new(self.db, self.inferable_typevars.clone());
// Prefer the declared type of generic classes.
let preferred_type_mappings = return_with_tcx.and_then(|(return_ty, tcx)| {
@@ -3169,7 +3169,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
// constraint set that we get from this assignability check, instead of inferring and
// building them in an earlier separate step.
if argument_type
.when_assignable_to(self.db, expected_ty, self.inferable_typevars)
.when_assignable_to(self.db, expected_ty, &self.inferable_typevars)
.is_never_satisfied(self.db)
{
let positional = matches!(argument, Argument::Positional | Argument::Synthetic)
@@ -3442,7 +3442,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
.when_assignable_to(
self.db,
KnownClass::Str.to_instance(self.db),
self.inferable_typevars,
&self.inferable_typevars,
)
.is_always_satisfied(self.db)
{
@@ -3507,7 +3507,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
fn finish(
self,
) -> (
InferableTypeVars<'db, 'db>,
InferableTypeVars<'db>,
Option<Specialization<'db>>,
Type<'db>,
) {
@@ -3580,7 +3580,7 @@ pub(crate) struct Binding<'db> {
return_ty: Type<'db>,
/// The inferable typevars in this signature.
inferable_typevars: InferableTypeVars<'db, 'db>,
inferable_typevars: InferableTypeVars<'db>,
/// The specialization that was inferred from the argument types, if the callable is generic.
specialization: Option<Specialization<'db>>,
@@ -3784,7 +3784,7 @@ impl<'db> Binding<'db> {
fn snapshot(&self) -> BindingSnapshot<'db> {
BindingSnapshot {
return_ty: self.return_ty,
inferable_typevars: self.inferable_typevars,
inferable_typevars: self.inferable_typevars.clone(),
specialization: self.specialization,
argument_matches: self.argument_matches.clone(),
parameter_tys: self.parameter_tys.clone(),
@@ -3834,7 +3834,7 @@ impl<'db> Binding<'db> {
#[derive(Clone, Debug)]
struct BindingSnapshot<'db> {
return_ty: Type<'db>,
inferable_typevars: InferableTypeVars<'db, 'db>,
inferable_typevars: InferableTypeVars<'db>,
specialization: Option<Specialization<'db>>,
argument_matches: Box<[MatchedArgument<'db>]>,
parameter_tys: Box<[Option<Type<'db>>]>,
@@ -3874,7 +3874,7 @@ impl<'db> CallableBindingSnapshot<'db> {
// ... and update the snapshot with the current state of the binding.
snapshot.return_ty = binding.return_ty;
snapshot.inferable_typevars = binding.inferable_typevars;
snapshot.inferable_typevars = binding.inferable_typevars.clone();
snapshot.specialization = binding.specialization;
snapshot
.argument_matches

View File

@@ -600,7 +600,7 @@ impl<'db> ClassType<'db> {
/// Return `true` if `other` is present in this class's MRO.
pub(super) fn is_subclass_of(self, db: &'db dyn Db, other: ClassType<'db>) -> bool {
self.when_subclass_of(db, other, InferableTypeVars::None)
self.when_subclass_of(db, other, &InferableTypeVars::None)
.is_always_satisfied(db)
}
@@ -608,7 +608,7 @@ impl<'db> ClassType<'db> {
self,
db: &'db dyn Db,
other: ClassType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to_impl(
db,
@@ -624,7 +624,7 @@ impl<'db> ClassType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -676,7 +676,7 @@ impl<'db> ClassType<'db> {
self,
db: &'db dyn Db,
other: ClassType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {
@@ -736,7 +736,7 @@ impl<'db> ClassType<'db> {
.is_disjoint_from(
db,
other_alias.specialization(db),
InferableTypeVars::None,
&InferableTypeVars::None,
)
.is_always_satisfied(db)
}

View File

@@ -346,7 +346,7 @@ impl<'db> ConstraintSet<'db> {
pub(crate) fn satisfied_by_all_typevars(
self,
db: &'db dyn Db,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> bool {
self.node.satisfied_by_all_typevars(db, inferable)
}
@@ -1311,7 +1311,7 @@ impl<'db> Node<'db> {
fn satisfied_by_all_typevars(
self,
db: &'db dyn Db,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> bool {
match self {
Node::AlwaysTrue => return true,

View File

@@ -1108,7 +1108,7 @@ impl<'db> FunctionType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1133,7 +1133,7 @@ impl<'db> FunctionType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self.normalized(db) == other.normalized(db) {

View File

@@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::fmt::Display;
use itertools::{Either, Itertools};
use itertools::Itertools;
use ruff_python_ast as ast;
use rustc_hash::{FxHashMap, FxHashSet};
@@ -119,50 +119,90 @@ pub(crate) fn typing_self<'db>(
)
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum InferableTypeVars<'a, 'db> {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum InferableTypeVars<'db> {
None,
One(&'a FxHashSet<BoundTypeVarIdentity<'db>>),
One(std::sync::Arc<FxHashSet<BoundTypeVarIdentity<'db>>>),
Two(
&'a InferableTypeVars<'a, 'db>,
&'a InferableTypeVars<'a, 'db>,
std::sync::Arc<InferableTypeVars<'db>>,
std::sync::Arc<InferableTypeVars<'db>>,
),
}
impl<'db> std::hash::Hash for InferableTypeVars<'db> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
InferableTypeVars::None => {
0u8.hash(state);
}
InferableTypeVars::One(set) => {
1u8.hash(state);
// Sort the identities for deterministic hashing.
let mut items: Vec<_> = set.iter().copied().collect();
items.sort_unstable();
for item in items {
item.hash(state);
}
}
InferableTypeVars::Two(left, right) => {
2u8.hash(state);
left.hash(state);
right.hash(state);
}
}
}
}
impl<'db> BoundTypeVarInstance<'db> {
pub(crate) fn is_inferable(
self,
db: &'db dyn Db,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> bool {
match inferable {
InferableTypeVars::None => false,
InferableTypeVars::One(typevars) => typevars.contains(&self.identity(db)),
InferableTypeVars::Two(left, right) => {
self.is_inferable(db, *left) || self.is_inferable(db, *right)
self.is_inferable(db, left) || self.is_inferable(db, right)
}
}
}
}
impl<'a, 'db> InferableTypeVars<'a, 'db> {
pub(crate) fn merge(&'a self, other: &'a InferableTypeVars<'a, 'db>) -> Self {
impl<'db> InferableTypeVars<'db> {
pub(crate) fn merge(self, other: InferableTypeVars<'db>) -> Self {
match (self, other) {
(InferableTypeVars::None, other) | (other, InferableTypeVars::None) => *other,
_ => InferableTypeVars::Two(self, other),
(InferableTypeVars::None, other) | (other, InferableTypeVars::None) => other,
(left, right) => InferableTypeVars::Two(std::sync::Arc::new(left), std::sync::Arc::new(right)),
}
}
// This is not an IntoIterator implementation because I have no desire to try to name the
// iterator type.
pub(crate) fn iter(self) -> impl Iterator<Item = BoundTypeVarIdentity<'db>> {
pub(crate) fn iter(&self) -> impl Iterator<Item = BoundTypeVarIdentity<'db>> + '_ {
enum Iter<'a, 'db> {
Empty,
One(std::collections::hash_set::Iter<'a, BoundTypeVarIdentity<'db>>),
Two(Box<dyn Iterator<Item = BoundTypeVarIdentity<'db>> + 'a>),
}
impl<'db> Iterator for Iter<'_, 'db> {
type Item = BoundTypeVarIdentity<'db>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Iter::Empty => None,
Iter::One(iter) => iter.next().copied(),
Iter::Two(iter) => iter.next(),
}
}
}
match self {
InferableTypeVars::None => Either::Left(Either::Left(std::iter::empty())),
InferableTypeVars::One(typevars) => Either::Right(typevars.iter().copied()),
InferableTypeVars::None => Iter::Empty,
InferableTypeVars::One(typevars) => Iter::One(typevars.iter()),
InferableTypeVars::Two(left, right) => {
let chained: Box<dyn Iterator<Item = BoundTypeVarIdentity<'db>>> =
Box::new(left.iter().chain(right.iter()));
Either::Left(Either::Right(chained))
Iter::Two(Box::new(left.iter().chain(right.iter())))
}
}
}
@@ -172,7 +212,7 @@ impl<'a, 'db> InferableTypeVars<'a, 'db> {
pub(crate) fn display(&self, db: &'db dyn Db) -> impl Display {
fn find_typevars<'db>(
result: &mut FxHashSet<BoundTypeVarIdentity<'db>>,
inferable: &InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) {
match inferable {
InferableTypeVars::None => {}
@@ -302,7 +342,7 @@ impl<'db> GenericContext<'db> {
/// In this example, `method`'s generic context binds `Self` and `T`, but its inferable set
/// also includes `A@C`. This is needed because at each call site, we need to infer the
/// specialized class instance type whose method is being invoked.
pub(crate) fn inferable_typevars(self, db: &'db dyn Db) -> InferableTypeVars<'db, 'db> {
pub(crate) fn inferable_typevars(self, db: &'db dyn Db) -> InferableTypeVars<'db> {
#[derive(Default)]
struct CollectTypeVars<'db> {
typevars: RefCell<FxHashSet<BoundTypeVarIdentity<'db>>>,
@@ -349,10 +389,8 @@ impl<'db> GenericContext<'db> {
visitor.typevars.into_inner()
}
// This ensures that salsa caches the FxHashSet, not the InferableTypeVars that wraps it.
// (That way InferableTypeVars can contain references, and doesn't need to impl
// salsa::Update.)
InferableTypeVars::One(inferable_typevars_inner(db, self))
// Wrap the Salsa-cached FxHashSet in an Arc.
InferableTypeVars::One(std::sync::Arc::new(inferable_typevars_inner(db, self).clone()))
}
pub(crate) fn variables(
@@ -769,7 +807,7 @@ fn is_subtype_in_invariant_position<'db>(
derived_materialization: MaterializationKind,
base_type: &Type<'db>,
base_materialization: MaterializationKind,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -847,7 +885,7 @@ fn has_relation_in_invariant_position<'db>(
derived_materialization: Option<MaterializationKind>,
base_type: &Type<'db>,
base_materialization: Option<MaterializationKind>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1233,7 +1271,7 @@ impl<'db> Specialization<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1308,7 +1346,7 @@ impl<'db> Specialization<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.is_disjoint_from_impl(
db,
@@ -1323,7 +1361,7 @@ impl<'db> Specialization<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -1382,7 +1420,7 @@ impl<'db> Specialization<'db> {
self,
db: &'db dyn Db,
other: Specialization<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self.materialization_kind(db) != other.materialization_kind(db) {
@@ -1483,7 +1521,7 @@ impl<'db> PartialSpecialization<'_, 'db> {
/// specialization of a generic function.
pub(crate) struct SpecializationBuilder<'db> {
db: &'db dyn Db,
inferable: InferableTypeVars<'db, 'db>,
inferable: InferableTypeVars<'db>,
types: FxHashMap<BoundTypeVarIdentity<'db>, Type<'db>>,
}
@@ -1492,7 +1530,7 @@ pub(crate) struct SpecializationBuilder<'db> {
pub(crate) type TypeVarAssignment<'db> = (BoundTypeVarIdentity<'db>, TypeVarVariance, Type<'db>);
impl<'db> SpecializationBuilder<'db> {
pub(crate) fn new(db: &'db dyn Db, inferable: InferableTypeVars<'db, 'db>) -> Self {
pub(crate) fn new(db: &'db dyn Db, inferable: InferableTypeVars<'db>) -> Self {
Self {
db,
inferable,
@@ -1520,7 +1558,7 @@ impl<'db> SpecializationBuilder<'db> {
Self {
db: self.db,
inferable: self.inferable,
inferable: self.inferable.clone(),
types,
}
}
@@ -1687,8 +1725,8 @@ impl<'db> SpecializationBuilder<'db> {
//
// For example, if `formal` is `list[T]` and `actual` is `list[int] | None`, we want to
// specialize `T` to `int`, and so ignore the `None`.
let actual = actual.filter_disjoint_elements(self.db, formal, self.inferable);
let formal = formal.filter_disjoint_elements(self.db, actual, self.inferable);
let actual = actual.filter_disjoint_elements(self.db, formal, &self.inferable);
let formal = formal.filter_disjoint_elements(self.db, actual, &self.inferable);
match (formal, actual) {
// TODO: We haven't implemented a full unification solver yet. If typevars appear in
@@ -1751,7 +1789,7 @@ impl<'db> SpecializationBuilder<'db> {
let assignable_elements =
(union_formal.elements(self.db).iter()).filter(|ty| {
actual
.when_subtype_of(self.db, **ty, self.inferable)
.when_subtype_of(self.db, **ty, &self.inferable)
.is_always_satisfied(self.db)
});
if assignable_elements.exactly_one().is_ok() {
@@ -1786,7 +1824,7 @@ impl<'db> SpecializationBuilder<'db> {
// The recursive call to `infer_map_impl` may succeed even if the actual type is
// not assignable to the formal element.
if !actual
.when_assignable_to(self.db, *formal_element, self.inferable)
.when_assignable_to(self.db, *formal_element, &self.inferable)
.is_never_satisfied(self.db)
{
found_matching_element = true;
@@ -1810,12 +1848,12 @@ impl<'db> SpecializationBuilder<'db> {
}
(Type::TypeVar(bound_typevar), ty) | (ty, Type::TypeVar(bound_typevar))
if bound_typevar.is_inferable(self.db, self.inferable) =>
if bound_typevar.is_inferable(self.db, &self.inferable) =>
{
match bound_typevar.typevar(self.db).bound_or_constraints(self.db) {
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
if !ty
.when_assignable_to(self.db, bound, self.inferable)
.when_assignable_to(self.db, bound, &self.inferable)
.is_always_satisfied(self.db)
{
return Err(SpecializationError::MismatchedBound {
@@ -1836,7 +1874,7 @@ impl<'db> SpecializationBuilder<'db> {
for constraint in constraints.elements(self.db) {
if ty
.when_assignable_to(self.db, *constraint, self.inferable)
.when_assignable_to(self.db, *constraint, &self.inferable)
.is_always_satisfied(self.db)
{
self.add_type_mapping(bound_typevar, *constraint, polarity, f);
@@ -1947,7 +1985,7 @@ impl<'db> SpecializationBuilder<'db> {
.when_constraint_set_assignable_to(
self.db,
formal_callable,
self.inferable,
&self.inferable,
);
self.add_type_mappings_from_constraint_set(formal, when, &mut f);
} else {
@@ -1956,7 +1994,7 @@ impl<'db> SpecializationBuilder<'db> {
.when_constraint_set_assignable_to_signatures(
self.db,
formal_callable,
self.inferable,
&self.inferable,
);
self.add_type_mappings_from_constraint_set(formal, when, &mut f);
}

View File

@@ -7650,7 +7650,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
annotation.filter_disjoint_elements(
self.db(),
Type::homogeneous_tuple(self.db(), Type::unknown()),
inferable,
&inferable,
)
});
@@ -7835,7 +7835,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
// `collection_ty` is `list`.
let tcx = tcx.map(|annotation| {
let collection_ty = collection_class.to_instance(self.db());
annotation.filter_disjoint_elements(self.db(), collection_ty, inferable)
annotation.filter_disjoint_elements(self.db(), collection_ty, &inferable)
});
// Extract the annotated type of `T`, if provided.
@@ -7986,7 +7986,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
annotation.filter_disjoint_elements(
self.db(),
collection_class.to_instance(self.db()),
InferableTypeVars::None,
&InferableTypeVars::None,
)
});
@@ -11851,7 +11851,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
match typevar.typevar(db).bound_or_constraints(db) {
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
if provided_type
.when_assignable_to(db, bound, InferableTypeVars::None)
.when_assignable_to(db, bound, &InferableTypeVars::None)
.is_never_satisfied(db)
{
let node = get_node(index);
@@ -11882,7 +11882,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
.when_assignable_to(
db,
constraints.as_type(db),
InferableTypeVars::None,
&InferableTypeVars::None,
)
.is_never_satisfied(db)
{

View File

@@ -127,7 +127,7 @@ impl<'db> Type<'db> {
self,
db: &'db dyn Db,
protocol: ProtocolInstanceType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -405,7 +405,7 @@ impl<'db> NominalInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -438,7 +438,7 @@ impl<'db> NominalInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
match (self.0, other.0) {
@@ -460,7 +460,7 @@ impl<'db> NominalInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -706,7 +706,7 @@ impl<'db> ProtocolInstanceType<'db> {
.satisfies_protocol(
db,
protocol,
InferableTypeVars::None,
&InferableTypeVars::None,
TypeRelation::Subtyping,
&HasRelationToVisitor::default(),
&IsDisjointVisitor::default(),
@@ -771,7 +771,7 @@ impl<'db> ProtocolInstanceType<'db> {
self,
db: &'db dyn Db,
other: Self,
_inferable: InferableTypeVars<'_, 'db>,
_inferable: &InferableTypeVars<'db>,
_visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
if self == other {
@@ -793,7 +793,7 @@ impl<'db> ProtocolInstanceType<'db> {
self,
_db: &'db dyn Db,
_other: Self,
_inferable: InferableTypeVars<'_, 'db>,
_inferable: &InferableTypeVars<'db>,
_visitor: &IsDisjointVisitor<'db>,
) -> ConstraintSet<'db> {
ConstraintSet::from(false)

View File

@@ -273,7 +273,7 @@ impl<'db> ProtocolInterface<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -694,7 +694,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
&self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -719,7 +719,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
&self,
db: &'db dyn Db,
other: Type<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,

View File

@@ -304,7 +304,7 @@ impl<'db> CallableSignature<'db> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to_impl(
db,
@@ -320,7 +320,7 @@ impl<'db> CallableSignature<'db> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -362,7 +362,7 @@ impl<'db> CallableSignature<'db> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to_impl(
db,
@@ -380,7 +380,7 @@ impl<'db> CallableSignature<'db> {
db: &'db dyn Db,
self_signatures: &[Signature<'db>],
other_signatures: &[Signature<'db>],
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -551,7 +551,7 @@ impl<'db> CallableSignature<'db> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
match (self.overloads.as_slice(), other.overloads.as_slice()) {
@@ -966,7 +966,7 @@ impl<'db> Signature<'db> {
}
}
fn inferable_typevars(&self, db: &'db dyn Db) -> InferableTypeVars<'db, 'db> {
fn inferable_typevars(&self, db: &'db dyn Db) -> InferableTypeVars<'db> {
match self.generic_context {
Some(generic_context) => generic_context.inferable_typevars(db),
None => InferableTypeVars::None,
@@ -980,7 +980,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &Signature<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
// If either signature is generic, their typevars should also be considered inferable when
@@ -997,11 +997,11 @@ impl<'db> Signature<'db> {
// return t
let self_inferable = self.inferable_typevars(db);
let other_inferable = other.inferable_typevars(db);
let inferable = inferable.merge(&self_inferable);
let inferable = inferable.merge(&other_inferable);
let inferable = inferable.clone().merge(self_inferable.clone());
let inferable = inferable.merge(other_inferable.clone());
// `inner` will create a constraint set that references these newly inferable typevars.
let when = self.is_equivalent_to_inner(db, other, inferable, visitor);
let when = self.is_equivalent_to_inner(db, other, &inferable, visitor);
// But the caller does not need to consider those extra typevars. Whatever constraint set
// we produce, we reduce it back down to the inferable set that the caller asked about.
@@ -1014,7 +1014,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &Signature<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
let mut result = ConstraintSet::from(true);
@@ -1100,7 +1100,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &CallableSignature<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
// If this signature is a paramspec, bind it to the entire overloaded other callable.
if let Some(self_bound_typevar) = self.parameters.as_paramspec()
@@ -1143,7 +1143,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
) -> ConstraintSet<'db> {
self.has_relation_to_impl(
db,
@@ -1160,7 +1160,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &Signature<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1179,14 +1179,14 @@ impl<'db> Signature<'db> {
// return t
let self_inferable = self.inferable_typevars(db);
let other_inferable = other.inferable_typevars(db);
let inferable = inferable.merge(&self_inferable);
let inferable = inferable.merge(&other_inferable);
let inferable = inferable.clone().merge(self_inferable.clone());
let inferable = inferable.merge(other_inferable.clone());
// `inner` will create a constraint set that references these newly inferable typevars.
let when = self.has_relation_to_inner(
db,
other,
inferable,
&inferable,
relation,
relation_visitor,
disjointness_visitor,
@@ -1203,7 +1203,7 @@ impl<'db> Signature<'db> {
&self,
db: &'db dyn Db,
other: &Signature<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,

View File

@@ -205,7 +205,7 @@ impl<'db> SubclassOfType<'db> {
self,
db: &'db dyn Db,
other: SubclassOfType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -247,7 +247,7 @@ impl<'db> SubclassOfType<'db> {
self,
db: &'db dyn Db,
other: Self,
_inferable: InferableTypeVars<'_, 'db>,
_inferable: &InferableTypeVars<'db>,
_visitor: &IsDisjointVisitor<'db>,
) -> ConstraintSet<'db> {
match (self.subclass_of, other.subclass_of) {

View File

@@ -273,7 +273,7 @@ impl<'db> TupleType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -292,7 +292,7 @@ impl<'db> TupleType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -309,7 +309,7 @@ impl<'db> TupleType<'db> {
self,
db: &'db dyn Db,
other: Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
self.tuple(db)
@@ -502,7 +502,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Tuple<Type<'db>>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -589,7 +589,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
ConstraintSet::from(self.0.len() == other.0.len()).and(db, || {
@@ -908,7 +908,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Tuple<Type<'db>>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1111,7 +1111,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
self.variable
@@ -1340,7 +1340,7 @@ impl<'db> Tuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -1369,7 +1369,7 @@ impl<'db> Tuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
match (self, other) {
@@ -1389,7 +1389,7 @@ impl<'db> Tuple<Type<'db>> {
&self,
db: &'db dyn Db,
other: &Self,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db> {
@@ -1409,7 +1409,7 @@ impl<'db> Tuple<Type<'db>> {
db: &'db dyn Db,
a: impl IntoIterator<Item = &'s Type<'db>>,
b: impl IntoIterator<Item = &'s Type<'db>>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
) -> ConstraintSet<'db>

View File

@@ -129,7 +129,7 @@ impl<'db> TypedDictType<'db> {
self,
db: &'db dyn Db,
target: TypedDictType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
relation: TypeRelation<'db>,
relation_visitor: &HasRelationToVisitor<'db>,
disjointness_visitor: &IsDisjointVisitor<'db>,
@@ -314,7 +314,7 @@ impl<'db> TypedDictType<'db> {
self,
db: &'db dyn Db,
other: TypedDictType<'db>,
inferable: InferableTypeVars<'_, 'db>,
inferable: &InferableTypeVars<'db>,
visitor: &IsEquivalentVisitor<'db>,
) -> ConstraintSet<'db> {
// TODO: `closed` and `extra_items` support will go here. Until then we don't look at the