[ty] Fix panics when pulling types for ClassVar or Final parameterized with >1 argument (#18824)

This commit is contained in:
Alex Waygood 2025-06-20 18:06:40 +01:00 committed by GitHub
parent 073a71ca9a
commit dc160c4a49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 20 deletions

View file

@ -84,13 +84,11 @@ d.a = 2
## Too many arguments ## Too many arguments
<!-- pull-types:skip -->
```py ```py
from typing import ClassVar from typing import ClassVar
class C: class C:
# error: [invalid-type-form] "Type qualifier `typing.ClassVar` expects exactly one type parameter" # error: [invalid-type-form] "Type qualifier `typing.ClassVar` expected exactly 1 argument, got 2"
x: ClassVar[int, str] = 1 x: ClassVar[int, str] = 1
``` ```

View file

@ -45,13 +45,11 @@ reveal_type(FINAL_E) # revealed: int
## Too many arguments ## Too many arguments
<!-- pull-types:skip -->
```py ```py
from typing import Final from typing import Final
class C: class C:
# error: [invalid-type-form] "Type qualifier `typing.Final` expects exactly one type parameter" # error: [invalid-type-form] "Type qualifier `typing.Final` expected exactly 1 argument, got 2"
x: Final[int, str] = 1 x: Final[int, str] = 1
``` ```

View file

@ -8659,19 +8659,14 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
} }
Type::SpecialForm( Type::SpecialForm(
type_qualifier @ (SpecialFormType::ClassVar | SpecialFormType::Final), type_qualifier @ (SpecialFormType::ClassVar | SpecialFormType::Final),
) => match slice { ) => {
ast::Expr::Tuple(..) => { let arguments = if let ast::Expr::Tuple(tuple) = slice {
if let Some(builder) = &*tuple.elts
self.context.report_lint(&INVALID_TYPE_FORM, subscript) } else {
{ std::slice::from_ref(slice)
builder.into_diagnostic(format_args!( };
"Type qualifier `{type_qualifier}` \ let num_arguments = arguments.len();
expects exactly one type parameter", let type_and_qualifiers = if num_arguments == 1 {
));
}
Type::unknown().into()
}
_ => {
let mut type_and_qualifiers = let mut type_and_qualifiers =
self.infer_annotation_expression_impl(slice); self.infer_annotation_expression_impl(slice);
match type_qualifier { match type_qualifier {
@ -8684,8 +8679,25 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
_ => unreachable!(), _ => unreachable!(),
} }
type_and_qualifiers type_and_qualifiers
} else {
for element in arguments {
self.infer_annotation_expression_impl(element);
}
if let Some(builder) =
self.context.report_lint(&INVALID_TYPE_FORM, subscript)
{
builder.into_diagnostic(format_args!(
"Type qualifier `{type_qualifier}` expected exactly 1 argument, \
got {num_arguments}",
));
}
Type::unknown().into()
};
if slice.is_tuple_expr() {
self.store_expression_type(slice, type_and_qualifiers.inner_type());
} }
}, type_and_qualifiers
}
_ => self _ => self
.infer_subscript_type_expression_no_store(subscript, slice, value_ty) .infer_subscript_type_expression_no_store(subscript, slice, value_ty)
.into(), .into(),