mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-28 10:50:26 +00:00
[ty] Add (unused) inferable parameter to type property methods (#20865)
A large part of the diff on #20677 just involves threading a new `inferable` parameter through all of the type property methods. In the interests of making that PR easier to review, I've pulled that bit out into here, so that it can be reviewed in isolation. This should be a pure refactoring, with no logic changes or behavioral changes.
This commit is contained in:
parent
85ff4f3eef
commit
8817ea5c84
11 changed files with 580 additions and 185 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -26,7 +26,9 @@ use crate::types::enums::is_enum_class;
|
||||||
use crate::types::function::{
|
use crate::types::function::{
|
||||||
DataclassTransformerParams, FunctionDecorators, FunctionType, KnownFunction, OverloadLiteral,
|
DataclassTransformerParams, FunctionDecorators, FunctionType, KnownFunction, OverloadLiteral,
|
||||||
};
|
};
|
||||||
use crate::types::generics::{Specialization, SpecializationBuilder, SpecializationError};
|
use crate::types::generics::{
|
||||||
|
InferableTypeVars, Specialization, SpecializationBuilder, SpecializationError,
|
||||||
|
};
|
||||||
use crate::types::signatures::{Parameter, ParameterForm, ParameterKind, Parameters};
|
use crate::types::signatures::{Parameter, ParameterForm, ParameterKind, Parameters};
|
||||||
use crate::types::tuple::{TupleLength, TupleType};
|
use crate::types::tuple::{TupleLength, TupleType};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
|
|
@ -597,7 +599,8 @@ impl<'db> Bindings<'db> {
|
||||||
Type::FunctionLiteral(function_type) => match function_type.known(db) {
|
Type::FunctionLiteral(function_type) => match function_type.known(db) {
|
||||||
Some(KnownFunction::IsEquivalentTo) => {
|
Some(KnownFunction::IsEquivalentTo) => {
|
||||||
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
||||||
let constraints = ty_a.when_equivalent_to(db, *ty_b);
|
let constraints =
|
||||||
|
ty_a.when_equivalent_to(db, *ty_b, InferableTypeVars::None);
|
||||||
let tracked = TrackedConstraintSet::new(db, constraints);
|
let tracked = TrackedConstraintSet::new(db, constraints);
|
||||||
overload.set_return_type(Type::KnownInstance(
|
overload.set_return_type(Type::KnownInstance(
|
||||||
KnownInstanceType::ConstraintSet(tracked),
|
KnownInstanceType::ConstraintSet(tracked),
|
||||||
|
|
@ -607,7 +610,8 @@ impl<'db> Bindings<'db> {
|
||||||
|
|
||||||
Some(KnownFunction::IsSubtypeOf) => {
|
Some(KnownFunction::IsSubtypeOf) => {
|
||||||
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
||||||
let constraints = ty_a.when_subtype_of(db, *ty_b);
|
let constraints =
|
||||||
|
ty_a.when_subtype_of(db, *ty_b, InferableTypeVars::None);
|
||||||
let tracked = TrackedConstraintSet::new(db, constraints);
|
let tracked = TrackedConstraintSet::new(db, constraints);
|
||||||
overload.set_return_type(Type::KnownInstance(
|
overload.set_return_type(Type::KnownInstance(
|
||||||
KnownInstanceType::ConstraintSet(tracked),
|
KnownInstanceType::ConstraintSet(tracked),
|
||||||
|
|
@ -617,7 +621,8 @@ impl<'db> Bindings<'db> {
|
||||||
|
|
||||||
Some(KnownFunction::IsAssignableTo) => {
|
Some(KnownFunction::IsAssignableTo) => {
|
||||||
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
||||||
let constraints = ty_a.when_assignable_to(db, *ty_b);
|
let constraints =
|
||||||
|
ty_a.when_assignable_to(db, *ty_b, InferableTypeVars::None);
|
||||||
let tracked = TrackedConstraintSet::new(db, constraints);
|
let tracked = TrackedConstraintSet::new(db, constraints);
|
||||||
overload.set_return_type(Type::KnownInstance(
|
overload.set_return_type(Type::KnownInstance(
|
||||||
KnownInstanceType::ConstraintSet(tracked),
|
KnownInstanceType::ConstraintSet(tracked),
|
||||||
|
|
@ -627,7 +632,8 @@ impl<'db> Bindings<'db> {
|
||||||
|
|
||||||
Some(KnownFunction::IsDisjointFrom) => {
|
Some(KnownFunction::IsDisjointFrom) => {
|
||||||
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
if let [Some(ty_a), Some(ty_b)] = overload.parameter_types() {
|
||||||
let constraints = ty_a.when_disjoint_from(db, *ty_b);
|
let constraints =
|
||||||
|
ty_a.when_disjoint_from(db, *ty_b, InferableTypeVars::None);
|
||||||
let tracked = TrackedConstraintSet::new(db, constraints);
|
let tracked = TrackedConstraintSet::new(db, constraints);
|
||||||
overload.set_return_type(Type::KnownInstance(
|
overload.set_return_type(Type::KnownInstance(
|
||||||
KnownInstanceType::ConstraintSet(tracked),
|
KnownInstanceType::ConstraintSet(tracked),
|
||||||
|
|
@ -1407,7 +1413,10 @@ impl<'db> CallableBinding<'db> {
|
||||||
let parameter_type = overload.signature.parameters()[*parameter_index]
|
let parameter_type = overload.signature.parameters()[*parameter_index]
|
||||||
.annotated_type()
|
.annotated_type()
|
||||||
.unwrap_or(Type::unknown());
|
.unwrap_or(Type::unknown());
|
||||||
if argument_type.is_assignable_to(db, parameter_type) {
|
if argument_type
|
||||||
|
.when_assignable_to(db, parameter_type, overload.inferable_typevars)
|
||||||
|
.is_always_satisfied()
|
||||||
|
{
|
||||||
is_argument_assignable_to_any_overload = true;
|
is_argument_assignable_to_any_overload = true;
|
||||||
break 'overload;
|
break 'overload;
|
||||||
}
|
}
|
||||||
|
|
@ -1633,7 +1642,14 @@ impl<'db> CallableBinding<'db> {
|
||||||
.unwrap_or(Type::unknown());
|
.unwrap_or(Type::unknown());
|
||||||
let first_parameter_type = &mut first_parameter_types[parameter_index];
|
let first_parameter_type = &mut first_parameter_types[parameter_index];
|
||||||
if let Some(first_parameter_type) = first_parameter_type {
|
if let Some(first_parameter_type) = first_parameter_type {
|
||||||
if !first_parameter_type.is_equivalent_to(db, current_parameter_type) {
|
if !first_parameter_type
|
||||||
|
.when_equivalent_to(
|
||||||
|
db,
|
||||||
|
current_parameter_type,
|
||||||
|
overload.inferable_typevars,
|
||||||
|
)
|
||||||
|
.is_always_satisfied()
|
||||||
|
{
|
||||||
participating_parameter_indexes.insert(parameter_index);
|
participating_parameter_indexes.insert(parameter_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1750,7 +1766,12 @@ impl<'db> CallableBinding<'db> {
|
||||||
matching_overloads.all(|(_, overload)| {
|
matching_overloads.all(|(_, overload)| {
|
||||||
overload
|
overload
|
||||||
.return_type()
|
.return_type()
|
||||||
.is_equivalent_to(db, first_overload_return_type)
|
.when_equivalent_to(
|
||||||
|
db,
|
||||||
|
first_overload_return_type,
|
||||||
|
overload.inferable_typevars,
|
||||||
|
)
|
||||||
|
.is_always_satisfied()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// No matching overload
|
// No matching overload
|
||||||
|
|
@ -2461,6 +2482,7 @@ struct ArgumentTypeChecker<'a, 'db> {
|
||||||
call_expression_tcx: &'a TypeContext<'db>,
|
call_expression_tcx: &'a TypeContext<'db>,
|
||||||
errors: &'a mut Vec<BindingError<'db>>,
|
errors: &'a mut Vec<BindingError<'db>>,
|
||||||
|
|
||||||
|
inferable_typevars: InferableTypeVars<'db, 'db>,
|
||||||
specialization: Option<Specialization<'db>>,
|
specialization: Option<Specialization<'db>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2482,6 +2504,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
parameter_tys,
|
parameter_tys,
|
||||||
call_expression_tcx,
|
call_expression_tcx,
|
||||||
errors,
|
errors,
|
||||||
|
inferable_typevars: InferableTypeVars::None,
|
||||||
specialization: None,
|
specialization: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2514,11 +2537,12 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_specialization(&mut self) {
|
fn infer_specialization(&mut self) {
|
||||||
if self.signature.generic_context.is_none() {
|
let Some(generic_context) = self.signature.generic_context else {
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut builder = SpecializationBuilder::new(self.db);
|
// TODO: Use the list of inferable typevars from the generic context of the callable.
|
||||||
|
let mut builder = SpecializationBuilder::new(self.db, self.inferable_typevars);
|
||||||
|
|
||||||
// Note that we infer the annotated type _before_ the arguments if this call is part of
|
// Note that we infer the annotated type _before_ the arguments if this call is part of
|
||||||
// an annotated assignment, to closer match the order of any unions written in the type
|
// an annotated assignment, to closer match the order of any unions written in the type
|
||||||
|
|
@ -2563,10 +2587,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.specialization = self
|
self.specialization = Some(builder.build(generic_context, *self.call_expression_tcx));
|
||||||
.signature
|
|
||||||
.generic_context
|
|
||||||
.map(|gc| builder.build(gc, *self.call_expression_tcx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_argument_type(
|
fn check_argument_type(
|
||||||
|
|
@ -2590,7 +2611,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
// constraint set that we get from this assignability check, instead of inferring and
|
// constraint set that we get from this assignability check, instead of inferring and
|
||||||
// building them in an earlier separate step.
|
// building them in an earlier separate step.
|
||||||
if argument_type
|
if argument_type
|
||||||
.when_assignable_to(self.db, expected_ty)
|
.when_assignable_to(self.db, expected_ty, self.inferable_typevars)
|
||||||
.is_never_satisfied()
|
.is_never_satisfied()
|
||||||
{
|
{
|
||||||
let positional = matches!(argument, Argument::Positional | Argument::Synthetic)
|
let positional = matches!(argument, Argument::Positional | Argument::Synthetic)
|
||||||
|
|
@ -2719,7 +2740,14 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !key_type.is_assignable_to(self.db, KnownClass::Str.to_instance(self.db)) {
|
if !key_type
|
||||||
|
.when_assignable_to(
|
||||||
|
self.db,
|
||||||
|
KnownClass::Str.to_instance(self.db),
|
||||||
|
self.inferable_typevars,
|
||||||
|
)
|
||||||
|
.is_always_satisfied()
|
||||||
|
{
|
||||||
self.errors.push(BindingError::InvalidKeyType {
|
self.errors.push(BindingError::InvalidKeyType {
|
||||||
argument_index: adjusted_argument_index,
|
argument_index: adjusted_argument_index,
|
||||||
provided_ty: key_type,
|
provided_ty: key_type,
|
||||||
|
|
@ -2754,8 +2782,8 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self) -> Option<Specialization<'db>> {
|
fn finish(self) -> (InferableTypeVars<'db, 'db>, Option<Specialization<'db>>) {
|
||||||
self.specialization
|
(self.inferable_typevars, self.specialization)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2819,6 +2847,9 @@ pub(crate) struct Binding<'db> {
|
||||||
/// Return type of the call.
|
/// Return type of the call.
|
||||||
return_ty: Type<'db>,
|
return_ty: Type<'db>,
|
||||||
|
|
||||||
|
/// The inferable typevars in this signature.
|
||||||
|
inferable_typevars: InferableTypeVars<'db, 'db>,
|
||||||
|
|
||||||
/// The specialization that was inferred from the argument types, if the callable is generic.
|
/// The specialization that was inferred from the argument types, if the callable is generic.
|
||||||
specialization: Option<Specialization<'db>>,
|
specialization: Option<Specialization<'db>>,
|
||||||
|
|
||||||
|
|
@ -2845,6 +2876,7 @@ impl<'db> Binding<'db> {
|
||||||
callable_type: signature_type,
|
callable_type: signature_type,
|
||||||
signature_type,
|
signature_type,
|
||||||
return_ty: Type::unknown(),
|
return_ty: Type::unknown(),
|
||||||
|
inferable_typevars: InferableTypeVars::None,
|
||||||
specialization: None,
|
specialization: None,
|
||||||
argument_matches: Box::from([]),
|
argument_matches: Box::from([]),
|
||||||
variadic_argument_matched_to_variadic_parameter: false,
|
variadic_argument_matched_to_variadic_parameter: false,
|
||||||
|
|
@ -2916,7 +2948,7 @@ impl<'db> Binding<'db> {
|
||||||
checker.infer_specialization();
|
checker.infer_specialization();
|
||||||
|
|
||||||
checker.check_argument_types();
|
checker.check_argument_types();
|
||||||
self.specialization = checker.finish();
|
(self.inferable_typevars, self.specialization) = checker.finish();
|
||||||
if let Some(specialization) = self.specialization {
|
if let Some(specialization) = self.specialization {
|
||||||
self.return_ty = self.return_ty.apply_specialization(db, specialization);
|
self.return_ty = self.return_ty.apply_specialization(db, specialization);
|
||||||
}
|
}
|
||||||
|
|
@ -3010,6 +3042,7 @@ impl<'db> Binding<'db> {
|
||||||
fn snapshot(&self) -> BindingSnapshot<'db> {
|
fn snapshot(&self) -> BindingSnapshot<'db> {
|
||||||
BindingSnapshot {
|
BindingSnapshot {
|
||||||
return_ty: self.return_ty,
|
return_ty: self.return_ty,
|
||||||
|
inferable_typevars: self.inferable_typevars,
|
||||||
specialization: self.specialization,
|
specialization: self.specialization,
|
||||||
argument_matches: self.argument_matches.clone(),
|
argument_matches: self.argument_matches.clone(),
|
||||||
parameter_tys: self.parameter_tys.clone(),
|
parameter_tys: self.parameter_tys.clone(),
|
||||||
|
|
@ -3020,6 +3053,7 @@ impl<'db> Binding<'db> {
|
||||||
fn restore(&mut self, snapshot: BindingSnapshot<'db>) {
|
fn restore(&mut self, snapshot: BindingSnapshot<'db>) {
|
||||||
let BindingSnapshot {
|
let BindingSnapshot {
|
||||||
return_ty,
|
return_ty,
|
||||||
|
inferable_typevars,
|
||||||
specialization,
|
specialization,
|
||||||
argument_matches,
|
argument_matches,
|
||||||
parameter_tys,
|
parameter_tys,
|
||||||
|
|
@ -3027,6 +3061,7 @@ impl<'db> Binding<'db> {
|
||||||
} = snapshot;
|
} = snapshot;
|
||||||
|
|
||||||
self.return_ty = return_ty;
|
self.return_ty = return_ty;
|
||||||
|
self.inferable_typevars = inferable_typevars;
|
||||||
self.specialization = specialization;
|
self.specialization = specialization;
|
||||||
self.argument_matches = argument_matches;
|
self.argument_matches = argument_matches;
|
||||||
self.parameter_tys = parameter_tys;
|
self.parameter_tys = parameter_tys;
|
||||||
|
|
@ -3046,6 +3081,7 @@ impl<'db> Binding<'db> {
|
||||||
/// Resets the state of this binding to its initial state.
|
/// Resets the state of this binding to its initial state.
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
self.return_ty = Type::unknown();
|
self.return_ty = Type::unknown();
|
||||||
|
self.inferable_typevars = InferableTypeVars::None;
|
||||||
self.specialization = None;
|
self.specialization = None;
|
||||||
self.argument_matches = Box::from([]);
|
self.argument_matches = Box::from([]);
|
||||||
self.parameter_tys = Box::from([]);
|
self.parameter_tys = Box::from([]);
|
||||||
|
|
@ -3056,6 +3092,7 @@ impl<'db> Binding<'db> {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct BindingSnapshot<'db> {
|
struct BindingSnapshot<'db> {
|
||||||
return_ty: Type<'db>,
|
return_ty: Type<'db>,
|
||||||
|
inferable_typevars: InferableTypeVars<'db, 'db>,
|
||||||
specialization: Option<Specialization<'db>>,
|
specialization: Option<Specialization<'db>>,
|
||||||
argument_matches: Box<[MatchedArgument<'db>]>,
|
argument_matches: Box<[MatchedArgument<'db>]>,
|
||||||
parameter_tys: Box<[Option<Type<'db>>]>,
|
parameter_tys: Box<[Option<Type<'db>>]>,
|
||||||
|
|
@ -3095,6 +3132,7 @@ impl<'db> CallableBindingSnapshot<'db> {
|
||||||
|
|
||||||
// ... and update the snapshot with the current state of the binding.
|
// ... and update the snapshot with the current state of the binding.
|
||||||
snapshot.return_ty = binding.return_ty;
|
snapshot.return_ty = binding.return_ty;
|
||||||
|
snapshot.inferable_typevars = binding.inferable_typevars;
|
||||||
snapshot.specialization = binding.specialization;
|
snapshot.specialization = binding.specialization;
|
||||||
snapshot
|
snapshot
|
||||||
.argument_matches
|
.argument_matches
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ use crate::types::diagnostic::INVALID_TYPE_ALIAS_TYPE;
|
||||||
use crate::types::enums::enum_metadata;
|
use crate::types::enums::enum_metadata;
|
||||||
use crate::types::function::{DataclassTransformerParams, KnownFunction};
|
use crate::types::function::{DataclassTransformerParams, KnownFunction};
|
||||||
use crate::types::generics::{
|
use crate::types::generics::{
|
||||||
GenericContext, Specialization, walk_generic_context, walk_specialization,
|
GenericContext, InferableTypeVars, Specialization, walk_generic_context, walk_specialization,
|
||||||
};
|
};
|
||||||
use crate::types::infer::nearest_enclosing_class;
|
use crate::types::infer::nearest_enclosing_class;
|
||||||
use crate::types::member::{Member, class_member};
|
use crate::types::member::{Member, class_member};
|
||||||
|
|
@ -540,17 +540,20 @@ impl<'db> ClassType<'db> {
|
||||||
|
|
||||||
/// Return `true` if `other` is present in this class's MRO.
|
/// 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 {
|
pub(super) fn is_subclass_of(self, db: &'db dyn Db, other: ClassType<'db>) -> bool {
|
||||||
self.when_subclass_of(db, other).is_always_satisfied()
|
self.when_subclass_of(db, other, InferableTypeVars::None)
|
||||||
|
.is_always_satisfied()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn when_subclass_of(
|
pub(super) fn when_subclass_of(
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: ClassType<'db>,
|
other: ClassType<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
self.has_relation_to_impl(
|
self.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other,
|
other,
|
||||||
|
inferable,
|
||||||
TypeRelation::Subtyping,
|
TypeRelation::Subtyping,
|
||||||
&HasRelationToVisitor::default(),
|
&HasRelationToVisitor::default(),
|
||||||
&IsDisjointVisitor::default(),
|
&IsDisjointVisitor::default(),
|
||||||
|
|
@ -561,6 +564,7 @@ impl<'db> ClassType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -586,6 +590,7 @@ impl<'db> ClassType<'db> {
|
||||||
base.specialization(db).has_relation_to_impl(
|
base.specialization(db).has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.specialization(db),
|
other.specialization(db),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -610,6 +615,7 @@ impl<'db> ClassType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: ClassType<'db>,
|
other: ClassType<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
if self == other {
|
if self == other {
|
||||||
|
|
@ -628,6 +634,7 @@ impl<'db> ClassType<'db> {
|
||||||
this.specialization(db).is_equivalent_to_impl(
|
this.specialization(db).is_equivalent_to_impl(
|
||||||
db,
|
db,
|
||||||
other.specialization(db),
|
other.specialization(db),
|
||||||
|
inferable,
|
||||||
visitor,
|
visitor,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ use crate::types::diagnostic::{
|
||||||
report_runtime_check_against_non_runtime_checkable_protocol,
|
report_runtime_check_against_non_runtime_checkable_protocol,
|
||||||
};
|
};
|
||||||
use crate::types::display::DisplaySettings;
|
use crate::types::display::DisplaySettings;
|
||||||
use crate::types::generics::GenericContext;
|
use crate::types::generics::{GenericContext, InferableTypeVars};
|
||||||
use crate::types::ide_support::all_members;
|
use crate::types::ide_support::all_members;
|
||||||
use crate::types::narrow::ClassInfoConstraintFunction;
|
use crate::types::narrow::ClassInfoConstraintFunction;
|
||||||
use crate::types::signatures::{CallableSignature, Signature};
|
use crate::types::signatures::{CallableSignature, Signature};
|
||||||
|
|
@ -81,9 +81,9 @@ use crate::types::visitor::any_over_type;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase,
|
ApplyTypeMappingVisitor, BoundMethodType, BoundTypeVarInstance, CallableType, ClassBase,
|
||||||
ClassLiteral, ClassType, DeprecatedInstance, DynamicType, FindLegacyTypeVarsVisitor,
|
ClassLiteral, ClassType, DeprecatedInstance, DynamicType, FindLegacyTypeVarsVisitor,
|
||||||
HasRelationToVisitor, IsEquivalentVisitor, KnownClass, KnownInstanceType, NormalizedVisitor,
|
HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor, KnownClass, KnownInstanceType,
|
||||||
SpecialFormType, TrackedConstraintSet, Truthiness, Type, TypeContext, TypeMapping,
|
NormalizedVisitor, SpecialFormType, TrackedConstraintSet, Truthiness, Type, TypeContext,
|
||||||
TypeRelation, UnionBuilder, binding_type, todo_type, walk_signature,
|
TypeMapping, TypeRelation, UnionBuilder, binding_type, todo_type, walk_signature,
|
||||||
};
|
};
|
||||||
use crate::{Db, FxOrderSet, ModuleName, resolve_module};
|
use crate::{Db, FxOrderSet, ModuleName, resolve_module};
|
||||||
|
|
||||||
|
|
@ -959,46 +959,42 @@ impl<'db> FunctionType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
match relation {
|
|
||||||
TypeRelation::Subtyping | TypeRelation::Redundancy => {
|
|
||||||
ConstraintSet::from(self.is_subtype_of(db, other))
|
|
||||||
}
|
|
||||||
TypeRelation::Assignability => ConstraintSet::from(self.is_assignable_to(db, other)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_subtype_of(self, db: &'db dyn Db, other: Self) -> bool {
|
|
||||||
// A function type is the subtype of itself, and not of any other function type. However,
|
// A function type is the subtype of itself, and not of any other function type. However,
|
||||||
// our representation of a function type includes any specialization that should be applied
|
// our representation of a function type includes any specialization that should be applied
|
||||||
// to the signature. Different specializations of the same function type are only subtypes
|
// to the signature. Different specializations of the same function type are only subtypes
|
||||||
// of each other if they result in subtype signatures.
|
// of each other if they result in subtype signatures.
|
||||||
if self.normalized(db) == other.normalized(db) {
|
if matches!(relation, TypeRelation::Subtyping | TypeRelation::Redundancy)
|
||||||
return true;
|
&& self.normalized(db) == other.normalized(db)
|
||||||
}
|
{
|
||||||
if self.literal(db) != other.literal(db) {
|
return ConstraintSet::from(true);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let self_signature = self.signature(db);
|
|
||||||
let other_signature = other.signature(db);
|
|
||||||
self_signature.is_subtype_of(db, other_signature)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_assignable_to(self, db: &'db dyn Db, other: Self) -> bool {
|
if self.literal(db) != other.literal(db) {
|
||||||
// A function type is assignable to itself, and not to any other function type. However,
|
return ConstraintSet::from(false);
|
||||||
// our representation of a function type includes any specialization that should be applied
|
}
|
||||||
// to the signature. Different specializations of the same function type are only
|
|
||||||
// assignable to each other if they result in assignable signatures.
|
let self_signature = self.signature(db);
|
||||||
self.literal(db) == other.literal(db)
|
let other_signature = other.signature(db);
|
||||||
&& self.signature(db).is_assignable_to(db, other.signature(db))
|
self_signature.has_relation_to_impl(
|
||||||
|
db,
|
||||||
|
other_signature,
|
||||||
|
inferable,
|
||||||
|
relation,
|
||||||
|
relation_visitor,
|
||||||
|
disjointness_visitor,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_equivalent_to_impl(
|
pub(crate) fn is_equivalent_to_impl(
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
if self.normalized(db) == other.normalized(db) {
|
if self.normalized(db) == other.normalized(db) {
|
||||||
|
|
@ -1009,7 +1005,7 @@ impl<'db> FunctionType<'db> {
|
||||||
}
|
}
|
||||||
let self_signature = self.signature(db);
|
let self_signature = self.signature(db);
|
||||||
let other_signature = other.signature(db);
|
let other_signature = other.signature(db);
|
||||||
self_signature.is_equivalent_to_impl(db, other_signature, visitor)
|
self_signature.is_equivalent_to_impl(db, other_signature, inferable, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn find_legacy_typevars_impl(
|
pub(crate) fn find_legacy_typevars_impl(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::types::constraints::ConstraintSet;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruff_python_ast as ast;
|
use ruff_python_ast as ast;
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::semantic_index::scope::{FileScopeId, NodeWithScopeKind, ScopeId};
|
||||||
use crate::semantic_index::{SemanticIndex, semantic_index};
|
use crate::semantic_index::{SemanticIndex, semantic_index};
|
||||||
use crate::types::class::ClassType;
|
use crate::types::class::ClassType;
|
||||||
use crate::types::class_base::ClassBase;
|
use crate::types::class_base::ClassBase;
|
||||||
|
use crate::types::constraints::ConstraintSet;
|
||||||
use crate::types::infer::infer_definition_types;
|
use crate::types::infer::infer_definition_types;
|
||||||
use crate::types::instance::{Protocol, ProtocolInstanceType};
|
use crate::types::instance::{Protocol, ProtocolInstanceType};
|
||||||
use crate::types::signatures::{Parameter, Parameters, Signature};
|
use crate::types::signatures::{Parameter, Parameters, Signature};
|
||||||
|
|
@ -140,6 +141,16 @@ pub(crate) fn typing_self<'db>(
|
||||||
.map(typevar_to_type)
|
.map(typevar_to_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub(crate) enum InferableTypeVars<'a, 'db> {
|
||||||
|
None,
|
||||||
|
// TODO: This variant isn't used, and only exists so that we can include the 'a and 'db in the
|
||||||
|
// type definition. They will be used soon when we start creating real InferableTypeVars
|
||||||
|
// instances.
|
||||||
|
#[expect(unused)]
|
||||||
|
Unused(PhantomData<&'a &'db ()>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, get_size2::GetSize)]
|
||||||
pub struct GenericContextTypeVar<'db> {
|
pub struct GenericContextTypeVar<'db> {
|
||||||
bound_typevar: BoundTypeVarInstance<'db>,
|
bound_typevar: BoundTypeVarInstance<'db>,
|
||||||
|
|
@ -593,12 +604,14 @@ pub(super) fn walk_specialization<'db, V: super::visitor::TypeVisitor<'db> + ?Si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::too_many_arguments)]
|
||||||
fn is_subtype_in_invariant_position<'db>(
|
fn is_subtype_in_invariant_position<'db>(
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
derived_type: &Type<'db>,
|
derived_type: &Type<'db>,
|
||||||
derived_materialization: MaterializationKind,
|
derived_materialization: MaterializationKind,
|
||||||
base_type: &Type<'db>,
|
base_type: &Type<'db>,
|
||||||
base_materialization: MaterializationKind,
|
base_materialization: MaterializationKind,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
|
|
@ -623,6 +636,7 @@ fn is_subtype_in_invariant_position<'db>(
|
||||||
derived.has_relation_to_impl(
|
derived.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
base,
|
base,
|
||||||
|
inferable,
|
||||||
TypeRelation::Subtyping,
|
TypeRelation::Subtyping,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -675,6 +689,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
derived_materialization: Option<MaterializationKind>,
|
derived_materialization: Option<MaterializationKind>,
|
||||||
base_type: &Type<'db>,
|
base_type: &Type<'db>,
|
||||||
base_materialization: Option<MaterializationKind>,
|
base_materialization: Option<MaterializationKind>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -688,6 +703,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
derived_mat,
|
derived_mat,
|
||||||
base_type,
|
base_type,
|
||||||
base_mat,
|
base_mat,
|
||||||
|
inferable,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
),
|
),
|
||||||
|
|
@ -707,6 +723,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
.has_relation_to_impl(
|
.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*base_type,
|
*base_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -715,6 +732,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
base_type.has_relation_to_impl(
|
base_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*derived_type,
|
*derived_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -728,6 +746,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
MaterializationKind::Top,
|
MaterializationKind::Top,
|
||||||
base_type,
|
base_type,
|
||||||
base_mat,
|
base_mat,
|
||||||
|
inferable,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -739,6 +758,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
derived_mat,
|
derived_mat,
|
||||||
base_type,
|
base_type,
|
||||||
MaterializationKind::Bottom,
|
MaterializationKind::Bottom,
|
||||||
|
inferable,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -750,6 +770,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
MaterializationKind::Bottom,
|
MaterializationKind::Bottom,
|
||||||
base_type,
|
base_type,
|
||||||
base_mat,
|
base_mat,
|
||||||
|
inferable,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
),
|
),
|
||||||
|
|
@ -759,6 +780,7 @@ fn has_relation_in_invariant_position<'db>(
|
||||||
derived_mat,
|
derived_mat,
|
||||||
base_type,
|
base_type,
|
||||||
MaterializationKind::Top,
|
MaterializationKind::Top,
|
||||||
|
inferable,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
),
|
),
|
||||||
|
|
@ -1002,6 +1024,7 @@ impl<'db> Specialization<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -1016,6 +1039,7 @@ impl<'db> Specialization<'db> {
|
||||||
return self_tuple.has_relation_to_impl(
|
return self_tuple.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_tuple,
|
other_tuple,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1043,6 +1067,7 @@ impl<'db> Specialization<'db> {
|
||||||
self_materialization_kind,
|
self_materialization_kind,
|
||||||
other_type,
|
other_type,
|
||||||
other_materialization_kind,
|
other_materialization_kind,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1050,6 +1075,7 @@ impl<'db> Specialization<'db> {
|
||||||
TypeVarVariance::Covariant => self_type.has_relation_to_impl(
|
TypeVarVariance::Covariant => self_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*other_type,
|
*other_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1057,6 +1083,7 @@ impl<'db> Specialization<'db> {
|
||||||
TypeVarVariance::Contravariant => other_type.has_relation_to_impl(
|
TypeVarVariance::Contravariant => other_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*self_type,
|
*self_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1075,6 +1102,7 @@ impl<'db> Specialization<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Specialization<'db>,
|
other: Specialization<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
if self.materialization_kind(db) != other.materialization_kind(db) {
|
if self.materialization_kind(db) != other.materialization_kind(db) {
|
||||||
|
|
@ -1100,7 +1128,7 @@ impl<'db> Specialization<'db> {
|
||||||
TypeVarVariance::Invariant
|
TypeVarVariance::Invariant
|
||||||
| TypeVarVariance::Covariant
|
| TypeVarVariance::Covariant
|
||||||
| TypeVarVariance::Contravariant => {
|
| TypeVarVariance::Contravariant => {
|
||||||
self_type.is_equivalent_to_impl(db, *other_type, visitor)
|
self_type.is_equivalent_to_impl(db, *other_type, inferable, visitor)
|
||||||
}
|
}
|
||||||
TypeVarVariance::Bivariant => ConstraintSet::from(true),
|
TypeVarVariance::Bivariant => ConstraintSet::from(true),
|
||||||
};
|
};
|
||||||
|
|
@ -1113,7 +1141,8 @@ impl<'db> Specialization<'db> {
|
||||||
(Some(_), None) | (None, Some(_)) => return ConstraintSet::from(false),
|
(Some(_), None) | (None, Some(_)) => return ConstraintSet::from(false),
|
||||||
(None, None) => {}
|
(None, None) => {}
|
||||||
(Some(self_tuple), Some(other_tuple)) => {
|
(Some(self_tuple), Some(other_tuple)) => {
|
||||||
let compatible = self_tuple.is_equivalent_to_impl(db, other_tuple, visitor);
|
let compatible =
|
||||||
|
self_tuple.is_equivalent_to_impl(db, other_tuple, inferable, visitor);
|
||||||
if result.intersect(db, compatible).is_never_satisfied() {
|
if result.intersect(db, compatible).is_never_satisfied() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -1168,13 +1197,15 @@ impl<'db> PartialSpecialization<'_, 'db> {
|
||||||
/// specialization of a generic function.
|
/// specialization of a generic function.
|
||||||
pub(crate) struct SpecializationBuilder<'db> {
|
pub(crate) struct SpecializationBuilder<'db> {
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
|
inferable: InferableTypeVars<'db, 'db>,
|
||||||
types: FxHashMap<BoundTypeVarIdentity<'db>, Type<'db>>,
|
types: FxHashMap<BoundTypeVarIdentity<'db>, Type<'db>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'db> SpecializationBuilder<'db> {
|
impl<'db> SpecializationBuilder<'db> {
|
||||||
pub(crate) fn new(db: &'db dyn Db) -> Self {
|
pub(crate) fn new(db: &'db dyn Db, inferable: InferableTypeVars<'db, 'db>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
db,
|
db,
|
||||||
|
inferable,
|
||||||
types: FxHashMap::default(),
|
types: FxHashMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1244,14 +1275,16 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
// without specializing `T` to `None`.
|
// without specializing `T` to `None`.
|
||||||
if !matches!(formal, Type::ProtocolInstance(_))
|
if !matches!(formal, Type::ProtocolInstance(_))
|
||||||
&& !actual.is_never()
|
&& !actual.is_never()
|
||||||
&& actual.is_subtype_of(self.db, formal)
|
&& actual
|
||||||
|
.when_subtype_of(self.db, formal, self.inferable)
|
||||||
|
.is_always_satisfied()
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// For example, if `formal` is `list[T]` and `actual` is `list[int] | None`, we want to specialize `T` to `int`.
|
// For example, if `formal` is `list[T]` and `actual` is `list[int] | None`, we want to specialize `T` to `int`.
|
||||||
// So, here we remove the union elements that are not related to `formal`.
|
// So, here we remove the union elements that are not related to `formal`.
|
||||||
actual = actual.filter_disjoint_elements(self.db, formal);
|
actual = actual.filter_disjoint_elements(self.db, formal, self.inferable);
|
||||||
|
|
||||||
match (formal, actual) {
|
match (formal, actual) {
|
||||||
// TODO: We haven't implemented a full unification solver yet. If typevars appear in
|
// TODO: We haven't implemented a full unification solver yet. If typevars appear in
|
||||||
|
|
@ -1324,7 +1357,10 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
(Type::TypeVar(bound_typevar), ty) | (ty, Type::TypeVar(bound_typevar)) => {
|
(Type::TypeVar(bound_typevar), ty) | (ty, Type::TypeVar(bound_typevar)) => {
|
||||||
match bound_typevar.typevar(self.db).bound_or_constraints(self.db) {
|
match bound_typevar.typevar(self.db).bound_or_constraints(self.db) {
|
||||||
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
|
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
|
||||||
if !ty.is_assignable_to(self.db, bound) {
|
if !ty
|
||||||
|
.when_assignable_to(self.db, bound, self.inferable)
|
||||||
|
.is_always_satisfied()
|
||||||
|
{
|
||||||
return Err(SpecializationError::MismatchedBound {
|
return Err(SpecializationError::MismatchedBound {
|
||||||
bound_typevar,
|
bound_typevar,
|
||||||
argument: ty,
|
argument: ty,
|
||||||
|
|
@ -1334,7 +1370,10 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
}
|
}
|
||||||
Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
|
Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
|
||||||
for constraint in constraints.elements(self.db) {
|
for constraint in constraints.elements(self.db) {
|
||||||
if ty.is_assignable_to(self.db, *constraint) {
|
if ty
|
||||||
|
.when_assignable_to(self.db, *constraint, self.inferable)
|
||||||
|
.is_always_satisfied()
|
||||||
|
{
|
||||||
self.add_type_mapping(bound_typevar, *constraint);
|
self.add_type_mapping(bound_typevar, *constraint);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,10 @@ use crate::types::diagnostic::{
|
||||||
use crate::types::function::{
|
use crate::types::function::{
|
||||||
FunctionDecorators, FunctionLiteral, FunctionType, KnownFunction, OverloadLiteral,
|
FunctionDecorators, FunctionLiteral, FunctionType, KnownFunction, OverloadLiteral,
|
||||||
};
|
};
|
||||||
use crate::types::generics::{GenericContext, bind_typevar, enclosing_generic_contexts};
|
use crate::types::generics::{
|
||||||
use crate::types::generics::{LegacyGenericBase, SpecializationBuilder};
|
GenericContext, InferableTypeVars, LegacyGenericBase, SpecializationBuilder, bind_typevar,
|
||||||
|
enclosing_generic_contexts,
|
||||||
|
};
|
||||||
use crate::types::infer::nearest_enclosing_function;
|
use crate::types::infer::nearest_enclosing_function;
|
||||||
use crate::types::instance::SliceLiteral;
|
use crate::types::instance::SliceLiteral;
|
||||||
use crate::types::mro::MroErrorKind;
|
use crate::types::mro::MroErrorKind;
|
||||||
|
|
@ -5964,11 +5966,14 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Use the list of inferable typevars from the generic context of the collection
|
||||||
|
// class.
|
||||||
|
let inferable = InferableTypeVars::None;
|
||||||
let tcx = tcx.map_annotation(|annotation| {
|
let tcx = tcx.map_annotation(|annotation| {
|
||||||
// Remove any union elements of `annotation` that are not related to `collection_ty`.
|
// Remove any union elements of `annotation` that are not related to `collection_ty`.
|
||||||
// e.g. `annotation: list[int] | None => list[int]` if `collection_ty: list`
|
// e.g. `annotation: list[int] | None => list[int]` if `collection_ty: list`
|
||||||
let collection_ty = collection_class.to_instance(self.db());
|
let collection_ty = collection_class.to_instance(self.db());
|
||||||
annotation.filter_disjoint_elements(self.db(), collection_ty)
|
annotation.filter_disjoint_elements(self.db(), collection_ty, inferable)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Extract the annotated type of `T`, if provided.
|
// Extract the annotated type of `T`, if provided.
|
||||||
|
|
@ -5977,7 +5982,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
.map(|specialization| specialization.types(self.db()));
|
.map(|specialization| specialization.types(self.db()));
|
||||||
|
|
||||||
// Create a set of constraints to infer a precise type for `T`.
|
// Create a set of constraints to infer a precise type for `T`.
|
||||||
let mut builder = SpecializationBuilder::new(self.db());
|
let mut builder = SpecializationBuilder::new(self.db(), inferable);
|
||||||
|
|
||||||
match annotated_elt_tys {
|
match annotated_elt_tys {
|
||||||
// The annotated type acts as a constraint for `T`.
|
// The annotated type acts as a constraint for `T`.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::place::PlaceAndQualifiers;
|
||||||
use crate::semantic_index::definition::Definition;
|
use crate::semantic_index::definition::Definition;
|
||||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||||
use crate::types::enums::is_single_member_enum;
|
use crate::types::enums::is_single_member_enum;
|
||||||
use crate::types::generics::walk_specialization;
|
use crate::types::generics::{InferableTypeVars, walk_specialization};
|
||||||
use crate::types::protocol_class::walk_protocol_interface;
|
use crate::types::protocol_class::walk_protocol_interface;
|
||||||
use crate::types::tuple::{TupleSpec, TupleType};
|
use crate::types::tuple::{TupleSpec, TupleType};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
|
|
@ -121,6 +121,7 @@ impl<'db> Type<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
protocol: ProtocolInstanceType<'db>,
|
protocol: ProtocolInstanceType<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -129,6 +130,7 @@ impl<'db> Type<'db> {
|
||||||
self_protocol.interface(db).has_relation_to_impl(
|
self_protocol.interface(db).has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
protocol.interface(db),
|
protocol.interface(db),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -142,6 +144,7 @@ impl<'db> Type<'db> {
|
||||||
member.is_satisfied_by(
|
member.is_satisfied_by(
|
||||||
db,
|
db,
|
||||||
self,
|
self,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -173,6 +176,7 @@ impl<'db> Type<'db> {
|
||||||
type_to_test.has_relation_to_impl(
|
type_to_test.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
Type::NominalInstance(nominal_instance),
|
Type::NominalInstance(nominal_instance),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -360,6 +364,7 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -372,6 +377,7 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
) => tuple1.has_relation_to_impl(
|
) => tuple1.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
tuple2,
|
tuple2,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -379,6 +385,7 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
_ => self.class(db).has_relation_to_impl(
|
_ => self.class(db).has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.class(db),
|
other.class(db),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -390,18 +397,19 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
match (self.0, other.0) {
|
match (self.0, other.0) {
|
||||||
(
|
(
|
||||||
NominalInstanceInner::ExactTuple(tuple1),
|
NominalInstanceInner::ExactTuple(tuple1),
|
||||||
NominalInstanceInner::ExactTuple(tuple2),
|
NominalInstanceInner::ExactTuple(tuple2),
|
||||||
) => tuple1.is_equivalent_to_impl(db, tuple2, visitor),
|
) => tuple1.is_equivalent_to_impl(db, tuple2, inferable, visitor),
|
||||||
(NominalInstanceInner::Object, NominalInstanceInner::Object) => {
|
(NominalInstanceInner::Object, NominalInstanceInner::Object) => {
|
||||||
ConstraintSet::from(true)
|
ConstraintSet::from(true)
|
||||||
}
|
}
|
||||||
(NominalInstanceInner::NonTuple(class1), NominalInstanceInner::NonTuple(class2)) => {
|
(NominalInstanceInner::NonTuple(class1), NominalInstanceInner::NonTuple(class2)) => {
|
||||||
class1.is_equivalent_to_impl(db, class2, visitor)
|
class1.is_equivalent_to_impl(db, class2, inferable, visitor)
|
||||||
}
|
}
|
||||||
_ => ConstraintSet::from(false),
|
_ => ConstraintSet::from(false),
|
||||||
}
|
}
|
||||||
|
|
@ -411,6 +419,7 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
|
|
@ -423,6 +432,7 @@ impl<'db> NominalInstanceType<'db> {
|
||||||
let compatible = self_spec.is_disjoint_from_impl(
|
let compatible = self_spec.is_disjoint_from_impl(
|
||||||
db,
|
db,
|
||||||
&other_spec,
|
&other_spec,
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
);
|
);
|
||||||
|
|
@ -650,6 +660,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
||||||
.satisfies_protocol(
|
.satisfies_protocol(
|
||||||
db,
|
db,
|
||||||
protocol,
|
protocol,
|
||||||
|
InferableTypeVars::None,
|
||||||
TypeRelation::Subtyping,
|
TypeRelation::Subtyping,
|
||||||
&HasRelationToVisitor::default(),
|
&HasRelationToVisitor::default(),
|
||||||
&IsDisjointVisitor::default(),
|
&IsDisjointVisitor::default(),
|
||||||
|
|
@ -708,6 +719,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
_inferable: InferableTypeVars<'_, 'db>,
|
||||||
_visitor: &IsEquivalentVisitor<'db>,
|
_visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
if self == other {
|
if self == other {
|
||||||
|
|
@ -729,6 +741,7 @@ impl<'db> ProtocolInstanceType<'db> {
|
||||||
self,
|
self,
|
||||||
_db: &'db dyn Db,
|
_db: &'db dyn Db,
|
||||||
_other: Self,
|
_other: Self,
|
||||||
|
_inferable: InferableTypeVars<'_, 'db>,
|
||||||
_visitor: &IsDisjointVisitor<'db>,
|
_visitor: &IsDisjointVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
ConstraintSet::from(false)
|
ConstraintSet::from(false)
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use crate::{
|
||||||
constraints::{ConstraintSet, IteratorConstraintsExtension, OptionConstraintsExtension},
|
constraints::{ConstraintSet, IteratorConstraintsExtension, OptionConstraintsExtension},
|
||||||
context::InferContext,
|
context::InferContext,
|
||||||
diagnostic::report_undeclared_protocol_member,
|
diagnostic::report_undeclared_protocol_member,
|
||||||
|
generics::InferableTypeVars,
|
||||||
signatures::{Parameter, Parameters},
|
signatures::{Parameter, Parameters},
|
||||||
todo_type,
|
todo_type,
|
||||||
},
|
},
|
||||||
|
|
@ -235,6 +236,7 @@ impl<'db> ProtocolInterface<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -276,6 +278,7 @@ impl<'db> ProtocolInterface<'db> {
|
||||||
our_type.has_relation_to_impl(
|
our_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
Type::Callable(other_type.bind_self(db)),
|
Type::Callable(other_type.bind_self(db)),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -288,6 +291,7 @@ impl<'db> ProtocolInterface<'db> {
|
||||||
) => our_method.bind_self(db).has_relation_to_impl(
|
) => our_method.bind_self(db).has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_method.bind_self(db),
|
other_method.bind_self(db),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -300,6 +304,7 @@ impl<'db> ProtocolInterface<'db> {
|
||||||
.has_relation_to_impl(
|
.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_type,
|
other_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -308,6 +313,7 @@ impl<'db> ProtocolInterface<'db> {
|
||||||
other_type.has_relation_to_impl(
|
other_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
our_type,
|
our_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -605,6 +611,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Type<'db>,
|
other: Type<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
|
|
@ -613,9 +620,13 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
ProtocolMemberKind::Property(_) | ProtocolMemberKind::Method(_) => {
|
ProtocolMemberKind::Property(_) | ProtocolMemberKind::Method(_) => {
|
||||||
ConstraintSet::from(false)
|
ConstraintSet::from(false)
|
||||||
}
|
}
|
||||||
ProtocolMemberKind::Other(ty) => {
|
ProtocolMemberKind::Other(ty) => ty.is_disjoint_from_impl(
|
||||||
ty.is_disjoint_from_impl(db, other, disjointness_visitor, relation_visitor)
|
db,
|
||||||
}
|
other,
|
||||||
|
inferable,
|
||||||
|
disjointness_visitor,
|
||||||
|
relation_visitor,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -625,6 +636,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Type<'db>,
|
other: Type<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -664,6 +676,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
attribute_type.has_relation_to_impl(
|
attribute_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
Type::Callable(method.bind_self(db)),
|
Type::Callable(method.bind_self(db)),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -684,6 +697,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
.has_relation_to_impl(
|
.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
attribute_type,
|
attribute_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -692,6 +706,7 @@ impl<'a, 'db> ProtocolMember<'a, 'db> {
|
||||||
attribute_type.has_relation_to_impl(
|
attribute_type.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*member_type,
|
*member_type,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ use super::{
|
||||||
use crate::semantic_index::definition::Definition;
|
use crate::semantic_index::definition::Definition;
|
||||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||||
use crate::types::function::FunctionType;
|
use crate::types::function::FunctionType;
|
||||||
use crate::types::generics::{GenericContext, typing_self, walk_generic_context};
|
use crate::types::generics::{
|
||||||
|
GenericContext, InferableTypeVars, typing_self, walk_generic_context,
|
||||||
|
};
|
||||||
use crate::types::infer::nearest_enclosing_class;
|
use crate::types::infer::nearest_enclosing_class;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, ClassLiteral,
|
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, ClassLiteral,
|
||||||
|
|
@ -174,41 +176,27 @@ impl<'db> CallableSignature<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether this callable type is a subtype of another callable type.
|
fn is_subtype_of_impl(
|
||||||
///
|
&self,
|
||||||
/// See [`Type::is_subtype_of`] for more details.
|
db: &'db dyn Db,
|
||||||
pub(crate) fn is_subtype_of(&self, db: &'db dyn Db, other: &Self) -> bool {
|
other: &Self,
|
||||||
self.is_subtype_of_impl(db, other).is_always_satisfied()
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
}
|
) -> ConstraintSet<'db> {
|
||||||
|
|
||||||
fn is_subtype_of_impl(&self, db: &'db dyn Db, other: &Self) -> ConstraintSet<'db> {
|
|
||||||
self.has_relation_to_impl(
|
self.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other,
|
other,
|
||||||
|
inferable,
|
||||||
TypeRelation::Subtyping,
|
TypeRelation::Subtyping,
|
||||||
&HasRelationToVisitor::default(),
|
&HasRelationToVisitor::default(),
|
||||||
&IsDisjointVisitor::default(),
|
&IsDisjointVisitor::default(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether this callable type is assignable to another callable type.
|
|
||||||
///
|
|
||||||
/// See [`Type::is_assignable_to`] for more details.
|
|
||||||
pub(crate) fn is_assignable_to(&self, db: &'db dyn Db, other: &Self) -> bool {
|
|
||||||
self.has_relation_to_impl(
|
|
||||||
db,
|
|
||||||
other,
|
|
||||||
TypeRelation::Assignability,
|
|
||||||
&HasRelationToVisitor::default(),
|
|
||||||
&IsDisjointVisitor::default(),
|
|
||||||
)
|
|
||||||
.is_always_satisfied()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn has_relation_to_impl(
|
pub(crate) fn has_relation_to_impl(
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -217,6 +205,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
db,
|
db,
|
||||||
&self.overloads,
|
&self.overloads,
|
||||||
&other.overloads,
|
&other.overloads,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -229,6 +218,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
self_signatures: &[Signature<'db>],
|
self_signatures: &[Signature<'db>],
|
||||||
other_signatures: &[Signature<'db>],
|
other_signatures: &[Signature<'db>],
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -239,6 +229,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
self_signature.has_relation_to_impl(
|
self_signature.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_signature,
|
other_signature,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -251,6 +242,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
db,
|
db,
|
||||||
std::slice::from_ref(self_signature),
|
std::slice::from_ref(self_signature),
|
||||||
other_signatures,
|
other_signatures,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -263,6 +255,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
db,
|
db,
|
||||||
self_signatures,
|
self_signatures,
|
||||||
std::slice::from_ref(other_signature),
|
std::slice::from_ref(other_signature),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -275,6 +268,7 @@ impl<'db> CallableSignature<'db> {
|
||||||
db,
|
db,
|
||||||
self_signatures,
|
self_signatures,
|
||||||
std::slice::from_ref(other_signature),
|
std::slice::from_ref(other_signature),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -290,20 +284,21 @@ impl<'db> CallableSignature<'db> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
match (self.overloads.as_slice(), other.overloads.as_slice()) {
|
match (self.overloads.as_slice(), other.overloads.as_slice()) {
|
||||||
([self_signature], [other_signature]) => {
|
([self_signature], [other_signature]) => {
|
||||||
// Common case: both callable types contain a single signature, use the custom
|
// Common case: both callable types contain a single signature, use the custom
|
||||||
// equivalence check instead of delegating it to the subtype check.
|
// equivalence check instead of delegating it to the subtype check.
|
||||||
self_signature.is_equivalent_to_impl(db, other_signature, visitor)
|
self_signature.is_equivalent_to_impl(db, other_signature, inferable, visitor)
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
if self == other {
|
if self == other {
|
||||||
return ConstraintSet::from(true);
|
return ConstraintSet::from(true);
|
||||||
}
|
}
|
||||||
self.is_subtype_of_impl(db, other)
|
self.is_subtype_of_impl(db, other, inferable)
|
||||||
.and(db, || other.is_subtype_of_impl(db, self))
|
.and(db, || other.is_subtype_of_impl(db, self, inferable))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -619,6 +614,7 @@ impl<'db> Signature<'db> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Signature<'db>,
|
other: &Signature<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
let mut result = ConstraintSet::from(true);
|
let mut result = ConstraintSet::from(true);
|
||||||
|
|
@ -626,7 +622,10 @@ impl<'db> Signature<'db> {
|
||||||
let self_type = self_type.unwrap_or(Type::unknown());
|
let self_type = self_type.unwrap_or(Type::unknown());
|
||||||
let other_type = other_type.unwrap_or(Type::unknown());
|
let other_type = other_type.unwrap_or(Type::unknown());
|
||||||
!result
|
!result
|
||||||
.intersect(db, self_type.is_equivalent_to_impl(db, other_type, visitor))
|
.intersect(
|
||||||
|
db,
|
||||||
|
self_type.is_equivalent_to_impl(db, other_type, inferable, visitor),
|
||||||
|
)
|
||||||
.is_never_satisfied()
|
.is_never_satisfied()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -702,6 +701,7 @@ impl<'db> Signature<'db> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Signature<'db>,
|
other: &Signature<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -777,6 +777,7 @@ impl<'db> Signature<'db> {
|
||||||
type1.has_relation_to_impl(
|
type1.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
type2,
|
type2,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::place::PlaceAndQualifiers;
|
use crate::place::PlaceAndQualifiers;
|
||||||
use crate::semantic_index::definition::Definition;
|
use crate::semantic_index::definition::Definition;
|
||||||
use crate::types::constraints::ConstraintSet;
|
use crate::types::constraints::ConstraintSet;
|
||||||
|
use crate::types::generics::InferableTypeVars;
|
||||||
use crate::types::variance::VarianceInferable;
|
use crate::types::variance::VarianceInferable;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType,
|
ApplyTypeMappingVisitor, BoundTypeVarInstance, ClassType, DynamicType,
|
||||||
|
|
@ -135,6 +136,7 @@ impl<'db> SubclassOfType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: SubclassOfType<'db>,
|
other: SubclassOfType<'db>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -157,6 +159,7 @@ impl<'db> SubclassOfType<'db> {
|
||||||
.has_relation_to_impl(
|
.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_class,
|
other_class,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -171,6 +174,7 @@ impl<'db> SubclassOfType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
_inferable: InferableTypeVars<'_, 'db>,
|
||||||
_visitor: &IsDisjointVisitor<'db>,
|
_visitor: &IsDisjointVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
match (self.subclass_of, other.subclass_of) {
|
match (self.subclass_of, other.subclass_of) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ use itertools::{Either, EitherOrBoth, Itertools};
|
||||||
use crate::semantic_index::definition::Definition;
|
use crate::semantic_index::definition::Definition;
|
||||||
use crate::types::class::{ClassType, KnownClass};
|
use crate::types::class::{ClassType, KnownClass};
|
||||||
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
use crate::types::constraints::{ConstraintSet, IteratorConstraintsExtension};
|
||||||
|
use crate::types::generics::InferableTypeVars;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
|
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
|
||||||
IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, Type, TypeMapping, TypeRelation,
|
IsDisjointVisitor, IsEquivalentVisitor, NormalizedVisitor, Type, TypeMapping, TypeRelation,
|
||||||
|
|
@ -258,6 +259,7 @@ impl<'db> TupleType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -265,6 +267,7 @@ impl<'db> TupleType<'db> {
|
||||||
self.tuple(db).has_relation_to_impl(
|
self.tuple(db).has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.tuple(db),
|
other.tuple(db),
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -275,10 +278,11 @@ impl<'db> TupleType<'db> {
|
||||||
self,
|
self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: Self,
|
other: Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
self.tuple(db)
|
self.tuple(db)
|
||||||
.is_equivalent_to_impl(db, other.tuple(db), visitor)
|
.is_equivalent_to_impl(db, other.tuple(db), inferable, visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_single_valued(self, db: &'db dyn Db) -> bool {
|
pub(crate) fn is_single_valued(self, db: &'db dyn Db) -> bool {
|
||||||
|
|
@ -442,6 +446,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Tuple<Type<'db>>,
|
other: &Tuple<Type<'db>>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -453,6 +458,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
self_ty.has_relation_to_impl(
|
self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*other_ty,
|
*other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -473,6 +479,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
let element_constraints = self_ty.has_relation_to_impl(
|
let element_constraints = self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*other_ty,
|
*other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -491,6 +498,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
let element_constraints = self_ty.has_relation_to_impl(
|
let element_constraints = self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*other_ty,
|
*other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -510,6 +518,7 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
self_ty.has_relation_to_impl(
|
self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.variable,
|
other.variable,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -524,13 +533,14 @@ impl<'db> FixedLengthTuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
ConstraintSet::from(self.0.len() == other.0.len()).and(db, || {
|
ConstraintSet::from(self.0.len() == other.0.len()).and(db, || {
|
||||||
(self.0.iter())
|
(self.0.iter())
|
||||||
.zip(&other.0)
|
.zip(&other.0)
|
||||||
.when_all(db, |(self_ty, other_ty)| {
|
.when_all(db, |(self_ty, other_ty)| {
|
||||||
self_ty.is_equivalent_to_impl(db, *other_ty, visitor)
|
self_ty.is_equivalent_to_impl(db, *other_ty, inferable, visitor)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -793,6 +803,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Tuple<Type<'db>>,
|
other: &Tuple<Type<'db>>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -825,6 +836,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
let element_constraints = self_ty.has_relation_to_impl(
|
let element_constraints = self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_ty,
|
other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -844,6 +856,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
let element_constraints = self_ty.has_relation_to_impl(
|
let element_constraints = self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_ty,
|
other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -884,6 +897,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
EitherOrBoth::Both(self_ty, other_ty) => self_ty.has_relation_to_impl(
|
EitherOrBoth::Both(self_ty, other_ty) => self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other_ty,
|
other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -891,6 +905,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
EitherOrBoth::Left(self_ty) => self_ty.has_relation_to_impl(
|
EitherOrBoth::Left(self_ty) => self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.variable,
|
other.variable,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -918,6 +933,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
EitherOrBoth::Both(self_ty, other_ty) => self_ty.has_relation_to_impl(
|
EitherOrBoth::Both(self_ty, other_ty) => self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
*other_ty,
|
*other_ty,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -925,6 +941,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
EitherOrBoth::Left(self_ty) => self_ty.has_relation_to_impl(
|
EitherOrBoth::Left(self_ty) => self_ty.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.variable,
|
other.variable,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -945,6 +962,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
self.variable.has_relation_to_impl(
|
self.variable.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other.variable,
|
other.variable,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -958,16 +976,17 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
self.variable
|
self.variable
|
||||||
.is_equivalent_to_impl(db, other.variable, visitor)
|
.is_equivalent_to_impl(db, other.variable, inferable, visitor)
|
||||||
.and(db, || {
|
.and(db, || {
|
||||||
(self.prenormalized_prefix_elements(db, None))
|
(self.prenormalized_prefix_elements(db, None))
|
||||||
.zip_longest(other.prenormalized_prefix_elements(db, None))
|
.zip_longest(other.prenormalized_prefix_elements(db, None))
|
||||||
.when_all(db, |pair| match pair {
|
.when_all(db, |pair| match pair {
|
||||||
EitherOrBoth::Both(self_ty, other_ty) => {
|
EitherOrBoth::Both(self_ty, other_ty) => {
|
||||||
self_ty.is_equivalent_to_impl(db, other_ty, visitor)
|
self_ty.is_equivalent_to_impl(db, other_ty, inferable, visitor)
|
||||||
}
|
}
|
||||||
EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => {
|
EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => {
|
||||||
ConstraintSet::from(false)
|
ConstraintSet::from(false)
|
||||||
|
|
@ -979,7 +998,7 @@ impl<'db> VariableLengthTuple<Type<'db>> {
|
||||||
.zip_longest(other.prenormalized_suffix_elements(db, None))
|
.zip_longest(other.prenormalized_suffix_elements(db, None))
|
||||||
.when_all(db, |pair| match pair {
|
.when_all(db, |pair| match pair {
|
||||||
EitherOrBoth::Both(self_ty, other_ty) => {
|
EitherOrBoth::Both(self_ty, other_ty) => {
|
||||||
self_ty.is_equivalent_to_impl(db, other_ty, visitor)
|
self_ty.is_equivalent_to_impl(db, other_ty, inferable, visitor)
|
||||||
}
|
}
|
||||||
EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => {
|
EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => {
|
||||||
ConstraintSet::from(false)
|
ConstraintSet::from(false)
|
||||||
|
|
@ -1170,6 +1189,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
relation: TypeRelation,
|
relation: TypeRelation,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
|
|
@ -1178,6 +1198,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
Tuple::Fixed(self_tuple) => self_tuple.has_relation_to_impl(
|
Tuple::Fixed(self_tuple) => self_tuple.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other,
|
other,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1185,6 +1206,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
Tuple::Variable(self_tuple) => self_tuple.has_relation_to_impl(
|
Tuple::Variable(self_tuple) => self_tuple.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
other,
|
other,
|
||||||
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
|
|
@ -1196,14 +1218,15 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
visitor: &IsEquivalentVisitor<'db>,
|
visitor: &IsEquivalentVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Tuple::Fixed(self_tuple), Tuple::Fixed(other_tuple)) => {
|
(Tuple::Fixed(self_tuple), Tuple::Fixed(other_tuple)) => {
|
||||||
self_tuple.is_equivalent_to_impl(db, other_tuple, visitor)
|
self_tuple.is_equivalent_to_impl(db, other_tuple, inferable, visitor)
|
||||||
}
|
}
|
||||||
(Tuple::Variable(self_tuple), Tuple::Variable(other_tuple)) => {
|
(Tuple::Variable(self_tuple), Tuple::Variable(other_tuple)) => {
|
||||||
self_tuple.is_equivalent_to_impl(db, other_tuple, visitor)
|
self_tuple.is_equivalent_to_impl(db, other_tuple, inferable, visitor)
|
||||||
}
|
}
|
||||||
(Tuple::Fixed(_), Tuple::Variable(_)) | (Tuple::Variable(_), Tuple::Fixed(_)) => {
|
(Tuple::Fixed(_), Tuple::Variable(_)) | (Tuple::Variable(_), Tuple::Fixed(_)) => {
|
||||||
ConstraintSet::from(false)
|
ConstraintSet::from(false)
|
||||||
|
|
@ -1215,6 +1238,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
&self,
|
&self,
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
other: &Self,
|
other: &Self,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
) -> ConstraintSet<'db> {
|
) -> ConstraintSet<'db> {
|
||||||
|
|
@ -1234,6 +1258,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db: &'db dyn Db,
|
db: &'db dyn Db,
|
||||||
a: impl IntoIterator<Item = &'s Type<'db>>,
|
a: impl IntoIterator<Item = &'s Type<'db>>,
|
||||||
b: impl IntoIterator<Item = &'s Type<'db>>,
|
b: impl IntoIterator<Item = &'s Type<'db>>,
|
||||||
|
inferable: InferableTypeVars<'_, 'db>,
|
||||||
disjointness_visitor: &IsDisjointVisitor<'db>,
|
disjointness_visitor: &IsDisjointVisitor<'db>,
|
||||||
relation_visitor: &HasRelationToVisitor<'db>,
|
relation_visitor: &HasRelationToVisitor<'db>,
|
||||||
) -> ConstraintSet<'db>
|
) -> ConstraintSet<'db>
|
||||||
|
|
@ -1244,6 +1269,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
self_element.is_disjoint_from_impl(
|
self_element.is_disjoint_from_impl(
|
||||||
db,
|
db,
|
||||||
*other_element,
|
*other_element,
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -1255,6 +1281,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db,
|
db,
|
||||||
self_tuple.elements(),
|
self_tuple.elements(),
|
||||||
other_tuple.elements(),
|
other_tuple.elements(),
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
),
|
),
|
||||||
|
|
@ -1266,6 +1293,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db,
|
db,
|
||||||
self_tuple.prefix_elements(),
|
self_tuple.prefix_elements(),
|
||||||
other_tuple.prefix_elements(),
|
other_tuple.prefix_elements(),
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -1274,6 +1302,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db,
|
db,
|
||||||
self_tuple.suffix_elements().rev(),
|
self_tuple.suffix_elements().rev(),
|
||||||
other_tuple.suffix_elements().rev(),
|
other_tuple.suffix_elements().rev(),
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -1284,6 +1313,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db,
|
db,
|
||||||
fixed.elements(),
|
fixed.elements(),
|
||||||
variable.prefix_elements(),
|
variable.prefix_elements(),
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
)
|
)
|
||||||
|
|
@ -1292,6 +1322,7 @@ impl<'db> Tuple<Type<'db>> {
|
||||||
db,
|
db,
|
||||||
fixed.elements().rev(),
|
fixed.elements().rev(),
|
||||||
variable.suffix_elements().rev(),
|
variable.suffix_elements().rev(),
|
||||||
|
inferable,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue