Skip to content

Commit 2a52aa9

Browse files
gvozdvmozgumeta-codesync[bot]
authored andcommitted
fix: handle ParamSpec args/kwargs subscripts like tuple/dict (#1693)
Summary: Fixes #1692 Pull Request resolved: #1693 Reviewed By: ndmitchell Differential Revision: D87946959 Pulled By: yangdanny97 fbshipit-source-id: c4aea136fac746462ea6e1667ead912b9d47b9c1
1 parent 91bfb00 commit 2a52aa9

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

pyrefly/lib/alt/expr.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,34 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
20742074
Some(&context),
20752075
)
20762076
}
2077+
Type::Args(_) => {
2078+
let tuple = Tuple::Unbounded(Box::new(self.stdlib.object().clone().to_type()));
2079+
self.infer_tuple_subscript(
2080+
tuple,
2081+
slice,
2082+
range,
2083+
errors,
2084+
Some(&|| ErrorContext::Index(self.for_display(base.clone()))),
2085+
)
2086+
}
2087+
Type::Kwargs(_) => {
2088+
let kwargs_ty = self
2089+
.stdlib
2090+
.dict(
2091+
self.stdlib.str().clone().to_type(),
2092+
self.stdlib.object().clone().to_type(),
2093+
)
2094+
.to_type();
2095+
self.call_method_or_error(
2096+
&kwargs_ty,
2097+
&dunder::GETITEM,
2098+
range,
2099+
&[CallArg::expr(slice)],
2100+
&[],
2101+
errors,
2102+
Some(&|| ErrorContext::Index(self.for_display(base.clone()))),
2103+
)
2104+
}
20772105
Type::ClassType(ref cls) | Type::SelfType(ref cls)
20782106
if let Some(tuple) = self.as_tuple(cls) =>
20792107
{

pyrefly/lib/module/typeshed.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use std::sync::LazyLock;
1515
use anyhow::anyhow;
1616
use dupe::Dupe;
1717
use pyrefly_bundled::bundled_typeshed;
18-
use pyrefly_config::error::ErrorDisplayConfig;
1918
use pyrefly_config::error_kind::ErrorKind;
2019
use pyrefly_config::error_kind::Severity;
2120
use pyrefly_python::module_name::ModuleName;

pyrefly/lib/test/paramspec.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,25 @@ def decorator(f: Callable[P, int]) -> Callable[P, None]:
300300
"#,
301301
);
302302

303+
testcase!(
304+
test_paramspec_args_kwargs_subscriptable,
305+
r#"
306+
from typing import Callable, ParamSpec, TypeVar, assert_type
307+
308+
FP = ParamSpec('FP')
309+
FR = TypeVar('FR')
310+
311+
def decorate(f: Callable[FP, FR]) -> Callable[FP, FR]:
312+
def wrapper(*args: FP.args, **kwargs: FP.kwargs) -> FR:
313+
if len(args) > 0:
314+
assert_type(args[0], object)
315+
if 'foo' in kwargs:
316+
assert_type(kwargs['foo'], object)
317+
return f(*args, **kwargs)
318+
return wrapper
319+
"#,
320+
);
321+
303322
testcase!(
304323
test_paramspec_named_arguments_concatenate,
305324
r#"

0 commit comments

Comments
 (0)