diff --git a/crates/red_knot_project/resources/test/corpus/95_annotation_string_tuple.py b/crates/red_knot_project/resources/test/corpus/95_annotation_string_tuple.py new file mode 100644 index 0000000000..84681b729e --- /dev/null +++ b/crates/red_knot_project/resources/test/corpus/95_annotation_string_tuple.py @@ -0,0 +1 @@ +t: "tuple[list[int]]" diff --git a/crates/red_knot_python_semantic/resources/primer/bad.txt b/crates/red_knot_python_semantic/resources/primer/bad.txt index 24a74e3ac9..bf180717b9 100644 --- a/crates/red_knot_python_semantic/resources/primer/bad.txt +++ b/crates/red_knot_python_semantic/resources/primer/bad.txt @@ -1,35 +1,30 @@ Expression # cycle panic (signature_) Tanjun # cycle panic (signature_) -aiohttp # missing expression ID -alerta # missing expression ID altair # cycle panics (try_metaclass_) antidote # hangs / slow artigraph # cycle panics (value_type_) colour # cycle panics (try_metaclass_) core # cycle panics (value_type_) -cpython # missing expression ID, access to field whilst being initialized, too many cycle iterations +cpython # access to field whilst being initialized, too many cycle iterations discord.py # some kind of hang, only when multi-threaded? freqtrade # cycle panics (try_metaclass_) hydpy # cycle panics (try_metaclass_) ibis # cycle panics (try_metaclass_) manticore # stack overflow materialize # stack overflow -meson # missing expression ID mypy # cycle panic (signature_) pandas # slow pandas-stubs # cycle panics (try_metaclass_) pandera # cycle panics (try_metaclass_) prefect # slow -pytest # cycle panics (signature_), missing expression ID +pytest # cycle panics (signature_) pywin32 # bad use-def map (binding with definitely-visible unbound) schemathesis # cycle panics (signature_) scikit-learn # success, but mypy-primer hangs processing the output -scipy # missing expression ID +scipy # missing expression type ("expression should belong to this TypeInference region") spack # success, but mypy-primer hangs processing the output spark # cycle panics (try_metaclass_) -sphinx # missing expression ID -steam.py # missing expression ID +steam.py # cycle panics (try_metaclass_), often hangs when multi-threaded streamlit # cycle panic (signature_) sympy # stack overflow -trio # missing expression ID xarray # cycle panics (try_metaclass_) diff --git a/crates/red_knot_python_semantic/resources/primer/good.txt b/crates/red_knot_python_semantic/resources/primer/good.txt index f767557707..0455d5c8fe 100644 --- a/crates/red_knot_python_semantic/resources/primer/good.txt +++ b/crates/red_knot_python_semantic/resources/primer/good.txt @@ -2,10 +2,12 @@ AutoSplit PyGithub PyWinCtl SinbadCogs +aiohttp aiohttp-devtools aioredis aiortc alectryon +alerta anyio apprise arviz @@ -47,6 +49,7 @@ jinja koda-validate kopf kornia +meson mitmproxy mkdocs mkosi @@ -92,11 +95,13 @@ scrapy setuptools sockeye speedrun.com_global_scoreboard_webapp +sphinx starlette static-frame stone strawberry tornado +trio twine typeshed-stats urllib3 diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 0d2e934ee6..74fd48d2e7 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -7615,7 +7615,7 @@ impl<'db> TypeInferenceBuilder<'db> { fn element_could_alter_type_of_whole_tuple( element: &ast::Expr, element_ty: Type, - builder: &TypeInferenceBuilder, + builder: &mut TypeInferenceBuilder, ) -> bool { if !element_ty.is_todo() { return false; @@ -7624,10 +7624,15 @@ impl<'db> TypeInferenceBuilder<'db> { match element { ast::Expr::EllipsisLiteral(_) | ast::Expr::Starred(_) => true, ast::Expr::Subscript(ast::ExprSubscript { value, .. }) => { - matches!( - builder.expression_type(value), - Type::KnownInstance(KnownInstanceType::Unpack) - ) + let value_ty = if builder.deferred_state.in_string_annotation() { + // Using `.expression_type` does not work in string annotations, because + // we do not store types for sub-expressions. Re-infer the type here. + builder.infer_expression(value) + } else { + builder.expression_type(value) + }; + + matches!(value_ty, Type::KnownInstance(KnownInstanceType::Unpack)) } _ => false, }