Skip to content

Unpacking TypeAliasType to tuple of types using * errors at runtime, Unpack doesn't #126085

Closed

Description

@alwaysmpe

Bug report

Bug description:

Discussed in microsoft/pyright#9343 @JelleZijlstra asked me to open this issue.

I'm writing classes using variadic generic code and as a minimal example I have the below code which raises no type errors on pyright playground and is crashing at runtime which I believe is a bug in cpython. The code:

from __future__ import annotations
from typing import Unpack, assert_type, TypeAlias
type FooArgT = tuple[str, str]
# deprecated but works at runtime
FooArgAliasT: TypeAlias = tuple[str, str]

class Foo[*Arg]:
    pass

type FooT = Foo[str, *FooArgT]
type FooUT = Foo[str, Unpack[FooArgT]]

class BarAU(Foo[str, *FooArgAliasT]):
    pass

class BarU(Foo[str, Unpack[FooArgT]]):
    pass

def foo_fn(t_arg: FooT, ut_arg: FooUT):
    assert_type(t_arg, FooT)
    assert_type(t_arg, FooUT)
    assert_type(t_arg, Foo[str, Unpack[FooArgT]])
    assert_type(t_arg, Foo[str, *FooArgT])
    assert_type(ut_arg, FooT)
    assert_type(ut_arg, FooUT)
    assert_type(ut_arg, Foo[str, Unpack[FooArgT]])
    assert_type(ut_arg, Foo[str, *FooArgT])

class Bar(Foo[str, *FooArgT]):
    pass

When I run this locally I get

Traceback (most recent call last):
  File "...", line 31, in <module>
    class Bar(Foo[str, *FooArgT]):
                  ^^^^^^^^^^^^^
TypeError: Value after * must be an iterable, not typing.TypeAliasType

By my understanding, the 3 class declarations are equivalent, pyright checks pass and from my understanding of the documentation cpython should allow unpacking of the aliased TypeVarTuple.

I'm running python3.13.0 in wsl installed using pyenv, output of python -V -V

Python 3.13.0 (main, Oct 24 2024, 00:12:39) [GCC 11.4.0]

CPython versions tested on:

3.13
3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    type-featureA feature request or enhancement
    and removed
    type-bugAn unexpected behavior, bug, or error
    on Oct 28, 2024
  2. JelleZijlstra commented on Oct 28, 2024

    @JelleZijlstra
    Member

    To fix this, we can add a tp_iter slot to TypeAliasType that produces Unpack[self]. Something very similar already exists for TypeVarTuple; in fact we can probably reuse the same C function. If anyone reading this is interested, please file a PR! Otherwise I'll do it myself at some point.

    I reclassified this as a feature request because it's adding a new capability to TypeAliasType, which we only do in new feature versions. However, we'll be able to backport this behavior to typing-extensions for the benefit of earlier Python versions.

  3. alwaysmpe commented on Oct 28, 2024

    @alwaysmpe
    Author

    I'll have a look but make zero promises as I've never touched the cpython code base before so anyone else is welcome.

  4. Eclips4 commented on Oct 28, 2024

    @Eclips4
    Member

    I'll have a look but make zero promises as I've never touched the cpython code base before so anyone else is welcome.

    FYI, you need to modify Objects/typevarobject.c file (add a tp_iter slot to _PyTypeAlias_Type). See typevartuple_iter as reference implementation.

  5. JelleZijlstra commented on Oct 28, 2024

    @JelleZijlstra
    Member

    I'd actually recommend to use typevartuple_iter directly; it looks like it should work unchanged. However, the function should be renamed for clarity in that case.

  6. tomasr8 commented on Dec 15, 2024

    @tomasr8
    Member

    @alwaysmpe Are you still planning to work on this? If not, I can take a look :)

  7. alwaysmpe commented on Dec 15, 2024

    @alwaysmpe
    Author

    @tomasr8 feel free to take it on, if nobody else gets to it I'll take it on at some point but it's not a blocker for my other projects as I'm using the T: TypeAlias = tuple[...] workaround so it's low on my priorities. I also finished the project that was using lots of variadics.

  8. added a commit that references this issue on Mar 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions