fix: closure codegen bug

This commit is contained in:
Shunsuke Shibayama 2024-02-11 00:14:02 +09:00
parent 2a26cc8a1d
commit 40a01db38f
2 changed files with 39 additions and 8 deletions

View file

@ -320,6 +320,14 @@ impl PyCodeGenerator {
self.units.last().unwrap()
}
fn captured_vars(&self) -> Vec<&str> {
let mut caps = vec![];
for unit in self.units.iter() {
caps.extend(unit.captured_vars.iter().map(|s| &**s));
}
caps
}
#[inline]
fn mut_cur_block(&mut self) -> &mut PyCodeGenUnit {
self.units.last_mut().unwrap()
@ -638,23 +646,27 @@ impl PyCodeGenerator {
}
}
if let Some(idx) = self
.cur_block_codeobj()
.names
.iter()
.position(|n| &**n == name)
{
Some(Name::local(idx))
} else if let Some(idx) = self
.cur_block_codeobj()
.varnames
.iter()
.position(|v| &**v == name)
{
if self.cur_block().captured_vars.contains(&Str::rc(name)) {
if self.captured_vars().contains(&name) {
Some(Name::deref(idx))
} else {
Some(Name::fast(idx))
}
} else if let Some(idx) = self
.cur_block_codeobj()
.names
.iter()
.position(|n| &**n == name)
{
if self.captured_vars().contains(&name) {
None
} else {
Some(Name::local(idx))
}
} else {
self.cur_block_codeobj()
.freevars
@ -3697,6 +3709,9 @@ impl PyCodeGenerator {
let mut cells = vec![];
if self.py_version.minor >= Some(11) {
for captured in captured_names {
self.mut_cur_block()
.captured_vars
.push(captured.inspect().clone());
self.write_instr(Opcode311::MAKE_CELL);
cells.push((captured, self.lasti()));
self.write_arg(0);