diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md b/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md index ed566b859e..893fb3c637 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/annotated.md @@ -47,7 +47,7 @@ def _(flag: bool): def _(x: Annotated | bool): reveal_type(x) # revealed: Unknown | bool -# error: [invalid-type-form] +# error: [invalid-type-form] "Special form `typing.Annotated` expected at least 2 arguments (one type and at least one metadata element)" def _(x: Annotated[()]): reveal_type(x) # revealed: Unknown diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/callable.md b/crates/ty_python_semantic/resources/mdtest/annotations/callable.md index 49d05eb653..05adfad25b 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/callable.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/callable.md @@ -116,6 +116,21 @@ def _(c: Callable[ reveal_type(c) # revealed: (...) -> Unknown ``` +### Tuple as the second argument + +```py +from typing import Callable + +# fmt: off + +def _(c: Callable[ + int, # error: [invalid-type-form] "The first argument to `Callable` must be either a list of types, ParamSpec, Concatenate, or `...`" + (str, ) # error: [invalid-type-form] "Tuple literals are not allowed in this context in a type expression" + ] + ): + reveal_type(c) # revealed: (...) -> Unknown +``` + ### List as both arguments ```py diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md b/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md index ed4571330e..5392e38c77 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/invalid.md @@ -95,6 +95,11 @@ async def outer(): # avoid unrelated syntax errors on yield, yield from, and aw ## Invalid Collection based AST nodes +```toml +[environment] +python-version = "3.12" +``` + ```py def _( a: {1: 2}, # error: [invalid-type-form] "Dict literals are not allowed in type expressions" @@ -103,7 +108,11 @@ def _( d: [k for k in [1, 2]], # error: [invalid-type-form] "List comprehensions are not allowed in type expressions" e: {k for k in [1, 2]}, # error: [invalid-type-form] "Set comprehensions are not allowed in type expressions" f: (k for k in [1, 2]), # error: [invalid-type-form] "Generator expressions are not allowed in type expressions" - g: [int, str], # error: [invalid-type-form] "List literals are not allowed in this context in a type expression" + # error: [invalid-type-form] "List literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?" + g: [int, str], + # error: [invalid-type-form] "Tuple literals are not allowed in this context in a type expression: Did you mean `tuple[int, str]`?" + h: (int, str), + i: (), # error: [invalid-type-form] "Tuple literals are not allowed in this context in a type expression: Did you mean `tuple[()]`?" ): reveal_type(a) # revealed: Unknown reveal_type(b) # revealed: Unknown @@ -112,6 +121,17 @@ def _( reveal_type(e) # revealed: Unknown reveal_type(f) # revealed: Unknown reveal_type(g) # revealed: Unknown + reveal_type(h) # revealed: Unknown + reveal_type(i) # revealed: Unknown + +# error: [invalid-type-form] "List literals are not allowed in this context in a type expression: Did you mean `list[int]`?" +class name_0[name_2: [int]]: + pass + +# error: [invalid-type-form] "List literals are not allowed in this context in a type expression" +# error: [invalid-type-form] "Dict literals are not allowed in type expressions" +class name_4[name_1: [{}]]: + pass ``` ## Diagnostics for common errors @@ -145,3 +165,42 @@ from PIL import Image def g(x: Image): ... # error: [invalid-type-form] ``` + +### List-literal used when you meant to use a list or tuple + +```py +def _( + x: [int], # error: [invalid-type-form] +) -> [int]: # error: [invalid-type-form] + return x +``` + +```py +def _( + x: [int, str], # error: [invalid-type-form] +) -> [int, str]: # error: [invalid-type-form] + return x +``` + +### Tuple-literal used when you meant to use a tuple + +```py +def _( + x: (), # error: [invalid-type-form] +) -> (): # error: [invalid-type-form] + return x +``` + +```py +def _( + x: (int,), # error: [invalid-type-form] +) -> (int,): # error: [invalid-type-form] + return x +``` + +```py +def _( + x: (int, str), # error: [invalid-type-form] +) -> (int, str): # error: [invalid-type-form] + return x +``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_List-literal_used_wh…_(f80dbf5dd571c940).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_List-literal_used_wh…_(f80dbf5dd571c940).snap new file mode 100644 index 0000000000..6e2b255903 --- /dev/null +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_List-literal_used_wh…_(f80dbf5dd571c940).snap @@ -0,0 +1,91 @@ +--- +source: crates/ty_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: invalid.md - Tests for invalid types in type expressions - Diagnostics for common errors - List-literal used when you meant to use a list or tuple +mdtest path: crates/ty_python_semantic/resources/mdtest/annotations/invalid.md +--- + +# Python source files + +## mdtest_snippet.py + +``` +1 | def _( +2 | x: [int], # error: [invalid-type-form] +3 | ) -> [int]: # error: [invalid-type-form] +4 | return x +5 | def _( +6 | x: [int, str], # error: [invalid-type-form] +7 | ) -> [int, str]: # error: [invalid-type-form] +8 | return x +``` + +# Diagnostics + +``` +error[invalid-type-form]: List literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:2:8 + | +1 | def _( +2 | x: [int], # error: [invalid-type-form] + | ^^^^^ Did you mean `list[int]`? +3 | ) -> [int]: # error: [invalid-type-form] +4 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: List literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:3:6 + | +1 | def _( +2 | x: [int], # error: [invalid-type-form] +3 | ) -> [int]: # error: [invalid-type-form] + | ^^^^^ Did you mean `list[int]`? +4 | return x +5 | def _( + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: List literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:6:8 + | +4 | return x +5 | def _( +6 | x: [int, str], # error: [invalid-type-form] + | ^^^^^^^^^^ Did you mean `tuple[int, str]`? +7 | ) -> [int, str]: # error: [invalid-type-form] +8 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: List literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:7:6 + | +5 | def _( +6 | x: [int, str], # error: [invalid-type-form] +7 | ) -> [int, str]: # error: [invalid-type-form] + | ^^^^^^^^^^ Did you mean `tuple[int, str]`? +8 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` diff --git a/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_Tuple-literal_used_w…_(f61204fc81905069).snap b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_Tuple-literal_used_w…_(f61204fc81905069).snap new file mode 100644 index 0000000000..5e268cd80c --- /dev/null +++ b/crates/ty_python_semantic/resources/mdtest/snapshots/invalid.md_-_Tests_for_invalid_ty…_-_Diagnostics_for_comm…_-_Tuple-literal_used_w…_(f61204fc81905069).snap @@ -0,0 +1,129 @@ +--- +source: crates/ty_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: invalid.md - Tests for invalid types in type expressions - Diagnostics for common errors - Tuple-literal used when you meant to use a tuple +mdtest path: crates/ty_python_semantic/resources/mdtest/annotations/invalid.md +--- + +# Python source files + +## mdtest_snippet.py + +``` + 1 | def _( + 2 | x: (), # error: [invalid-type-form] + 3 | ) -> (): # error: [invalid-type-form] + 4 | return x + 5 | def _( + 6 | x: (int,), # error: [invalid-type-form] + 7 | ) -> (int,): # error: [invalid-type-form] + 8 | return x + 9 | def _( +10 | x: (int, str), # error: [invalid-type-form] +11 | ) -> (int, str): # error: [invalid-type-form] +12 | return x +``` + +# Diagnostics + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:2:8 + | +1 | def _( +2 | x: (), # error: [invalid-type-form] + | ^^ Did you mean `tuple[()]`? +3 | ) -> (): # error: [invalid-type-form] +4 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:3:6 + | +1 | def _( +2 | x: (), # error: [invalid-type-form] +3 | ) -> (): # error: [invalid-type-form] + | ^^ Did you mean `tuple[()]`? +4 | return x +5 | def _( + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:6:8 + | +4 | return x +5 | def _( +6 | x: (int,), # error: [invalid-type-form] + | ^^^^^^ Did you mean `tuple[int]`? +7 | ) -> (int,): # error: [invalid-type-form] +8 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:7:6 + | +5 | def _( +6 | x: (int,), # error: [invalid-type-form] +7 | ) -> (int,): # error: [invalid-type-form] + | ^^^^^^ Did you mean `tuple[int]`? +8 | return x +9 | def _( + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:10:8 + | + 8 | return x + 9 | def _( +10 | x: (int, str), # error: [invalid-type-form] + | ^^^^^^^^^^ Did you mean `tuple[int, str]`? +11 | ) -> (int, str): # error: [invalid-type-form] +12 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` + +``` +error[invalid-type-form]: Tuple literals are not allowed in this context in a type expression + --> src/mdtest_snippet.py:11:6 + | + 9 | def _( +10 | x: (int, str), # error: [invalid-type-form] +11 | ) -> (int, str): # error: [invalid-type-form] + | ^^^^^^^^^^ Did you mean `tuple[int, str]`? +12 | return x + | +info: See the following page for a reference on valid type expressions: +info: https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions +info: rule `invalid-type-form` is enabled by default + +``` diff --git a/crates/ty_python_semantic/src/types/diagnostic.rs b/crates/ty_python_semantic/src/types/diagnostic.rs index 7233c81b6e..8bcf8a8bb0 100644 --- a/crates/ty_python_semantic/src/types/diagnostic.rs +++ b/crates/ty_python_semantic/src/types/diagnostic.rs @@ -1878,11 +1878,14 @@ pub(crate) fn report_invalid_arguments_to_callable( )); } -pub(crate) fn add_type_expression_reference_link(mut diag: LintDiagnosticGuard) { +pub(crate) fn add_type_expression_reference_link<'db, 'ctx>( + mut diag: LintDiagnosticGuard<'db, 'ctx>, +) -> LintDiagnosticGuard<'db, 'ctx> { diag.info("See the following page for a reference on valid type expressions:"); diag.info( "https://typing.python.org/en/latest/spec/annotations.html#type-and-annotation-expressions", ); + diag } pub(crate) fn report_runtime_check_against_non_runtime_checkable_protocol( diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index 6650552b1e..8de15d66f4 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -33,6 +33,7 @@ //! the query cycle until a fixed-point is reached. Salsa has a built-in fixed limit on the number //! of iterations, so if we fail to converge, Salsa will eventually panic. (This should of course //! be considered a bug.) + use itertools::{Either, Itertools}; use ruff_db::diagnostic::{Annotation, DiagnosticId, Severity}; use ruff_db::files::File; @@ -95,11 +96,11 @@ use crate::types::unpacker::{UnpackResult, Unpacker}; use crate::types::{ BareTypeAliasType, CallDunderError, CallableType, ClassLiteral, ClassType, DataclassParams, DynamicType, GenericAlias, IntersectionBuilder, IntersectionType, KnownClass, - KnownInstanceType, MemberLookupPolicy, MetaclassCandidate, PEP695TypeAliasType, Parameter, - ParameterForm, Parameters, SpecialFormType, StringLiteralType, SubclassOfType, Truthiness, - TupleType, Type, TypeAliasType, TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, - TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, TypeVarVariance, UnionBuilder, - UnionType, binding_type, todo_type, + KnownInstanceType, LintDiagnosticGuard, MemberLookupPolicy, MetaclassCandidate, + PEP695TypeAliasType, Parameter, ParameterForm, Parameters, SpecialFormType, StringLiteralType, + SubclassOfType, Truthiness, TupleType, Type, TypeAliasType, TypeAndQualifiers, + TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints, TypeVarInstance, TypeVarKind, + TypeVarVariance, UnionBuilder, UnionType, binding_type, todo_type, }; use crate::unpack::{Unpack, UnpackPosition}; use crate::util::subscript::{PyIndex, PySlice}; @@ -8308,7 +8309,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.store_expression_type(slice, inner_annotation_ty.inner_type()); inner_annotation_ty } else { - self.infer_type_expression(slice); + for argument in arguments { + self.infer_expression(argument); + } + self.store_expression_type(slice, Type::unknown()); TypeAndQualifiers::unknown() } } else { @@ -8416,15 +8420,15 @@ impl<'db> TypeInferenceBuilder<'db, '_> { } fn report_invalid_type_expression( - &mut self, + &self, expression: &ast::Expr, message: std::fmt::Arguments, - ) -> Type<'db> { - if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, expression) { - let diag = builder.into_diagnostic(message); - diagnostic::add_type_expression_reference_link(diag); - } - Type::unknown() + ) -> Option { + self.context + .report_lint(&INVALID_TYPE_FORM, expression) + .map(|builder| { + diagnostic::add_type_expression_reference_link(builder.into_diagnostic(message)) + }) } /// Infer the type of a type expression without storing the result. @@ -8511,56 +8515,126 @@ impl<'db> TypeInferenceBuilder<'db, '_> { // TODO: add a subdiagnostic linking to type-expression grammar // and stating that it is only valid in `typing.Literal[]` or `typing.Annotated[]` - ast::Expr::BytesLiteral(_) => self.report_invalid_type_expression( - expression, - format_args!("Bytes literals are not allowed in this context in a type expression"), - ), + ast::Expr::BytesLiteral(_) => { + self.report_invalid_type_expression( + expression, + format_args!( + "Bytes literals are not allowed in this context in a type expression" + ), + ); + Type::unknown() + } - // TODO: add a subdiagnostic linking to type-expression grammar - // and stating that it is only valid in `typing.Literal[]` or `typing.Annotated[]` ast::Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Int(_), .. - }) => self.report_invalid_type_expression( - expression, - format_args!("Int literals are not allowed in this context in a type expression"), - ), + }) => { + self.report_invalid_type_expression( + expression, + format_args!( + "Int literals are not allowed in this context in a type expression" + ), + ); + + Type::unknown() + } ast::Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Float(_), .. - }) => self.report_invalid_type_expression( - expression, - format_args!("Float literals are not allowed in type expressions"), - ), + }) => { + self.report_invalid_type_expression( + expression, + format_args!("Float literals are not allowed in type expressions"), + ); + Type::unknown() + } ast::Expr::NumberLiteral(ast::ExprNumberLiteral { value: ast::Number::Complex { .. }, .. - }) => self.report_invalid_type_expression( - expression, - format_args!("Complex literals are not allowed in type expressions"), - ), - - // TODO: add a subdiagnostic linking to type-expression grammar - // and stating that it is only valid in `typing.Literal[]` or `typing.Annotated[]` - ast::Expr::BooleanLiteral(_) => self.report_invalid_type_expression( - expression, - format_args!( - "Boolean literals are not allowed in this context in a type expression" - ), - ), - - // TODO: add a subdiagnostic linking to type-expression grammar - // and stating that it is only valid as first argument to `typing.Callable[]` - ast::Expr::List(list) => { - self.infer_list_expression(list); + }) => { self.report_invalid_type_expression( + expression, + format_args!("Complex literals are not allowed in type expressions"), + ); + Type::unknown() + } + + ast::Expr::BooleanLiteral(_) => { + self.report_invalid_type_expression( + expression, + format_args!( + "Boolean literals are not allowed in this context in a type expression" + ), + ); + Type::unknown() + } + + ast::Expr::List(list) => { + let db = self.db(); + + let inner_types: Vec> = list + .iter() + .map(|element| self.infer_type_expression(element)) + .collect(); + + if let Some(mut diagnostic) = self.report_invalid_type_expression( expression, format_args!( "List literals are not allowed in this context in a type expression" ), - ) + ) { + if !inner_types.iter().any(|ty| { + matches!( + ty, + Type::Dynamic(DynamicType::Todo(_) | DynamicType::Unknown) + ) + }) { + let hinted_type = if list.len() == 1 { + KnownClass::List.to_specialized_instance(db, inner_types) + } else { + TupleType::from_elements(db, inner_types) + }; + + diagnostic.set_primary_message(format_args!( + "Did you mean `{}`?", + hinted_type.display(self.db()), + )); + } + } + Type::unknown() + } + + ast::Expr::Tuple(tuple) => { + let inner_types: Vec> = tuple + .elts + .iter() + .map(|expr| self.infer_type_expression(expr)) + .collect(); + + if tuple.parenthesized { + if let Some(mut diagnostic) = self.report_invalid_type_expression( + expression, + format_args!( + "Tuple literals are not allowed in this context in a type expression" + ), + ) { + if !inner_types.iter().any(|ty| { + matches!( + ty, + Type::Dynamic(DynamicType::Todo(_) | DynamicType::Unknown) + ) + }) { + let hinted_type = TupleType::from_elements(self.db(), inner_types); + diagnostic.set_primary_message(format_args!( + "Did you mean `{}`?", + hinted_type.display(self.db()), + )); + } + } + } + Type::unknown() } ast::Expr::BoolOp(bool_op) => { @@ -8568,7 +8642,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Boolean operations are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Named(named) => { @@ -8576,7 +8651,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Named expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::UnaryOp(unary) => { @@ -8584,7 +8660,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Unary operations are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Lambda(lambda_expression) => { @@ -8592,7 +8669,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("`lambda` expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::If(if_expression) => { @@ -8600,7 +8678,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("`if` expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Dict(dict) => { @@ -8608,7 +8687,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Dict literals are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Set(set) => { @@ -8616,7 +8696,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Set literals are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::DictComp(dictcomp) => { @@ -8624,7 +8705,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Dict comprehensions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::ListComp(listcomp) => { @@ -8632,7 +8714,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("List comprehensions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::SetComp(setcomp) => { @@ -8640,7 +8723,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Set comprehensions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Generator(generator) => { @@ -8648,7 +8732,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Generator expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Await(await_expression) => { @@ -8656,7 +8741,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("`await` expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Yield(yield_expression) => { @@ -8664,7 +8750,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("`yield` expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::YieldFrom(yield_from) => { @@ -8672,7 +8759,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("`yield from` expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Compare(compare) => { @@ -8680,7 +8768,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Comparison expressions are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Call(call_expr) => { @@ -8688,7 +8777,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Function calls are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::FString(fstring) => { @@ -8696,7 +8786,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("F-strings are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::TString(tstring) => { @@ -8704,7 +8795,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("T-strings are not allowed in type expressions"), - ) + ); + Type::unknown() } ast::Expr::Slice(slice) => { @@ -8712,7 +8804,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> { self.report_invalid_type_expression( expression, format_args!("Slices are not allowed in type expressions"), - ) + ); + Type::unknown() } // ================================================================================= @@ -8724,11 +8817,6 @@ impl<'db> TypeInferenceBuilder<'db, '_> { todo_type!("ellipsis literal in type expression") } - ast::Expr::Tuple(tuple) => { - self.infer_tuple_expression(tuple); - Type::unknown() - } - ast::Expr::Starred(starred) => { self.infer_starred_expression(starred); todo_type!("PEP 646") @@ -9076,7 +9164,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> { } let [type_expr, metadata @ ..] = &arguments[..] else { - self.infer_type_expression(arguments_slice); + for argument in arguments { + self.infer_expression(argument); + } + self.store_expression_type(arguments_slice, Type::unknown()); return Type::unknown(); };