mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:45:24 +00:00
[red-knot] fix scope inference with deferred types (#13204)
Test coverage for #13131 wasn't as good as I thought it was, because although we infer a lot of types in stubs in typeshed, we don't check typeshed, and therefore we don't do scope-level inference and pull all types for a scope. So we didn't really have good test coverage for scope-level inference in a stub. And because of this, I got the code for supporting that wrong, meaning that if we did scope-level inference with deferred types, we'd end up never populating the deferred types in the scope's `TypeInference`, which causes panics like #13160. Here I both add test coverage by running the corpus tests both as `.py` and as `.pyi` (which reveals the panic), and I fix the code to support deferred types in scope inference. This also revealed a problem with deferred types in generic functions, which effectively span two scopes. That problem will require a bit more thought, and I don't want to block this PR on it, so for now I just don't defer annotations on generic functions. Fixes #13160.
This commit is contained in:
parent
dfee65882b
commit
29c36a56b2
4 changed files with 27 additions and 18 deletions
|
@ -468,11 +468,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
.as_deref()
|
||||
.expect("function type params scope without type params");
|
||||
|
||||
// TODO: this should also be applied to parameter annotations.
|
||||
if !self.is_stub() {
|
||||
self.infer_optional_expression(function.returns.as_deref());
|
||||
}
|
||||
|
||||
// TODO: defer annotation resolution in stubs, with __future__.annotations, or stringified
|
||||
self.infer_optional_expression(function.returns.as_deref());
|
||||
self.infer_type_parameters(type_params);
|
||||
self.infer_parameters(&function.parameters);
|
||||
}
|
||||
|
@ -567,7 +564,9 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
self.infer_parameters(parameters);
|
||||
|
||||
// TODO: this should also be applied to parameter annotations.
|
||||
if !self.is_stub() {
|
||||
if self.is_stub() {
|
||||
self.types.has_deferred = true;
|
||||
} else {
|
||||
self.infer_optional_annotation_expression(returns.as_deref());
|
||||
}
|
||||
}
|
||||
|
@ -684,7 +683,9 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
|
||||
// inference of bases deferred in stubs
|
||||
// TODO also defer stringified generic type parameters
|
||||
if !self.is_stub() {
|
||||
if self.is_stub() {
|
||||
self.types.has_deferred = true;
|
||||
} else {
|
||||
for base in class.bases() {
|
||||
self.infer_expression(base);
|
||||
}
|
||||
|
@ -693,14 +694,12 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
|
||||
fn infer_function_deferred(&mut self, function: &ast::StmtFunctionDef) {
|
||||
if self.is_stub() {
|
||||
self.types.has_deferred = true;
|
||||
self.infer_optional_annotation_expression(function.returns.as_deref());
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_class_deferred(&mut self, class: &ast::StmtClassDef) {
|
||||
if self.is_stub() {
|
||||
self.types.has_deferred = true;
|
||||
for base in class.bases() {
|
||||
self.infer_expression(base);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue