mirror of https://github.com/astral-sh/ruff
[ty] Avoid enforcing standalone expression for tests in f-strings (#21967)
## Summary Based on what we do elsewhere and my understanding of "standalone" here... Closes https://github.com/astral-sh/ty/issues/1865.
This commit is contained in:
parent
8e13765b57
commit
682d29c256
|
|
@ -152,6 +152,20 @@ The expressions in these string annotations aren't valid expressions in this con
|
|||
shouldn't panic.
|
||||
|
||||
```py
|
||||
# Regression test for https://github.com/astral-sh/ty/issues/1865
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_conditional: "f'{1 if 1 else 1}'"
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_boolean_expression: "f'{1 or 2}'"
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_generator_expression: "f'{(i for i in range(5))}'"
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_list_comprehension: "f'{[i for i in range(5)]}'"
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_dict_comprehension: "f'{ {i: i for i in range(5)} }'"
|
||||
# error: [fstring-type-annotation]
|
||||
stringified_fstring_with_set_comprehension: "f'{ {i for i in range(5)} }'"
|
||||
|
||||
a: "1 or 2"
|
||||
b: "(x := 1)"
|
||||
# error: [invalid-type-form]
|
||||
|
|
|
|||
|
|
@ -522,6 +522,11 @@ impl<'db> SemanticIndex<'db> {
|
|||
self.scopes_by_node[&node.node_key()]
|
||||
}
|
||||
|
||||
/// Returns the id of the scope that `node` creates, if it exists.
|
||||
pub(crate) fn try_node_scope(&self, node: NodeWithScopeRef) -> Option<FileScopeId> {
|
||||
self.scopes_by_node.get(&node.node_key()).copied()
|
||||
}
|
||||
|
||||
/// Checks if there is an import of `__future__.annotations` in the global scope, which affects
|
||||
/// the logic for type inference.
|
||||
pub(super) fn has_future_annotations(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -7926,7 +7926,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
let Some(first_comprehension) = comprehensions_iter.next() else {
|
||||
unreachable!("Comprehension must contain at least one generator");
|
||||
};
|
||||
self.infer_standalone_expression(&first_comprehension.iter, TypeContext::default());
|
||||
self.infer_maybe_standalone_expression(&first_comprehension.iter, TypeContext::default());
|
||||
|
||||
if first_comprehension.is_async {
|
||||
EvaluationMode::Async
|
||||
|
|
@ -7946,9 +7946,12 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
|
||||
let evaluation_mode = self.infer_first_comprehension_iter(generators);
|
||||
|
||||
let scope_id = self
|
||||
let Some(scope_id) = self
|
||||
.index
|
||||
.node_scope(NodeWithScopeRef::GeneratorExpression(generator));
|
||||
.try_node_scope(NodeWithScopeRef::GeneratorExpression(generator))
|
||||
else {
|
||||
return Type::unknown();
|
||||
};
|
||||
let scope = scope_id.to_scope_id(self.db(), self.file());
|
||||
let inference = infer_scope_types(self.db(), scope);
|
||||
let yield_type = inference.expression_type(elt.as_ref());
|
||||
|
|
@ -8021,9 +8024,12 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
|
||||
self.infer_first_comprehension_iter(generators);
|
||||
|
||||
let scope_id = self
|
||||
let Some(scope_id) = self
|
||||
.index
|
||||
.node_scope(NodeWithScopeRef::ListComprehension(listcomp));
|
||||
.try_node_scope(NodeWithScopeRef::ListComprehension(listcomp))
|
||||
else {
|
||||
return Type::unknown();
|
||||
};
|
||||
let scope = scope_id.to_scope_id(self.db(), self.file());
|
||||
let inference = infer_scope_types(self.db(), scope);
|
||||
let element_type = inference.expression_type(elt.as_ref());
|
||||
|
|
@ -8046,9 +8052,12 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
|
||||
self.infer_first_comprehension_iter(generators);
|
||||
|
||||
let scope_id = self
|
||||
let Some(scope_id) = self
|
||||
.index
|
||||
.node_scope(NodeWithScopeRef::DictComprehension(dictcomp));
|
||||
.try_node_scope(NodeWithScopeRef::DictComprehension(dictcomp))
|
||||
else {
|
||||
return Type::unknown();
|
||||
};
|
||||
let scope = scope_id.to_scope_id(self.db(), self.file());
|
||||
let inference = infer_scope_types(self.db(), scope);
|
||||
let key_type = inference.expression_type(key.as_ref());
|
||||
|
|
@ -8071,9 +8080,12 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
|
||||
self.infer_first_comprehension_iter(generators);
|
||||
|
||||
let scope_id = self
|
||||
let Some(scope_id) = self
|
||||
.index
|
||||
.node_scope(NodeWithScopeRef::SetComprehension(setcomp));
|
||||
.try_node_scope(NodeWithScopeRef::SetComprehension(setcomp))
|
||||
else {
|
||||
return Type::unknown();
|
||||
};
|
||||
let scope = scope_id.to_scope_id(self.db(), self.file());
|
||||
let inference = infer_scope_types(self.db(), scope);
|
||||
let element_type = inference.expression_type(elt.as_ref());
|
||||
|
|
@ -8165,14 +8177,14 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
builder.module(),
|
||||
)
|
||||
} else {
|
||||
builder.infer_standalone_expression(iter, tcx)
|
||||
builder.infer_maybe_standalone_expression(iter, tcx)
|
||||
}
|
||||
.iterate(builder.db())
|
||||
.homogeneous_element_type(builder.db())
|
||||
});
|
||||
|
||||
for expr in ifs {
|
||||
self.infer_standalone_expression(expr, TypeContext::default());
|
||||
self.infer_maybe_standalone_expression(expr, TypeContext::default());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8278,7 +8290,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
orelse,
|
||||
} = if_expression;
|
||||
|
||||
let test_ty = self.infer_standalone_expression(test, TypeContext::default());
|
||||
let test_ty = self.infer_maybe_standalone_expression(test, TypeContext::default());
|
||||
let body_ty = self.infer_expression(body, tcx);
|
||||
let orelse_ty = self.infer_expression(orelse, tcx);
|
||||
|
||||
|
|
@ -10341,7 +10353,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
|||
let ty = if index == values.len() - 1 {
|
||||
builder.infer_expression(value, TypeContext::default())
|
||||
} else {
|
||||
builder.infer_standalone_expression(value, TypeContext::default())
|
||||
builder.infer_maybe_standalone_expression(value, TypeContext::default())
|
||||
};
|
||||
|
||||
(ty, value.range())
|
||||
|
|
|
|||
Loading…
Reference in New Issue