diff --git a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/classvar.md b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/classvar.md index c92901341e..6b86ab5fab 100644 --- a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/classvar.md +++ b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/classvar.md @@ -84,13 +84,11 @@ d.a = 2 ## Too many arguments - - ```py from typing import ClassVar 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 ``` diff --git a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/final.md b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/final.md index c5f5a86375..d50277c09b 100644 --- a/crates/ty_python_semantic/resources/mdtest/type_qualifiers/final.md +++ b/crates/ty_python_semantic/resources/mdtest/type_qualifiers/final.md @@ -45,13 +45,11 @@ reveal_type(FINAL_E) # revealed: int ## Too many arguments - - ```py from typing import Final 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 ``` diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index e369f6c51b..af720ca38c 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -8659,19 +8659,14 @@ impl<'db> TypeInferenceBuilder<'db, '_> { } Type::SpecialForm( type_qualifier @ (SpecialFormType::ClassVar | SpecialFormType::Final), - ) => match slice { - ast::Expr::Tuple(..) => { - if let Some(builder) = - self.context.report_lint(&INVALID_TYPE_FORM, subscript) - { - builder.into_diagnostic(format_args!( - "Type qualifier `{type_qualifier}` \ - expects exactly one type parameter", - )); - } - Type::unknown().into() - } - _ => { + ) => { + let arguments = if let ast::Expr::Tuple(tuple) = slice { + &*tuple.elts + } else { + std::slice::from_ref(slice) + }; + let num_arguments = arguments.len(); + let type_and_qualifiers = if num_arguments == 1 { let mut type_and_qualifiers = self.infer_annotation_expression_impl(slice); match type_qualifier { @@ -8684,8 +8679,25 @@ impl<'db> TypeInferenceBuilder<'db, '_> { _ => unreachable!(), } 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 .infer_subscript_type_expression_no_store(subscript, slice, value_ty) .into(),