diff --git a/crates/vm/src/stdlib/_typing.rs b/crates/vm/src/stdlib/_typing.rs index 863dd8367..fad43d8eb 100644 --- a/crates/vm/src/stdlib/_typing.rs +++ b/crates/vm/src/stdlib/_typing.rs @@ -321,7 +321,9 @@ pub(crate) mod decl { return module.clone(); } // Fall back to compute_value's __module__ (like PyFunction_GetModule) - if let Ok(module) = self.compute_value.get_attr("__module__", vm) { + if self.is_lazy + && let Ok(module) = self.compute_value.get_attr("__module__", vm) + { return module; } vm.ctx.none() diff --git a/extra_tests/snippets/stdlib_typing.py b/extra_tests/snippets/stdlib_typing.py index 4082d683f..8ba64844c 100644 --- a/extra_tests/snippets/stdlib_typing.py +++ b/extra_tests/snippets/stdlib_typing.py @@ -63,3 +63,24 @@ try: repr(nested) except RecursionError: pass + + +# Eager aliases without a caller module never inspect their aliased value. +alias_module_lookups = [] + + +class AliasModuleValue: + @property + def __module__(self): + alias_module_lookups.append(True) + return "unexpected_value_module" + + +for alias_value in (int, AliasModuleValue()): + alias_namespace = {"value": alias_value} + exec( + "from typing import TypeAliasType; alias = TypeAliasType('Alias', value)", + alias_namespace, + ) + assert alias_namespace["alias"].__module__ is None +assert alias_module_lookups == []