sublimelsp / LSP-pyright

Python support for Sublime's LSP plugin provided through microsoft/pyright.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Child Classes not Recognized as Return Types

munkybutt opened this issue · comments

When defining a parent class as the return type of a function, assigning the output of the function to a variable of a child class raises an error.

class CustomInt(int):
    pass

def get_int() -> int:
    return CustomInt(1)

def get_ints() -> tuple[int, ...]:
    return (CustomInt(1), CustomInt(2))

# this is accepted:
fn_int: int
fn_int = get_int()
# this raises an error:
fn_custom_int: CustomInt
fn_custom_int = get_int()

# this is accepted:
fn_ints: tuple[int, ...] = get_ints()
# this raises an error:
fn_custom_ints: tuple[CustomInt, ...] = get_ints()
# this is fine:
test_ints: tuple[int, ...]
test_ints = (CustomInt(1), CustomInt(2))

image

image

Worth mentioning that this error does not occur in VSCode.

That's a server issue so you would have to report it to https://github.com/microsoft/pyright. LSP-pyright just show you what the server says.

That is what I thought until I tested the same code in VSCode, and it accepts the signatures without an error - so there must be something on the Sublime side?

I seem to see that's wrong indeed. If CustomInt is Dog and int is Animal, as you did class Dog(Animal): .... But now you are trying to do fn_dog = get_animal(), which is incorrect indeed. You cannot assign an animal (maybe a cat) to a dog.

VSCode has type checking disabled by default. See python.analysis.typeCheckingMode setting in Vscode

Apologies, you are both correct - I had lost the correct example of the issue when I made my simplified example.

My original function can return a parent class or any of the child classes.
To get the correct type annotation for the function return type I am defining the type of the variable to one of the valid child classes which is defined in the return type.

This is a correct example, which also occurs in VSCode:

class CustomInt(int):
    pass

def get_int() -> int | CustomInt:
    return CustomInt(1)

def get_ints() -> tuple[int, ...] | tuple[CustomInt, ...]:
    return (CustomInt(1), CustomInt(2))


# this is accepted:
fn_int: int
fn_int = get_int()
# this raises an error:
fn_custom_int: CustomInt
fn_custom_int = get_int()

# this is accepted:
fn_ints: tuple[int, ...] = get_ints()
# this raises an error:
fn_custom_ints: tuple[CustomInt, ...] = get_ints()

# this is fine:
test_ints: tuple[int, ...] | tuple[CustomInt, ...]
test_ints = (CustomInt(1), CustomInt(2))

I will log it with them - thanks for your time!

Ignore me, that is also correctly invalid. Sorry - long day 😢