-
from abc import ABC
from dataclasses import dataclass
import typing
@dataclass
class Val(ABC):
shape: typing.Tuple[int, ...]
@dataclass
class Add(Val):
x: Val
y: Val
@dataclass
class Slice[T: Val = Val](Val):
dim: int
value: T
@dataclass
class UntaggedSlice(Val):
dim: int
value: Val
def do_something(val: Val) -> Val:
if isinstance(val, Add):
reveal_type(val) # Type of "val" is "Add"
return val.x
elif isinstance(val, Slice):
reveal_type(val) # Type of "val" is "Slice[Unknown]"
return val.value # Type of "value" is unknown
elif isinstance(val, Slice):
val = typing.cast(Slice, val)
reveal_type(val) # Type of "val" is "Slice[Val]"
return val.value
elif isinstance(val, UntaggedSlice):
reveal_type(val) # Type of "val" is "UntaggedSlice"
return val.value
else:
return valUsing the Pylance extension version 2025.6.106 in VSCode. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
|
Narrowing I have considered changing the narrowing behavior of |
Beta Was this translation helpful? Give feedback.
Narrowing
valfromValtoSlice[Val]would not be sound in this case. For example, ifdo_somethingreceives an object of typeSlice[Add], it would be unsound for the value's type to beSlice[Val]within the block guarded byisinstance(val, Slice). Such a type would allow you to overwrite thevaluefield with an object that is not compatible withAdd.I have considered changing the narrowing behavior of
isinstancein the case where type parameters are covariant. In that circumstances, I think it would be OK to use the upper bound rather thanUnknown. Likewise, it should be possible to use the lower bound (Never) in the case of contravariant type parameters. But I don't see a way aroundUnk…