From 476ecbfc6d4a965616a5a65ba2929bac114f392e Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Wed, 5 Nov 2025 15:15:52 -0500 Subject: [PATCH] [ty] Filter `TypeVar`/`ParamSpec`/`TypeVarTuple` definitions out of the builtins fallback --- .../src/types/infer/builder.rs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index b7608bbfff..3a7aa12143 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -7421,7 +7421,33 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { if Some(self.scope()) == builtins_module_scope(db) { Place::Undefined.into() } else { - builtins_symbol(db, symbol_name) + let possible_fallback = builtins_symbol(db, symbol_name); + let Some(fallback_type) = possible_fallback.ignore_possibly_undefined() else { + return possible_fallback; + }; + // Exclude `TypeVar`/`ParamSpec`/`TypeVarTuple` definitions from the + // builtin-scope fallback. These don't exist at runtime. And pragmatically, + // unlike e.g. typeshed's protocols/typeddicts/type aliases, it's never + // actually useful to reuse one of typeshed's typevarlike definitions from + // `builtins.pyi`, even in an `if TYPE_CHECKING` block. + match fallback_type { + Type::NominalInstance(instance) + if matches!( + instance.known_class(db), + Some( + KnownClass::TypeVar + | KnownClass::ParamSpec + | KnownClass::TypeVarTuple + ) + ) => + { + Place::Undefined.into() + } + Type::KnownInstance(KnownInstanceType::TypeVar(_)) => { + Place::Undefined.into() + } + _ => possible_fallback, + } } }) // Still not found? It might be `reveal_type`...