mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 05:14:52 +00:00
fix constrained typevar inference
This commit is contained in:
parent
b1a987318f
commit
7abff51010
1 changed files with 27 additions and 10 deletions
|
@ -1,7 +1,5 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::types::constraints::ConstraintSet;
|
||||
|
||||
use itertools::Itertools;
|
||||
use ruff_db::parsed::ParsedModuleRef;
|
||||
use ruff_python_ast as ast;
|
||||
|
@ -12,6 +10,7 @@ use crate::semantic_index::definition::Definition;
|
|||
use crate::semantic_index::scope::{FileScopeId, NodeWithScopeKind};
|
||||
use crate::types::class::ClassType;
|
||||
use crate::types::class_base::ClassBase;
|
||||
use crate::types::constraints::ConstraintSet;
|
||||
use crate::types::infer::infer_definition_types;
|
||||
use crate::types::instance::{Protocol, ProtocolInstanceType};
|
||||
use crate::types::signatures::{Parameter, Parameters, Signature};
|
||||
|
@ -20,7 +19,7 @@ use crate::types::{
|
|||
ApplyTypeMappingVisitor, BoundTypeVarInstance, FindLegacyTypeVarsVisitor, HasRelationToVisitor,
|
||||
IsEquivalentVisitor, KnownClass, KnownInstanceType, MaterializationKind, NormalizedVisitor,
|
||||
Type, TypeMapping, TypeRelation, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind,
|
||||
TypeVarVariance, UnionType, binding_type, declaration_type,
|
||||
TypeVarVariance, UnionBuilder, UnionType, binding_type, declaration_type,
|
||||
};
|
||||
use crate::{Db, FxOrderSet};
|
||||
|
||||
|
@ -1113,17 +1112,35 @@ impl<'db> SpecializationBuilder<'db> {
|
|||
self.add_type_mapping(bound_typevar, ty);
|
||||
}
|
||||
Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
|
||||
// If the type is assignable to _all_ of the constraints, then we
|
||||
// specialize the typevar to the type itself. If the type is assignable to
|
||||
// some but not all of them, we specialize the type to the union of the
|
||||
// constraints that it was assignable to. Otherwise it's a specialization
|
||||
// error.
|
||||
let mut builder = UnionBuilder::new(self.db);
|
||||
let mut when_all_assignable = ConstraintSet::from(true);
|
||||
let mut any_assignable = false;
|
||||
for constraint in constraints.elements(self.db) {
|
||||
if ty.is_assignable_to(self.db, *constraint) {
|
||||
self.add_type_mapping(bound_typevar, *constraint);
|
||||
return Ok(());
|
||||
let when_assignable: ConstraintSet =
|
||||
ty.when_assignable_to(self.db, *constraint);
|
||||
if when_assignable.is_always_satisfied() {
|
||||
builder = builder.add(*constraint);
|
||||
any_assignable = true;
|
||||
}
|
||||
when_all_assignable.intersect(self.db, &when_assignable);
|
||||
}
|
||||
|
||||
if when_all_assignable.is_always_satisfied() {
|
||||
self.add_type_mapping(bound_typevar, ty);
|
||||
} else if any_assignable {
|
||||
self.add_type_mapping(bound_typevar, builder.build());
|
||||
} else {
|
||||
return Err(SpecializationError::MismatchedConstraint {
|
||||
bound_typevar,
|
||||
argument: ty,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.add_type_mapping(bound_typevar, ty);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue