Compare commits

...

2 Commits

Author SHA1 Message Date
Alex Waygood
4d0b56393f wip 2026-01-14 14:28:47 +00:00
Alex Waygood
50fbd93af9 [ty] Filter TypeVar/ParamSpec/TypeVarTuple definitions out of the builtins fallback 2026-01-14 14:28:06 +00:00
3 changed files with 38 additions and 1 deletions

View File

@@ -137,3 +137,5 @@ foo: int
baz: str
chr: int
```
## `TypeVar`/`ParamSpec`/`TypeVarTuple`

View File

@@ -1090,6 +1090,15 @@ impl<'db> Type<'db> {
Type::FunctionLiteral(f) => {
f.has_known_decorator(db, FunctionDecorators::TYPE_CHECK_ONLY)
}
Type::TypeAlias(alias) => alias.value_type(db).is_type_check_only(db),
Type::Union(union) => union
.elements(db)
.iter()
.all(|ty| ty.is_type_check_only(db)),
Type::Intersection(intersection) => intersection
.positive(db)
.iter()
.any(|element| element.is_type_check_only(db)),
_ => false,
}
}

View File

@@ -10298,7 +10298,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`...