Skip to content

Looping through list of aliased union causes potentially-missing members to be available #3161

@refi64

Description

@refi64

Summary

https://play.ty.dev/e386b6ff-128c-45d7-bc1a-89108e3a1ad3

class A:
    pass

class B:
    def do_b_thing(self) -> None:
        pass


type U = A | B


class Cls:
    def __init__(self,
        not_aliased: list[A | B],   # list of `A | B`
        aliased: list[U],  # effectively the same as above, but with an intermediate alias
    ) -> None:
        # All of this is as expected: we can't access B-only methods from `A | B`...
        self.not_aliased = not_aliased
        reveal_type(self.not_aliased[0])  # A | B
        self.not_aliased[0].do_b_thing()  # not defined on `A` in union `A | B`
        for item in self.not_aliased:
            reveal_type(item)  # A | B
            item.do_b_thing()  # not defined on `A` in union `A | B`

        # ...even if it's through an alias. Why would an alias change anything anyway?
        self.aliased = aliased
        reveal_type(self.aliased[0])  # A | B
        self.aliased[0].do_b_thing()  # not defined on `A` in union `A | B`
        for item in self.aliased:
            reveal_type(item)  # A | B
            item.do_b_thing()  # not defined on `A` in union `U`


    def do_thing(self) -> None:
        # If we do all the same stuff from a method, then it's all still as expected, right?
        reveal_type(self.not_aliased[0])  # Unknown | A | B
        self.not_aliased[0].do_b_thing()  # ERROR: not defined on `A` in union `Unknown | A | B`
        for item in self.not_aliased:
            reveal_type(item)  # Unknown | A | B
            item.do_b_thing()  # not defined on `A` in union `Unknown | A | B`

        # But when we access the list of aliases...
        reveal_type(self.aliased[0])  # Unknown | A | B
        self.aliased[0].do_b_thing()  # ERROR: not defined on `A` in union `Unknown | A | B`
        for item in self.aliased:
            reveal_type(item)  # Unknown | A | B
            item.do_b_thing()  # SOMEHOW NOT AN ERROR?????

Version

6e76b4cd8 (from playground)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions