Add remaining sites

This commit is contained in:
Charlie Marsh 2025-12-15 21:36:03 -05:00
parent 2d50bcf145
commit 04651bc1e4
3 changed files with 39 additions and 12 deletions

View File

@ -155,6 +155,16 @@ shouldn't panic.
# 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)"

View File

@ -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 {

View File

@ -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());
}
}
@ -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())