mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
[red-knot] Resolve function annotations before adding function symbol (#13084)
This PR has the `SemanticIndexBuilder` visit function definition annotations before adding the function symbol/name to the builder. For example, the following snippet no longer causes a panic: ```python def bool(x) -> bool: Return True ``` Note: This fix changes the ordering of the global symbol table. Closes #13069
This commit is contained in:
parent
d19fd1b91c
commit
8c09496b07
5 changed files with 30 additions and 16 deletions
|
@ -575,7 +575,7 @@ def f(a: str, /, b: str, c: int = 1, *args, d: int = 2, **kwargs):
|
|||
let index = semantic_index(&db, file);
|
||||
let global_table = symbol_table(&db, global_scope(&db, file));
|
||||
|
||||
assert_eq!(names(&global_table), vec!["f", "str", "int"]);
|
||||
assert_eq!(names(&global_table), vec!["str", "int", "f"]);
|
||||
|
||||
let [(function_scope_id, _function_scope)] = index
|
||||
.child_scopes(FileScopeId::global())
|
||||
|
|
|
@ -392,20 +392,6 @@ where
|
|||
self.visit_decorator(decorator);
|
||||
}
|
||||
|
||||
let symbol = self
|
||||
.add_or_update_symbol(function_def.name.id.clone(), SymbolFlags::IS_DEFINED);
|
||||
self.add_definition(symbol, function_def);
|
||||
|
||||
// The default value of the parameters needs to be evaluated in the
|
||||
// enclosing scope.
|
||||
for default in function_def
|
||||
.parameters
|
||||
.iter_non_variadic_params()
|
||||
.filter_map(|param| param.default.as_deref())
|
||||
{
|
||||
self.visit_expr(default);
|
||||
}
|
||||
|
||||
self.with_type_params(
|
||||
NodeWithScopeRef::FunctionTypeParameters(function_def),
|
||||
function_def.type_params.as_deref(),
|
||||
|
@ -426,6 +412,21 @@ where
|
|||
builder.pop_scope()
|
||||
},
|
||||
);
|
||||
// The default value of the parameters needs to be evaluated in the
|
||||
// enclosing scope.
|
||||
for default in function_def
|
||||
.parameters
|
||||
.iter_non_variadic_params()
|
||||
.filter_map(|param| param.default.as_deref())
|
||||
{
|
||||
self.visit_expr(default);
|
||||
}
|
||||
// The symbol for the function name itself has to be evaluated
|
||||
// at the end to match the runtime evaluation of parameter defaults
|
||||
// and return-type annotations.
|
||||
let symbol = self
|
||||
.add_or_update_symbol(function_def.name.id.clone(), SymbolFlags::IS_DEFINED);
|
||||
self.add_definition(symbol, function_def);
|
||||
}
|
||||
ast::Stmt::ClassDef(class) => {
|
||||
for decorator in &class.decorator_list {
|
||||
|
|
|
@ -374,9 +374,9 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
let Some(type_params) = function.type_params.as_deref() else {
|
||||
panic!("function type params scope without type params");
|
||||
};
|
||||
self.infer_optional_expression(function.returns.as_deref());
|
||||
self.infer_type_parameters(type_params);
|
||||
self.infer_parameters(&function.parameters);
|
||||
self.infer_optional_expression(function.returns.as_deref());
|
||||
}
|
||||
|
||||
fn infer_function_body(&mut self, function: &ast::StmtFunctionDef) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
def bool(x) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class MyClass: ...
|
||||
|
||||
|
||||
def MyClass() -> MyClass: ...
|
||||
|
||||
|
||||
def x(self) -> x: ...
|
|
@ -0,0 +1,2 @@
|
|||
def bool(x=bool):
|
||||
return x
|
Loading…
Add table
Add a link
Reference in a new issue