From 9675c1139ae57fffd9fdde55ab5fde9c2244c7ac Mon Sep 17 00:00:00 2001 From: Hana Joo Date: Fri, 25 Apr 2025 02:34:58 -0700 Subject: [PATCH] Add bound support for TypeVars in PEP 695 PiperOrigin-RevId: 751334932 --- pytype/tests/test_typevar1.py | 14 ++++++++++++++ pytype/vm.py | 32 +++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/pytype/tests/test_typevar1.py b/pytype/tests/test_typevar1.py index 3c0d1e92a..948439fc2 100644 --- a/pytype/tests/test_typevar1.py +++ b/pytype/tests/test_typevar1.py @@ -52,6 +52,20 @@ def test_unused_typevar_pep695_switch_order(self): """, ) + @test_utils.skipBeforePy((3, 12), "PEP 695 - 3.12 feature") + def test_type_var_with_bounds_in_type_alias(self): + ty = self.Infer(""" + type Alias[T: int] = list[T] + """) + self.assertTypesMatchPytd( + ty, + """ + from typing import TypeVar + T = TypeVar('T', bound=int) + Alias = list[T] + """, + ) + @test_utils.skipBeforePy((3, 12), "PEP 695 - 3.12 feature") def test_unused_typevar_pep695_function_type_var_single(self): ty = self.Infer(""" diff --git a/pytype/vm.py b/pytype/vm.py index f65822f1f..fe89dcb24 100644 --- a/pytype/vm.py +++ b/pytype/vm.py @@ -3931,7 +3931,37 @@ def byte_INTRINSIC_PREP_RERAISE_STAR(self, state): return state def byte_INTRINSIC_TYPEVAR_WITH_BOUND(self, state): - # TODO: b/350910471 - Implement to support PEP 695 + """This intrinsic is a synonym of typing.TypeVar('T', bound=...).""" + # First parameter(bound_func) is the function object that returns the type + # representation of the bound. + state, (type_var_name, bound_func) = state.popn(2) + + type_var_name = self.ctx.convert.constant_to_var( + type_var_name.data[0].pyval, node=state.node + ) + _, bound = function.call_function( + self.ctx, + state.node, + bound_func, + args=function.Args( + posargs=(), + namedargs={}, + starargs=None, + starstarargs=None, + ), + ) + _, ret = function.call_function( + self.ctx, + state.node, + self._typings_type_var, + args=function.Args( + posargs=(type_var_name,), + namedargs={"bound": bound}, + starargs=None, + starstarargs=None, + ), + ) + state = state.push(ret) return state def byte_INTRINSIC_TYPEVAR_WITH_CONSTRAINTS(self, state):