diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 1633eaf52983..e677a24c8a10 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -70,6 +70,7 @@ TypeVarLikeType, TypeVarTupleType, TypeVarType, + UninhabitedType, UnionType, get_proper_type, ) @@ -269,6 +270,10 @@ def _analyze_member_access( if not mx.suppress_errors: mx.msg.deleted_as_rvalue(typ, mx.context) return AnyType(TypeOfAny.from_error) + elif isinstance(typ, UninhabitedType): + attr_type = UninhabitedType() + attr_type.ambiguous = typ.ambiguous + return attr_type return report_missing_attribute(mx.original_type, typ, name, mx) diff --git a/test-data/unit/check-unreachable-code.test b/test-data/unit/check-unreachable-code.test index 368431127b76..f425410a9774 100644 --- a/test-data/unit/check-unreachable-code.test +++ b/test-data/unit/check-unreachable-code.test @@ -1587,3 +1587,19 @@ x = 0 # not unreachable f2: Callable[[], NoReturn] = lambda: foo() x = 0 # not unreachable + +[case testAttributeNoReturn] +# flags: --warn-unreachable +from typing import Optional, NoReturn, TypeVar + +def foo() -> NoReturn: + raise + +T = TypeVar("T") +def bar(x: Optional[list[T]] = None) -> T: + ... + +reveal_type(bar().attr) # N: Revealed type is "Never" +1 # not unreachable +reveal_type(foo().attr) # N: Revealed type is "Never" +1 # E: Statement is unreachable