Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions mypy/stubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,9 +506,13 @@ def _verify_metaclass(

@verify.register(nodes.TypeInfo)
def verify_typeinfo(
stub: nodes.TypeInfo, runtime: MaybeMissing[type[Any]], object_path: list[str]
stub: nodes.TypeInfo,
runtime: MaybeMissing[type[Any]],
object_path: list[str],
*,
is_alias_target: bool = False,
) -> Iterator[Error]:
if stub.is_type_check_only:
if stub.is_type_check_only and not is_alias_target:
# This type only exists in stubs, we only check that the runtime part
# is missing. Other checks are not required.
if not isinstance(runtime, Missing):
Expand Down Expand Up @@ -1449,7 +1453,7 @@ def verify_typealias(
# Okay, either we couldn't construct a fullname
# or the fullname of the stub didn't match the fullname of the runtime.
# Fallback to a full structural check of the runtime vis-a-vis the stub.
yield from verify(stub_origin, runtime_origin, object_path)
yield from verify_typeinfo(stub_origin, runtime_origin, object_path, is_alias_target=True)
return
if isinstance(stub_target, mypy.types.UnionType):
# complain if runtime is not a Union or UnionType
Expand Down
11 changes: 11 additions & 0 deletions mypy/test/teststubtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2468,6 +2468,17 @@ def func2() -> None: ...
runtime="def func2() -> None: ...",
error="func2",
)
# A type that exists at runtime is allowed to alias a type marked
# as '@type_check_only' in the stubs.
yield Case(
stub="""
@type_check_only
class _X1: ...
X2 = _X1
""",
runtime="class X2: ...",
error=None,
)


def remove_color_code(s: str) -> str:
Expand Down
Loading