From d3a7cb3fe4f42ae2817c168cd189759e53ddd665 Mon Sep 17 00:00:00 2001 From: Felix Scherz Date: Thu, 15 May 2025 22:01:38 +0200 Subject: [PATCH] [ty] support accessing `__builtins__` global (#18118) ## Summary The PR adds an explicit check for `"__builtins__"` during name lookup, similar to how `"__file__"` is implemented. The inferred type is `Any`. closes https://github.com/astral-sh/ty/issues/393 ## Test Plan Added a markdown test for `__builtins__`. --------- Co-authored-by: David Peter --- .../resources/mdtest/scopes/moduletype_attrs.md | 9 +++++++++ crates/ty_python_semantic/src/symbol.rs | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/crates/ty_python_semantic/resources/mdtest/scopes/moduletype_attrs.md b/crates/ty_python_semantic/resources/mdtest/scopes/moduletype_attrs.md index 152ab6edb3..140a4ac72b 100644 --- a/crates/ty_python_semantic/resources/mdtest/scopes/moduletype_attrs.md +++ b/crates/ty_python_semantic/resources/mdtest/scopes/moduletype_attrs.md @@ -15,6 +15,15 @@ reveal_type(__package__) # revealed: str | None reveal_type(__doc__) # revealed: str | None reveal_type(__spec__) # revealed: ModuleSpec | None reveal_type(__path__) # revealed: MutableSequence[str] +reveal_type(__builtins__) # revealed: Any + +import sys + +reveal_type(sys.__builtins__) # revealed: Any + +from builtins import __builtins__ as __bi__ + +reveal_type(__bi__) # revealed: Any class X: reveal_type(__name__) # revealed: str diff --git a/crates/ty_python_semantic/src/symbol.rs b/crates/ty_python_semantic/src/symbol.rs index 1d11567679..2c93e8dae5 100644 --- a/crates/ty_python_semantic/src/symbol.rs +++ b/crates/ty_python_semantic/src/symbol.rs @@ -324,6 +324,8 @@ pub(crate) fn imported_symbol<'db>( || { if name == "__getattr__" { Symbol::Unbound.into() + } else if name == "__builtins__" { + Symbol::bound(Type::any()).into() } else { KnownClass::ModuleType.to_instance(db).member(db, name) } @@ -1013,6 +1015,8 @@ mod implicit_globals { // None`. if name == "__file__" { Symbol::bound(KnownClass::Str.to_instance(db)).into() + } else if name == "__builtins__" { + Symbol::bound(Type::any()).into() } // In general we wouldn't check to see whether a symbol exists on a class before doing the // `.member()` call on the instance type -- we'd just do the `.member`() call on the instance