From c548ef20278f18ec9e88796fd0a1c4b5b5395a40 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Thu, 11 Dec 2025 11:25:37 -0500 Subject: [PATCH] [ty] Squash false positive logs for failing to find `builtins` as a real module I recently started noticing this showing up in the logs for every scope based completion request: ``` 2025-12-11 11:25:35.704329935 DEBUG request{id=29 method="textDocument/completion"}:map_stub_definition: Module `builtins` not found while looking in parent dirs ``` And in particular, it was repeated several times. This was confusing to me because, well, of course `builtins` should resolve. This particular code path comes from looking for the docstrings of completion items. This involves a spelunking that ultimately tries to resolve a "real" module if the stub doesn't have available docstrings. But I guess there is no "real" `builtins` module, so `resolve_real_module` fails. Which is fine, but the noisy logs were annoying since this is an expected case. So here, we carve out a short circuit for `builtins` and also improve the log message. --- .../ty_python_semantic/src/module_resolver/resolver.rs | 9 ++++++++- crates/ty_python_semantic/src/types/ide_support.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/ty_python_semantic/src/module_resolver/resolver.rs b/crates/ty_python_semantic/src/module_resolver/resolver.rs index 123b4ac31e..60b565a564 100644 --- a/crates/ty_python_semantic/src/module_resolver/resolver.rs +++ b/crates/ty_python_semantic/src/module_resolver/resolver.rs @@ -265,7 +265,14 @@ fn desperately_resolve_module<'db>( let _span = tracing::trace_span!("desperately_resolve_module", %name).entered(); let Some(resolved) = desperately_resolve_name(db, importing_file, name, mode) else { - tracing::debug!("Module `{name}` not found while looking in parent dirs"); + let extra = match module_name.mode(db) { + ModuleResolveMode::StubsAllowed => "neither stub nor real module file", + ModuleResolveMode::StubsNotAllowed => "stubs not allowed", + ModuleResolveMode::StubsNotAllowedSomeShadowingAllowed => { + "stubs not allowed but some shadowing allowed" + } + }; + tracing::debug!("Module `{name}` not found while looking in parent dirs ({extra})"); return None; }; diff --git a/crates/ty_python_semantic/src/types/ide_support.rs b/crates/ty_python_semantic/src/types/ide_support.rs index 5162e8a13d..398084a113 100644 --- a/crates/ty_python_semantic/src/types/ide_support.rs +++ b/crates/ty_python_semantic/src/types/ide_support.rs @@ -843,6 +843,7 @@ mod resolve_definition { use ruff_db::system::SystemPath; use ruff_db::vendored::VendoredPathBuf; use ruff_python_ast as ast; + use ruff_python_stdlib::sys::is_builtin_module; use rustc_hash::FxHashSet; use tracing::trace; @@ -1160,6 +1161,14 @@ mod resolve_definition { // here because there isn't really an importing file. However this `resolve_real_module` // can be understood as essentially `import .`, which is also what `file_to_module` is, // so this is in fact exactly the file we want to consider the importer. + // + // ... unless we have a builtin module. i.e., A module embedded + // into the interpreter. In which case, all we have are stubs. + // `resolve_real_module` will always return `None` for this case, but + // it will emit false positive logs. And this saves us some work. + if is_builtin_module(db.python_version().minor, stub_module.name(db)) { + return None; + } let real_module = resolve_real_module(db, stub_file_for_module_lookup, stub_module.name(db))?; trace!("Found real module: {}", real_module.name(db));