Skip to content

[red-knot] Emit errors for more AST nodes that are invalid (or only valid in specific contexts) in type expressions #16816

Closed
@AlexWaygood

Description

@AlexWaygood

Some AST nodes are always invalid in type expressions; we should emit an invalid-type-form diagnostic in red-knot if we see one of these in a type expression. This applies to all of these branches:

// Forms which are invalid in the context of annotation expressions: we infer their
// nested expressions as normal expressions, but the type of the top-level expression is
// always `Type::unknown` in these cases.
ast::Expr::BoolOp(bool_op) => {
self.infer_boolean_expression(bool_op);
Type::unknown()
}
ast::Expr::Named(named) => {
self.infer_named_expression(named);
Type::unknown()
}
ast::Expr::UnaryOp(unary) => {
self.infer_unary_expression(unary);
Type::unknown()
}
ast::Expr::Lambda(lambda_expression) => {
self.infer_lambda_expression(lambda_expression);
Type::unknown()
}
ast::Expr::If(if_expression) => {
self.infer_if_expression(if_expression);
Type::unknown()
}
ast::Expr::Dict(dict) => {
self.infer_dict_expression(dict);
Type::unknown()
}
ast::Expr::Set(set) => {
self.infer_set_expression(set);
Type::unknown()
}
ast::Expr::ListComp(listcomp) => {
self.infer_list_comprehension_expression(listcomp);
Type::unknown()
}
ast::Expr::SetComp(setcomp) => {
self.infer_set_comprehension_expression(setcomp);
Type::unknown()
}
ast::Expr::DictComp(dictcomp) => {
self.infer_dict_comprehension_expression(dictcomp);
Type::unknown()
}
ast::Expr::Generator(generator) => {
self.infer_generator_expression(generator);
Type::unknown()
}
ast::Expr::Await(await_expression) => {
self.infer_await_expression(await_expression);
Type::unknown()
}
ast::Expr::Yield(yield_expression) => {
self.infer_yield_expression(yield_expression);
Type::unknown()
}
ast::Expr::YieldFrom(yield_from) => {
self.infer_yield_from_expression(yield_from);
Type::unknown()
}
ast::Expr::Compare(compare) => {
self.infer_compare_expression(compare);
Type::unknown()
}
ast::Expr::Call(call_expr) => {
self.infer_call_expression(call_expr);
Type::unknown()
}
ast::Expr::FString(fstring) => {
self.infer_fstring_expression(fstring);
Type::unknown()
}
ast::Expr::List(list) => {
self.infer_list_expression(list);
Type::unknown()
}
ast::Expr::Tuple(tuple) => {
self.infer_tuple_expression(tuple);
Type::unknown()
}
ast::Expr::Slice(slice) => {
self.infer_slice_expression(slice);
Type::unknown()
}
ast::Expr::IpyEscapeCommand(_) => todo!("Implement Ipy escape command support"),

Similarly, an ellipsis literal is only valid in very specific contexts in type expressions: as part of a Callable type expression (e.g. Callable[..., int] or as part of a tuple-subscript type expression (e.g. tuple[int, ...]. We should never call infer_type_expression_no_store with an ellipsis literal node if we're visiting a sub-expression in either of those type expressions. So we should also be emitting a diagnostic if we hit this branch:

// TODO: an Ellipsis literal *on its own* does not have any meaning in annotation
// expressions, but is meaningful in the context of a number of special forms.
ast::Expr::EllipsisLiteral(_literal) => {
todo_type!("ellipsis literal in type expression")
}

This would be a good contributor task. The changes required will be very similar to the ones done in #16765. @MatthewMckee4, you might be interested in taking this one on, possibly? :-)

Metadata

Metadata

Assignees

Labels

help wantedContributions especially welcometyMulti-file analysis & type inference

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions