[red-knot] Infer Todo, not Unknown, for PEP-604 unions in annotations (#13908)

This commit is contained in:
Alex Waygood 2024-10-25 19:21:31 +01:00 committed by GitHub
parent 085a43a262
commit 5eb87aa56e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 5 deletions

View file

@ -211,7 +211,13 @@ fn declarations_ty<'db>(
let declared_ty = if let Some(second) = all_types.next() {
let mut builder = UnionBuilder::new(db).add(first);
for other in [second].into_iter().chain(all_types) {
if !first.is_equivalent_to(db, other) {
// Make sure not to emit spurious errors relating to `Type::Todo`,
// since we only infer this type due to a limitation in our current model.
//
// `Unknown` is different here, since we might infer `Unknown`
// for one of these due to a variable being defined in one possible
// control-flow branch but not another one.
if !first.is_equivalent_to(db, other) && !first.is_todo() && !other.is_todo() {
conflicting.push(other);
}
builder = builder.add(other);
@ -292,6 +298,10 @@ impl<'db> Type<'db> {
matches!(self, Type::Never)
}
pub const fn is_todo(&self) -> bool {
matches!(self, Type::Todo)
}
pub const fn into_class_literal_type(self) -> Option<ClassType<'db>> {
match self {
Type::ClassLiteral(class_type) => Some(class_type),

View file

@ -3471,6 +3471,17 @@ impl<'db> TypeInferenceBuilder<'db> {
Type::Todo
}
// TODO PEP-604 unions
ast::Expr::BinOp(binary) => {
self.infer_binary_expression(binary);
match binary.op {
// PEP-604 unions are okay
ast::Operator::BitOr => Type::Todo,
// anything else is an invalid annotation:
_ => Type::Unknown,
}
}
// 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.
@ -3482,10 +3493,6 @@ impl<'db> TypeInferenceBuilder<'db> {
self.infer_named_expression(named);
Type::Unknown
}
ast::Expr::BinOp(binary) => {
self.infer_binary_expression(binary);
Type::Unknown
}
ast::Expr::UnaryOp(unary) => {
self.infer_unary_expression(unary);
Type::Unknown