From 1f7a29d3476b7c869789b68388daa4f4270374b2 Mon Sep 17 00:00:00 2001 From: David Peter Date: Fri, 7 Feb 2025 13:00:04 +0100 Subject: [PATCH] [red-knot] Unpacker: Make invariant explicit and directly return a Type (#16018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Do not return `Option>` from `Unpacker::get`, but just `Type`. Panic otherwise. - Rename `Unpacker::get` to `Unpacker::expression_type` --- crates/red_knot_python_semantic/src/types.rs | 5 ++--- crates/red_knot_python_semantic/src/types/infer.rs | 4 ++-- crates/red_knot_python_semantic/src/types/unpacker.rs | 10 ++++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/red_knot_python_semantic/src/types.rs b/crates/red_knot_python_semantic/src/types.rs index 360b9a5546..d9d8ac2e9e 100644 --- a/crates/red_knot_python_semantic/src/types.rs +++ b/crates/red_knot_python_semantic/src/types.rs @@ -4254,9 +4254,8 @@ impl<'db> Class<'db> { // (.., self.name, ..) = // [.., self.name, ..] = - let inferred_ty = infer_unpack_types(db, *unpack) - .get(*attribute_expression_id) - .expect("Failed to look up type of attribute in unpack assignment"); + let inferred_ty = + infer_unpack_types(db, *unpack).expression_type(*attribute_expression_id); union_of_inferred_types = union_of_inferred_types.add(inferred_ty); } } diff --git a/crates/red_knot_python_semantic/src/types/infer.rs b/crates/red_knot_python_semantic/src/types/infer.rs index 6f224b398d..3d4d9ad75b 100644 --- a/crates/red_knot_python_semantic/src/types/infer.rs +++ b/crates/red_knot_python_semantic/src/types/infer.rs @@ -2085,7 +2085,7 @@ impl<'db> TypeInferenceBuilder<'db> { } let name_ast_id = name.scoped_expression_id(self.db(), self.scope()); - unpacked.get(name_ast_id).unwrap_or(Type::unknown()) + unpacked.expression_type(name_ast_id) } TargetKind::Name => { if self.in_stub() && value.is_ellipsis_literal_expr() { @@ -2356,7 +2356,7 @@ impl<'db> TypeInferenceBuilder<'db> { self.context.extend(unpacked); } let name_ast_id = name.scoped_expression_id(self.db(), self.scope()); - unpacked.get(name_ast_id).unwrap_or(Type::unknown()) + unpacked.expression_type(name_ast_id) } TargetKind::Name => iterable_ty .iterate(self.db()) diff --git a/crates/red_knot_python_semantic/src/types/unpacker.rs b/crates/red_knot_python_semantic/src/types/unpacker.rs index f7782d4e6b..bd5baa982d 100644 --- a/crates/red_knot_python_semantic/src/types/unpacker.rs +++ b/crates/red_knot_python_semantic/src/types/unpacker.rs @@ -268,8 +268,14 @@ pub(crate) struct UnpackResult<'db> { } impl<'db> UnpackResult<'db> { - pub(crate) fn get(&self, expr_id: ScopedExpressionId) -> Option> { - self.targets.get(&expr_id).copied() + /// Returns the inferred type for a given sub-expression of the left-hand side target + /// of an unpacking assignment. + /// + /// Panics if a scoped expression ID is passed in that does not correspond to a sub- + /// expression of the target. + #[track_caller] + pub(crate) fn expression_type(&self, expr_id: ScopedExpressionId) -> Type<'db> { + self.targets[&expr_id] } }