Skip to content

Conversation

KotlinIsland
Copy link
Contributor

@KotlinIsland KotlinIsland commented Sep 21, 2025

support:

a: list[object] = list[int]().copy()

This comment has been minimized.

This comment has been minimized.

@overload
def __init__(self, iterable: Iterable[_T], /) -> None: ...
def copy(self) -> list[_T]: ...
def copy(self) -> list[_S | _T]: ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_S has no meaning, as it's only used once in this context. It's just interpreted as Any in this context.

Copy link
Collaborator

@srittau srittau Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you're trying to do, but we should probably use:

Suggested change
def copy(self) -> list[_S | _T]: ...
# The new list can allow broader types that the old one. `Any` allows that.
def copy(self) -> list[_T | Any]: ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_S has no meaning, as it's only used once in this context. It's just interpreted as Any in this context.

that is demonstrably not true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code sample in basedpyright playground

from __future__ import annotations
from typing import Any

class A[T]:
    t: T
    def copy1[Expected](self) -> A[Expected | T]:
        return A()
    def copy2[Expected](self) -> A[Any | T]:
        return A()
a: A[object] = A[int]().copy1()
a: A[object] = A[int]().copy2()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basedpyright is incorrect there. A[int | Any] should be assignable to A[object].

Copy link
Contributor Author

@KotlinIsland KotlinIsland Sep 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider this example:

def empty_list[T=Never]() -> list[T]:
    return []

a = empty_list()
b: list[int] = empty_list()

if we were to use Any here, then the type of a would be list[Any]

additionally, there would be absolutely no safety within empty_list to return the correct type. i'm not really sure where this idea that type variables only in return positions being invalid came from

this is literally the meaning of a type variable, to use Any is a mistake

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basedpyright is incorrect there. A[int | Any] should be assignable to A[object].

yes: microsoft/pyright#10713 (comment)

i was a little hasty with the first example, i think it's clear though that this case is the intended use of a type variable, not Any

Copy link
Contributor

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants