Skip to content

Commit 2bd1875

Browse files
authored
Merge 8f0350b into 1616095
2 parents 1616095 + 8f0350b commit 2bd1875

2 files changed

Lines changed: 37 additions & 7 deletions

File tree

crates/ty_python_semantic/src/types/call/bind.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,18 @@ impl<'db> Bindings<'db> {
351351
self.elements.iter_mut().flat_map(|e| e.bindings.iter_mut())
352352
}
353353

354+
/// Returns `true` if every element of the union contains an intersection element with a matching
355+
/// overload that satisfies the provided closure, or `false` otherwise.
356+
pub(crate) fn satisfies(&self, f: impl Fn(&Binding<'db>) -> bool) -> bool {
357+
self.elements.iter().all(|element| {
358+
element
359+
.bindings
360+
.iter()
361+
.flat_map(CallableBinding::matching_overloads)
362+
.any(|(_, overload)| f(overload))
363+
})
364+
}
365+
354366
/// Maps each `CallableBinding` to a type and combines results while preserving
355367
/// the union-of-intersections structure:
356368
///

crates/ty_python_semantic/src/types/infer/builder.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4976,7 +4976,24 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
49764976
_ => &[],
49774977
};
49784978

4979-
let mut try_narrow = |narrowed_ty| {
4979+
let mut try_narrow = |narrowed_ty: Type<'db>| {
4980+
// Short-circuit if there is no overload with a matching return type.
4981+
if !bindings.satisfies(|overload| {
4982+
let inferable = overload
4983+
.signature
4984+
.generic_context
4985+
.map(|generic_context| generic_context.inferable_typevars(db))
4986+
.unwrap_or(InferableTypeVars::None);
4987+
4988+
!overload
4989+
.constructor_instance_type
4990+
.unwrap_or(overload.signature.return_ty)
4991+
.when_assignable_to(db, narrowed_ty, &constraints, inferable)
4992+
.is_never_satisfied(db)
4993+
}) {
4994+
return None;
4995+
}
4996+
49804997
let narrowed_tcx = TypeContext::new(Some(narrowed_ty));
49814998

49824999
let mut speculative_bindings = bindings.clone();
@@ -5030,7 +5047,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
50305047
))
50315048
};
50325049

5033-
// Prefer the declared type of generic classes.
5050+
// Prefer generic class instances when narrowing.
5051+
//
5052+
// Splitting up this loop is not necessary for correctness, but leads to a slight
5053+
// performance improvement.
50345054
for narrowed_ty in narrow_targets
50355055
.iter()
50365056
.filter(|ty| ty.class_specialization(db).is_some())
@@ -5039,11 +5059,6 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
50395059
return result;
50405060
}
50415061
}
5042-
5043-
// Try the remaining elements of the union.
5044-
//
5045-
// TODO: We could also attempt an inference without type context, but this
5046-
// leads to similar performance issues.
50475062
for narrowed_ty in narrow_targets
50485063
.iter()
50495064
.filter(|ty| ty.class_specialization(db).is_none())
@@ -5054,6 +5069,9 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
50545069
}
50555070

50565071
// Infer against the entire union as a fallback.
5072+
//
5073+
// TODO: We could also attempt an inference without type context, but this
5074+
// leads to similar performance issues.
50575075
self.infer_all_argument_types(
50585076
ast_arguments,
50595077
argument_types,

0 commit comments

Comments
 (0)