codegen: module seed CodeInfo emits empty flags (#7782)

CPython convention: top-level module / interactive / expression code
does not carry CO_NEWLOCALS or CO_OPTIMIZED. The per-scope mapping at
enter_scope::CompilerScope::Module already returns empty flags, but
Compiler::new seeded the root CodeInfo with CodeFlags::NEWLOCALS,
forcing module code into the NEWLOCALS arm of frame.rs:725-731 so
locals were allocated as a fresh empty dict instead of being bound to
globals (the correct semantics for exec(code, globals)).

Restore the seed to empty() so it matches the per-scope mapping and
CPython's compiler_enter_scope for module scope.
This commit is contained in:
Jeong, YunWon authored and GitHub committed 2026-05-05 16:22:55 +09:00
1 parent e6d2522cd2
commit 3757582ca2
1 file changed
+9 -1
+9 -1
View File
@@ -505,7 +505,15 @@ impl Compiler {
fn new(opts: CompileOpts, source_file: SourceFile, code_name: String) -> Self {
let module_code = ir::CodeInfo {
flags: bytecode::CodeFlags::NEWLOCALS,
// CPython convention: top-level module / interactive /
// expression code does not carry CO_NEWLOCALS or CO_OPTIMIZED.
// (See `Python/compile.c compiler_enter_scope` for module
// scope.) This matches the per-scope mapping at
// enter_scope::CompilerScope::Module below, which also returns
// empty flags. frame.rs:725-731 then binds locals to globals
// for module/REPL frames whose `scope.locals` is None — the
// correct semantics for `exec(code, globals)` and module init.
flags: bytecode::CodeFlags::empty(),
source_path: source_file.name().to_owned(),
private: None,
blocks: vec![ir::Block::default()],