diff --git a/mypy/semanal.py b/mypy/semanal.py index fb6f299a37956..da58c95869667 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -2403,6 +2403,9 @@ def analyze_unbound_tvar(self, t: Type) -> tuple[str, TypeVarLikeExpr] | None: if isinstance(t, UnboundType): sym = self.lookup_qualified(t.name, t) if sym and sym.fullname in UNPACK_TYPE_NAMES: + if not t.args: + # Unpack used without arguments, e.g. `Protocol[Unpack]` + return None inner_t = t.args[0] if isinstance(inner_t, UnboundType): return self.analyze_unbound_tvar_impl(inner_t, is_unpacked=True) diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test index 7ca21b280aad0..ff5cdc8719bc6 100644 --- a/test-data/unit/check-typevar-tuple.test +++ b/test-data/unit/check-typevar-tuple.test @@ -2765,3 +2765,11 @@ def func(d: Callable[[Unpack[Ts]], T]) -> T: ... y = func[1, int] # E: Type application is only supported for generic classes \ # E: Invalid type: try using Literal[1] instead? [builtins fixtures/tuple.pyi] + +[case testTypeVarTupleUnpackWithoutArgsInProtocol] +# https://github.com/python/mypy/issues/21467 +from typing import Protocol, Unpack + +class C(Protocol[Unpack]): # E: Free type variable expected in Protocol[...] + pass +[builtins fixtures/tuple.pyi]