Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discard the default arg of TypeVar #1847

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions pytype/overlays/typing_overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,16 @@ def _get_typeparam_args(self, node, args):
contravariant = self._get_namedarg(node, args, "contravariant", False)
if constraints and bound:
raise TypeVarError("constraints and a bound are mutually exclusive")
extra_kwargs = set(args.namedargs) - {"bound", "covariant", "contravariant"}
# `default` is unsupported for now - access it just to generate a warning.
# TODO: b/382028836 - actually support the `default` arg to `TypeVar`
self._get_namedarg(node, args, "default", None)

extra_kwargs = set(args.namedargs) - {
"bound",
"covariant",
"contravariant",
"default",
}
if extra_kwargs:
raise TypeVarError("extra keyword arguments: " + ", ".join(extra_kwargs))
if args.starargs:
Expand Down Expand Up @@ -345,7 +354,10 @@ def _get_namedarg(self, node, args, name, default_value):
if name == "bound":
return self._get_annotation(node, args.namedargs[name], name)
else:
ret = self._get_constant(args.namedargs[name], name, bool)
if name == "default":
ret = self._get_annotation(node, args.namedargs[name], name)
else:
ret = self._get_constant(args.namedargs[name], name, bool)
# This error is logged only if _get_constant succeeds.
self.ctx.errorlog.not_supported_yet(
self.ctx.vm.frames, f'argument "{name}" to TypeVar'
Expand Down
10 changes: 8 additions & 2 deletions pytype/stubs/builtins/typing.pytd
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ Text = str
# purposes and to make it easier for pytype to type-check arguments to TypeVar
# and ParamSpec.
def _typevar_new(
name: str, *constraints: type | str | None, bound: type | str | None = None,
covariant: bool = False, contravariant: bool = False): ...
name: str,
*constraints: type | str | None,
bound: type | str | None = None,
covariant: bool = False,
contravariant: bool = False,
infer_variance: bool = False,
default: Any = None,
): ...
def _paramspec_new(
name: str, *constraints: type | str | None, bound: type | str | None = None,
covariant: bool = False, contravariant: bool = False): ...
Expand Down
35 changes: 35 additions & 0 deletions pytype/tests/test_typevar1.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,41 @@ def test_contravariant(self):
},
)

def test_default(self):
ty = self.Infer("""
from typing import Generic, TypeVar

T = TypeVar("T", default=int) # pytype: disable=not-supported-yet

class Foo(Generic[T]):
pass

f = Foo()
""")
self.assertTypesMatchPytd(
ty,
"""
from typing import Generic, TypeVar

T = TypeVar('T')

class Foo(Generic[T]): ...

f: Foo[nothing]
""",
)

self.CheckWithErrors("""
from typing import Generic, TypeVar

T = TypeVar("T", default=int) # not-supported-yet

class Foo(Generic[T]):
pass

f = Foo()
""")

def test_dont_propagate_pyval(self):
# in functions like f(x: T) -> T, if T has constraints we should not copy
# the value of constant types between instances of the typevar.
Expand Down
Loading