Skip to content

Commit a28bec8

Browse files
Merge pull request #22266 from ChayimFriedman2/closure-analysis
fix: Fix handling of `self` in `lower_coroutine_body_with_moved_arguments()`
2 parents a936884 + ac53ab9 commit a28bec8

2 files changed

Lines changed: 26 additions & 0 deletions

File tree

crates/hir-def/src/expr_store/lower.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ pub(super) fn lower_body(
165165
};
166166

167167
let body_expr = collector.collect(
168+
self_param,
168169
&mut params,
169170
body,
170171
if is_async_fn {
@@ -963,6 +964,7 @@ impl<'db> ExprCollector<'db> {
963964
/// drop order are stable.
964965
fn lower_coroutine_body_with_moved_arguments(
965966
&mut self,
967+
self_param: Option<BindingId>,
966968
params: &mut [PatId],
967969
body: ExprId,
968970
kind: CoroutineKind,
@@ -995,6 +997,26 @@ impl<'db> ExprCollector<'db> {
995997
// `let <pattern> = <pattern>;` statement as an optimization.
996998

997999
let mut statements = Vec::new();
1000+
1001+
if let Some(self_param) = self_param {
1002+
let Binding { ref name, mode, hygiene, .. } = self.store.bindings[self_param];
1003+
let name = name.clone();
1004+
let child_binding_id = self.alloc_binding(name.clone(), mode, hygiene);
1005+
let child_pat_id =
1006+
self.alloc_pat_desugared(Pat::Bind { id: child_binding_id, subpat: None });
1007+
self.add_definition_to_binding(child_binding_id, child_pat_id);
1008+
let expr = self.alloc_expr_desugared(Expr::Path(name.into()));
1009+
if !hygiene.is_root() {
1010+
self.store.ident_hygiene.insert(expr.into(), hygiene);
1011+
}
1012+
statements.push(Statement::Let {
1013+
pat: child_pat_id,
1014+
type_ref: None,
1015+
initializer: Some(expr),
1016+
else_branch: None,
1017+
});
1018+
}
1019+
9981020
for param in params {
9991021
let (name, hygiene, is_simple_parameter) = match self.store.pats[*param] {
10001022
// Check if this is a binding pattern, if so, we can optimize and avoid adding a
@@ -1094,6 +1116,7 @@ impl<'db> ExprCollector<'db> {
10941116

10951117
fn collect(
10961118
&mut self,
1119+
self_param: Option<BindingId>,
10971120
params: &mut [PatId],
10981121
expr: Option<ast::Expr>,
10991122
awaitable: Awaitable,
@@ -1111,6 +1134,7 @@ impl<'db> ExprCollector<'db> {
11111134
(false, false) => unreachable!(),
11121135
};
11131136
this.lower_coroutine_body_with_moved_arguments(
1137+
self_param,
11141138
params,
11151139
body,
11161140
kind,
@@ -1587,6 +1611,7 @@ impl<'db> ExprCollector<'db> {
15871611
// It's important that this expr is allocated immediately before the closure.
15881612
// We rely on it for `coroutine_for_closure()`.
15891613
body = this.lower_coroutine_body_with_moved_arguments(
1614+
None,
15901615
&mut args,
15911616
body,
15921617
kind,

crates/hir-def/src/expr_store/tests/body.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ async fn main(&self, param1: i32, ref mut param2: i32, _: i32, param4 @ _: i32,
653653
"#,
654654
expect![[r#"
655655
fn main(self, param1, mut param2, mut <ra@gennew>0, mut param4, mut <ra@gennew>1) async {
656+
let self = self;
656657
let mut param1 = param1;
657658
let mut param2 = param2;
658659
let ref mut param2 = param2;

0 commit comments

Comments
 (0)