Skip to content

Commit 5c249f3

Browse files
rchen152meta-codesync[bot]
authored andcommitted
Extend save+restore of partial vars around overload calls to all placeholder vars
Summary: Fixes #3002. Reviewed By: migeed-z Differential Revision: D100591004 fbshipit-source-id: 1bb3e81a6f668f70ae9b3ed3993265db6dd3b5e6
1 parent fc600bd commit 5c249f3

2 files changed

Lines changed: 34 additions & 11 deletions

File tree

pyrefly/lib/alt/overload.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -502,14 +502,14 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
502502
hint: Option<HintRef>,
503503
ctor_targs: &Option<&mut TArgs>,
504504
) -> (CalledOverload<'c>, bool) {
505-
// Collect partial vars so we can save/restore them around each overload evaluation. This
506-
// prevents premature pinning of partial vars on failed overload calls.
507-
let partial_vars = self.collect_partial_vars(self_obj, args, keywords);
505+
// Collect placeholder vars so we can save/restore them around each overload evaluation. This
506+
// prevents premature pinning of vars on failed overload calls.
507+
let placeholder_vars = self.collect_placeholder_vars(self_obj, args, keywords);
508508

509509
let mut matched_overloads = Vec::with_capacity(overloads.len());
510510
let mut closest_unmatched_overload: Option<CalledOverload<'c>> = None;
511511
for callable in overloads {
512-
let snapshot = self.solver().snapshot_vars(&partial_vars);
512+
let snapshot = self.solver().snapshot_vars(&placeholder_vars);
513513
let called_overload = self.call_overload(
514514
callable,
515515
metadata,
@@ -630,7 +630,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
630630
matched_overloads
631631
.iter()
632632
.find_position(|o| {
633-
let snapshot = self.solver().snapshot_vars(&partial_vars);
633+
let snapshot = self.solver().snapshot_vars(&placeholder_vars);
634634
let res = self.call_overload(
635635
o.func,
636636
metadata,
@@ -747,18 +747,18 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
747747
Some(candidate)
748748
}
749749

750-
/// Collect partial vars from self_obj and Type-valued arguments.
751-
fn collect_partial_vars(
750+
/// Collect placeholder vars from self_obj and Type-valued arguments.
751+
fn collect_placeholder_vars(
752752
&self,
753753
self_obj: Option<&Type>,
754754
args: &[CallArg],
755755
keywords: &[CallKeyword],
756756
) -> Vec<Var> {
757-
let mut partial_vars: Vec<Var> = Vec::new();
757+
let mut placeholder_vars: Vec<Var> = Vec::new();
758758
let mut collect = |ty: &Type| {
759759
for var in ty.collect_maybe_placeholder_vars() {
760-
if self.solver().var_is_partial(var) && !partial_vars.contains(&var) {
761-
partial_vars.push(var);
760+
if !placeholder_vars.contains(&var) {
761+
placeholder_vars.push(var);
762762
}
763763
}
764764
};
@@ -777,7 +777,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
777777
collect(ty);
778778
}
779779
}
780-
partial_vars
780+
placeholder_vars
781781
}
782782

783783
fn call_overload<'c>(

pyrefly/lib/test/constructors.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,3 +1003,26 @@ def f(x: dict[Kind, int]) -> None:
10031003
g(dict(x))
10041004
"#,
10051005
);
1006+
1007+
testcase!(
1008+
test_overloaded_constructor_with_hint,
1009+
r#"
1010+
from collections.abc import Mapping
1011+
from typing import assert_type, Generic, Never, overload, SupportsInt, TypeVar
1012+
1013+
_T_co = TypeVar("_T_co", covariant=True)
1014+
_T = TypeVar("_T")
1015+
1016+
class Box(Generic[_T_co]):
1017+
@overload
1018+
def __init__(self: "Box[Never]", val: Mapping[Never, SupportsInt], /) -> None: ...
1019+
@overload
1020+
def __init__(self: "Box[_T]", val: Mapping[_T, SupportsInt], /) -> None: ...
1021+
def __init__(self, val: object, /) -> None:
1022+
pass
1023+
1024+
def process(items: Box[_T]) -> "Box[_T]": ...
1025+
1026+
assert_type(process(Box({1: 1})), Box[int])
1027+
"#,
1028+
);

0 commit comments

Comments
 (0)