Skip to content

Conversation

@dhruvmanila
Copy link
Member

@dhruvmanila dhruvmanila commented Dec 19, 2024

Summary

Related to #13773

This PR adds support for unpacking for statement targets.

This involves updating the value field in the Unpack target to use an enum which specifies the "where did the value expression came from?". This is because for an iterable expression, we need to unpack the iterator type while for assignment statement we need to unpack the value type itself. And, this needs to be done in the unpack query.

Question

One of the ways unpacking works in for statement is by looking at the union of the types because if the iterable expression is a tuple then the iterator type will be union of all the types in the tuple. This means that the test cases that will test the unpacking in for statement will also implicitly test the unpacking union logic. I was wondering if it makes sense to merge these cases and only add the ones that are specific to the union unpacking or for statement unpacking logic.

Test Plan

Add test cases involving iterating over a tuple type. I've intentionally left out certain cases for now and I'm curious to know any thoughts on the above query.

@dhruvmanila dhruvmanila added the ty Multi-file analysis & type inference label Dec 19, 2024
@dhruvmanila dhruvmanila changed the title [red-knot] Add support for unpacking union types [red-knot] Add support for unpacking for target Dec 19, 2024
@dhruvmanila dhruvmanila force-pushed the dhruv/unpack-union branch 3 times, most recently from 15d1613 to 9292856 Compare December 20, 2024 04:22
@dhruvmanila dhruvmanila force-pushed the dhruv/unpack-for-target branch from 8b38f74 to c9799b6 Compare December 20, 2024 04:25
@github-actions
Copy link
Contributor

github-actions bot commented Dec 20, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@dhruvmanila dhruvmanila force-pushed the dhruv/unpack-for-target branch from c9799b6 to 94b8bdc Compare December 20, 2024 10:06
Base automatically changed from dhruv/unpack-union to main December 20, 2024 11:01
@dhruvmanila dhruvmanila force-pushed the dhruv/unpack-for-target branch 3 times, most recently from 7cd3be6 to fe681d0 Compare December 20, 2024 12:03
reveal_type(b) # revealed: str | bytes
```

## For statement
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've intentionally left out certain test cases, refer to the "Question" in PR description.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the tests you have here look good!


debug_assert_eq!(&self.current_assignments, &[]);
self.push_assignment(for_stmt.into());
let current_assignment = match &**target {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically the same logic as in the assignment statement, I'm going to wait until I implement unpacking support in other places to get an overview of what can be simplified to avoid repetition.

Comment on lines -204 to -209
let value = unpack.value(db);
let scope = unpack.scope(db);

let result = infer_expression_types(db, value);
let value_ty = result.expression_ty(value.node_ref(db).scoped_expression_id(db, scope));

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inferring the value type is moved in the Unpacker

Comment on lines +210 to +217
// TODO
//self.visit_expr(&assign.value);
return;
}
Stmt::For(for_stmt) => {
self.visit_target(&for_stmt.target);
// TODO
//self.visit_expr(&for_stmt.iter);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually a bug, calling visit_expr on the expression panics in the following case:

[] = *data
() = *data

This is because in infer_target, we completely skip the inference when there are no elements in the list / tuple target.

I'm going to fix this in a follow-up.

@dhruvmanila dhruvmanila marked this pull request as ready for review December 20, 2024 12:15
Copy link
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

reveal_type(b) # revealed: str | bytes
```

## For statement
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the tests you have here look good!

@dhruvmanila dhruvmanila force-pushed the dhruv/unpack-for-target branch from fe681d0 to 6a116dc Compare December 23, 2024 06:09
@dhruvmanila dhruvmanila enabled auto-merge (squash) December 23, 2024 06:09
@dhruvmanila dhruvmanila merged commit 113c804 into main Dec 23, 2024
20 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/unpack-for-target branch December 23, 2024 06:13
dhruvmanila added a commit that referenced this pull request Dec 23, 2024
## Summary

This PR resolves
#15058 (comment) by
inferring the value expression even if there are no targets in the list
/ tuple expression.

## Test Plan

Remove TODO from corpus tests, making sure it doesn't panic.
carljm added a commit that referenced this pull request Mar 8, 2025
## Summary

Resolves #16365

Add support for unpacking `with` statement targets.

## Test Plan

Added some test cases, alike the ones added by #15058.

---------

Co-authored-by: Carl Meyer <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants