diff --git a/mypy/checker.py b/mypy/checker.py index 8775f1ddef29..a38420ef97f3 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -8028,7 +8028,22 @@ def get_type_range_of_type(self, typ: Type) -> TypeRange | None: if isinstance(typ, UnionType): type_ranges = [self.get_type_range_of_type(item) for item in typ.items] - item = make_simplified_union([t.item for t in type_ranges if t is not None]) + if any(t is None for t in type_ranges): + return None + # Filter out None and UninhabitedType entries (type checkers need explicit None check) + valid_ranges = [ + t + for t in type_ranges + if t is not None and not isinstance(get_proper_type(t.item), UninhabitedType) + ] + if not valid_ranges: + return TypeRange(UninhabitedType(), is_upper_bound=False) + # If the only meaningful type we can extract is "object", we've lost + # type precision (e.g. from a widened _ClassInfo alias). Return None + # to avoid narrowing to a useless type. + item = make_simplified_union([t.item for t in valid_ranges]) + if isinstance(item, Instance) and item.type.fullname == "builtins.object": + return None return TypeRange(item, is_upper_bound=True) if isinstance(typ, FunctionLike) and typ.is_type_obj(): # If a type is generic, `isinstance` can only narrow its variables to Any.