From 7a37e62173c018e0b04efec0320da219672cc79b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 10:38:41 +0000 Subject: [PATCH 1/4] Initial plan From 6af48b2f015b5fce7bdfd7af3fb65270e698da70 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 11:35:20 +0000 Subject: [PATCH 2/4] Fix frozen module origname metadata Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com> --- crates/compiler-core/src/frozen.rs | 39 +++++++++++++------ crates/derive-impl/src/compile_bytecode.rs | 21 ++++++++--- crates/vm/src/import.rs | 12 ++++-- crates/vm/src/stdlib/imp.rs | 2 +- crates/vm/src/vm/mod.rs | 44 ++++++++++++++++++++++ 5 files changed, 96 insertions(+), 22 deletions(-) diff --git a/crates/compiler-core/src/frozen.rs b/crates/compiler-core/src/frozen.rs index a79569ad7fb..34a626e2b1d 100644 --- a/crates/compiler-core/src/frozen.rs +++ b/crates/compiler-core/src/frozen.rs @@ -1,11 +1,14 @@ use crate::bytecode::*; use crate::marshal::{self, Read, ReadBorrowed, Write}; -/// A frozen module. Holds a frozen code object and whether it is part of a package +/// A frozen module. Holds a frozen code object and whether it is part of a package. +/// The `origname` type is generic to allow either static names (runtime) or +/// borrowed/owned names during compile-time freezing. #[derive(Copy, Clone)] -pub struct FrozenModule { +pub struct FrozenModule { pub code: FrozenCodeObject, pub package: bool, + pub origname: N, } #[derive(Copy, Clone)] @@ -55,7 +58,7 @@ impl + ?Sized> FrozenLib { } impl<'a, B: AsRef<[u8]> + ?Sized> IntoIterator for &'a FrozenLib { - type Item = (&'a str, FrozenModule<&'a [u8]>); + type Item = (&'a str, FrozenModule<&'a [u8], &'a str>); type IntoIter = FrozenModulesIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -69,7 +72,7 @@ pub struct FrozenModulesIter<'a> { } impl<'a> Iterator for FrozenModulesIter<'a> { - type Item = (&'a str, FrozenModule<&'a [u8]>); + type Item = (&'a str, FrozenModule<&'a [u8], &'a str>); fn next(&mut self) -> Option { if self.remaining > 0 { @@ -90,21 +93,30 @@ impl ExactSizeIterator for FrozenModulesIter<'_> {} fn read_entry<'a>( rdr: &mut &'a [u8], -) -> Result<(&'a str, FrozenModule<&'a [u8]>), marshal::MarshalError> { +) -> Result<(&'a str, FrozenModule<&'a [u8], &'a str>), marshal::MarshalError> { let len = rdr.read_u32()?; let name = rdr.read_str_borrow(len)?; let len = rdr.read_u32()?; let code_slice = rdr.read_slice_borrow(len)?; let code = FrozenCodeObject { bytes: code_slice }; let package = rdr.read_u8()? != 0; - Ok((name, FrozenModule { code, package })) + let len = rdr.read_u32()?; + let origname = rdr.read_str_borrow(len)?; + Ok(( + name, + FrozenModule { + code, + package, + origname, + }, + )) } impl FrozenLib> { /// Encode the given iterator of frozen modules into a compressed vector of bytes - pub fn encode<'a, I, B: AsRef<[u8]>>(lib: I) -> Self + pub fn encode<'a, I, B: AsRef<[u8]>, N: AsRef>(lib: I) -> Self where - I: IntoIterator), IntoIter: ExactSizeIterator + Clone>, + I: IntoIterator), IntoIter: ExactSizeIterator + Clone>, { let iter = lib.into_iter(); let mut bytes = Vec::new(); @@ -113,9 +125,9 @@ impl FrozenLib> { } } -fn write_lib<'a, B: AsRef<[u8]>>( +fn write_lib<'a, B: AsRef<[u8]>, N: AsRef>( buf: &mut Vec, - lib: impl ExactSizeIterator)>, + lib: impl ExactSizeIterator)>, ) { marshal::write_len(buf, lib.len()); for (name, module) in lib { @@ -123,8 +135,13 @@ fn write_lib<'a, B: AsRef<[u8]>>( } } -fn write_entry(buf: &mut Vec, name: &str, module: FrozenModule>) { +fn write_entry>( + buf: &mut Vec, + name: &str, + module: FrozenModule, N>, +) { marshal::write_vec(buf, name.as_bytes()); marshal::write_vec(buf, module.code.bytes.as_ref()); buf.write_u8(module.package as u8); + marshal::write_vec(buf, module.origname.as_ref().as_bytes()); } diff --git a/crates/derive-impl/src/compile_bytecode.rs b/crates/derive-impl/src/compile_bytecode.rs index 23c90690dad..a34f09cbc31 100644 --- a/crates/derive-impl/src/compile_bytecode.rs +++ b/crates/derive-impl/src/compile_bytecode.rs @@ -45,6 +45,7 @@ enum CompilationSourceKind { struct CompiledModule { code: CodeObject, package: bool, + origname: String, } struct CompilationSource { @@ -91,12 +92,17 @@ impl CompilationSource { mode, compiler, ), - _ => Ok(hashmap! { - module_name.clone() => CompiledModule { - code: self.compile_single(mode, module_name, compiler)?, - package: false, - }, - }), + _ => { + let origname = module_name.clone(); + let code = self.compile_single(mode, module_name, compiler)?; + Ok(hashmap! { + origname.clone() => CompiledModule { + code, + package: false, + origname, + }, + }) + } } } @@ -220,11 +226,13 @@ impl CompilationSource { Err(e) => return Err(e), }; + let origname = module_name.clone(); code_map.insert( module_name, CompiledModule { code, package: is_init, + origname, }, ); } @@ -368,6 +376,7 @@ pub fn impl_py_freeze( let v = frozen::FrozenModule { code: frozen::FrozenCodeObject::encode(&v.code), package: v.package, + origname: &*v.origname, }; (&**k, v) })); diff --git a/crates/vm/src/import.rs b/crates/vm/src/import.rs index f970a335aa5..23c4ba75020 100644 --- a/crates/vm/src/import.rs +++ b/crates/vm/src/import.rs @@ -69,11 +69,15 @@ pub fn make_frozen(vm: &VirtualMachine, name: &str) -> PyResult> { } pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult { - let frozen = make_frozen(vm, module_name)?; - let module = import_code_obj(vm, module_name, frozen, false)?; + let frozen = vm.state.frozen.get(module_name).ok_or_else(|| { + vm.new_import_error( + format!("No such frozen object named {module_name}"), + vm.ctx.new_str(module_name), + ) + })?; + let module = import_code_obj(vm, module_name, vm.ctx.new_code(frozen.code), false)?; debug_assert!(module.get_attr(identifier!(vm, __name__), vm).is_ok()); - // TODO: give a correct origname here - module.set_attr("__origname__", vm.ctx.new_str(module_name.to_owned()), vm)?; + module.set_attr("__origname__", vm.ctx.new_str(frozen.origname), vm)?; Ok(module) } diff --git a/crates/vm/src/stdlib/imp.rs b/crates/vm/src/stdlib/imp.rs index df32b0c0068..a85453f27ab 100644 --- a/crates/vm/src/stdlib/imp.rs +++ b/crates/vm/src/stdlib/imp.rs @@ -191,7 +191,7 @@ mod _imp { Err(e) => return Err(e.to_pyexception(name.as_str(), vm)), }; - let origname = name; // FIXME: origname != name + let origname = vm.ctx.new_str(info.origname); Ok(Some((None, info.package, origname))) } diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index b156e30b738..1a1042d9e8d 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -1001,6 +1001,10 @@ impl AsRef for VirtualMachine { } } +use std::sync::OnceLock; + +static FROZEN_ORIGNAME_ALIASES: OnceLock> = OnceLock::new(); + fn core_frozen_inits() -> impl Iterator { let iter = core::iter::empty(); macro_rules! ext_modules { @@ -1036,6 +1040,23 @@ fn core_frozen_inits() -> impl Iterator { crate_name = "rustpython_compiler_core" ); + let aliases = FROZEN_ORIGNAME_ALIASES.get_or_init(|| { + HashMap::from([ + ("_frozen_importlib", "importlib._bootstrap"), + ( + "_frozen_importlib_external", + "importlib._bootstrap_external", + ), + ]) + }); + + let iter = iter.map(|(name, mut module)| { + if let Some(origname) = aliases.get(name) { + module.origname = *origname; + } + (name, module) + }); + iter } @@ -1064,3 +1085,26 @@ fn test_nested_frozen() { } }) } + +#[test] +fn frozen_origname_matches() { + use rustpython_vm as vm; + + vm::Interpreter::with_init(Default::default(), |_vm| {}).enter(|vm| { + let check = |name, expected| { + let module = import::import_frozen(vm, name).unwrap(); + let origname: PyStrRef = module + .get_attr("__origname__", vm) + .unwrap() + .try_into_value(vm) + .unwrap(); + assert_eq!(origname.as_str(), expected); + }; + + check("_frozen_importlib", "importlib._bootstrap"); + check( + "_frozen_importlib_external", + "importlib._bootstrap_external", + ); + }); +} From 873c7f28966c6a477f244198ec8827cf80b2dd52 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Dec 2025 17:13:11 +0000 Subject: [PATCH 3/4] Fix clippy warning in frozen origname handling Co-authored-by: youknowone <69878+youknowone@users.noreply.github.com> --- crates/vm/src/vm/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 1a1042d9e8d..f8b3270434f 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -1050,14 +1050,12 @@ fn core_frozen_inits() -> impl Iterator { ]) }); - let iter = iter.map(|(name, mut module)| { + iter.map(|(name, mut module)| { if let Some(origname) = aliases.get(name) { module.origname = *origname; } (name, module) - }); - - iter + }) } #[test] From 72f314dfa62973092e1e492e0ab484fe0de33195 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Wed, 31 Dec 2025 19:36:44 +0900 Subject: [PATCH 4/4] reimpl origname --- crates/compiler-core/src/frozen.rs | 39 ++++++---------------- crates/derive-impl/src/compile_bytecode.rs | 21 ++++-------- crates/vm/src/import.rs | 5 +-- crates/vm/src/stdlib/imp.rs | 4 ++- crates/vm/src/vm/mod.rs | 29 ++++++---------- 5 files changed, 33 insertions(+), 65 deletions(-) diff --git a/crates/compiler-core/src/frozen.rs b/crates/compiler-core/src/frozen.rs index 34a626e2b1d..a79569ad7fb 100644 --- a/crates/compiler-core/src/frozen.rs +++ b/crates/compiler-core/src/frozen.rs @@ -1,14 +1,11 @@ use crate::bytecode::*; use crate::marshal::{self, Read, ReadBorrowed, Write}; -/// A frozen module. Holds a frozen code object and whether it is part of a package. -/// The `origname` type is generic to allow either static names (runtime) or -/// borrowed/owned names during compile-time freezing. +/// A frozen module. Holds a frozen code object and whether it is part of a package #[derive(Copy, Clone)] -pub struct FrozenModule { +pub struct FrozenModule { pub code: FrozenCodeObject, pub package: bool, - pub origname: N, } #[derive(Copy, Clone)] @@ -58,7 +55,7 @@ impl + ?Sized> FrozenLib { } impl<'a, B: AsRef<[u8]> + ?Sized> IntoIterator for &'a FrozenLib { - type Item = (&'a str, FrozenModule<&'a [u8], &'a str>); + type Item = (&'a str, FrozenModule<&'a [u8]>); type IntoIter = FrozenModulesIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -72,7 +69,7 @@ pub struct FrozenModulesIter<'a> { } impl<'a> Iterator for FrozenModulesIter<'a> { - type Item = (&'a str, FrozenModule<&'a [u8], &'a str>); + type Item = (&'a str, FrozenModule<&'a [u8]>); fn next(&mut self) -> Option { if self.remaining > 0 { @@ -93,30 +90,21 @@ impl ExactSizeIterator for FrozenModulesIter<'_> {} fn read_entry<'a>( rdr: &mut &'a [u8], -) -> Result<(&'a str, FrozenModule<&'a [u8], &'a str>), marshal::MarshalError> { +) -> Result<(&'a str, FrozenModule<&'a [u8]>), marshal::MarshalError> { let len = rdr.read_u32()?; let name = rdr.read_str_borrow(len)?; let len = rdr.read_u32()?; let code_slice = rdr.read_slice_borrow(len)?; let code = FrozenCodeObject { bytes: code_slice }; let package = rdr.read_u8()? != 0; - let len = rdr.read_u32()?; - let origname = rdr.read_str_borrow(len)?; - Ok(( - name, - FrozenModule { - code, - package, - origname, - }, - )) + Ok((name, FrozenModule { code, package })) } impl FrozenLib> { /// Encode the given iterator of frozen modules into a compressed vector of bytes - pub fn encode<'a, I, B: AsRef<[u8]>, N: AsRef>(lib: I) -> Self + pub fn encode<'a, I, B: AsRef<[u8]>>(lib: I) -> Self where - I: IntoIterator), IntoIter: ExactSizeIterator + Clone>, + I: IntoIterator), IntoIter: ExactSizeIterator + Clone>, { let iter = lib.into_iter(); let mut bytes = Vec::new(); @@ -125,9 +113,9 @@ impl FrozenLib> { } } -fn write_lib<'a, B: AsRef<[u8]>, N: AsRef>( +fn write_lib<'a, B: AsRef<[u8]>>( buf: &mut Vec, - lib: impl ExactSizeIterator)>, + lib: impl ExactSizeIterator)>, ) { marshal::write_len(buf, lib.len()); for (name, module) in lib { @@ -135,13 +123,8 @@ fn write_lib<'a, B: AsRef<[u8]>, N: AsRef>( } } -fn write_entry>( - buf: &mut Vec, - name: &str, - module: FrozenModule, N>, -) { +fn write_entry(buf: &mut Vec, name: &str, module: FrozenModule>) { marshal::write_vec(buf, name.as_bytes()); marshal::write_vec(buf, module.code.bytes.as_ref()); buf.write_u8(module.package as u8); - marshal::write_vec(buf, module.origname.as_ref().as_bytes()); } diff --git a/crates/derive-impl/src/compile_bytecode.rs b/crates/derive-impl/src/compile_bytecode.rs index a34f09cbc31..23c90690dad 100644 --- a/crates/derive-impl/src/compile_bytecode.rs +++ b/crates/derive-impl/src/compile_bytecode.rs @@ -45,7 +45,6 @@ enum CompilationSourceKind { struct CompiledModule { code: CodeObject, package: bool, - origname: String, } struct CompilationSource { @@ -92,17 +91,12 @@ impl CompilationSource { mode, compiler, ), - _ => { - let origname = module_name.clone(); - let code = self.compile_single(mode, module_name, compiler)?; - Ok(hashmap! { - origname.clone() => CompiledModule { - code, - package: false, - origname, - }, - }) - } + _ => Ok(hashmap! { + module_name.clone() => CompiledModule { + code: self.compile_single(mode, module_name, compiler)?, + package: false, + }, + }), } } @@ -226,13 +220,11 @@ impl CompilationSource { Err(e) => return Err(e), }; - let origname = module_name.clone(); code_map.insert( module_name, CompiledModule { code, package: is_init, - origname, }, ); } @@ -376,7 +368,6 @@ pub fn impl_py_freeze( let v = frozen::FrozenModule { code: frozen::FrozenCodeObject::encode(&v.code), package: v.package, - origname: &*v.origname, }; (&**k, v) })); diff --git a/crates/vm/src/import.rs b/crates/vm/src/import.rs index 23c4ba75020..d67bf59b35f 100644 --- a/crates/vm/src/import.rs +++ b/crates/vm/src/import.rs @@ -5,7 +5,7 @@ use crate::{ builtins::{PyCode, list, traceback::PyTraceback}, exceptions::types::PyBaseException, scope::Scope, - vm::{VirtualMachine, thread}, + vm::{VirtualMachine, resolve_frozen_alias, thread}, }; pub(crate) fn init_importlib_base(vm: &mut VirtualMachine) -> PyResult { @@ -77,7 +77,8 @@ pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult { })?; let module = import_code_obj(vm, module_name, vm.ctx.new_code(frozen.code), false)?; debug_assert!(module.get_attr(identifier!(vm, __name__), vm).is_ok()); - module.set_attr("__origname__", vm.ctx.new_str(frozen.origname), vm)?; + let origname = resolve_frozen_alias(module_name); + module.set_attr("__origname__", vm.ctx.new_str(origname), vm)?; Ok(module) } diff --git a/crates/vm/src/stdlib/imp.rs b/crates/vm/src/stdlib/imp.rs index a85453f27ab..ad2cede975c 100644 --- a/crates/vm/src/stdlib/imp.rs +++ b/crates/vm/src/stdlib/imp.rs @@ -2,6 +2,8 @@ use crate::frozen::FrozenModule; use crate::{VirtualMachine, builtins::PyBaseExceptionRef}; pub(crate) use _imp::make_module; +pub use crate::vm::resolve_frozen_alias; + #[cfg(feature = "threading")] #[pymodule(sub)] mod lock { @@ -191,7 +193,7 @@ mod _imp { Err(e) => return Err(e.to_pyexception(name.as_str(), vm)), }; - let origname = vm.ctx.new_str(info.origname); + let origname = vm.ctx.new_str(super::resolve_frozen_alias(name.as_str())); Ok(Some((None, info.package, origname))) } diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index f8b3270434f..2eef479d1b4 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -1001,9 +1001,15 @@ impl AsRef for VirtualMachine { } } -use std::sync::OnceLock; - -static FROZEN_ORIGNAME_ALIASES: OnceLock> = OnceLock::new(); +/// Resolve frozen module alias to its original name. +/// Returns the original module name if an alias exists, otherwise returns the input name. +pub fn resolve_frozen_alias(name: &str) -> &str { + match name { + "_frozen_importlib" => "importlib._bootstrap", + "_frozen_importlib_external" => "importlib._bootstrap_external", + _ => name, + } +} fn core_frozen_inits() -> impl Iterator { let iter = core::iter::empty(); @@ -1040,22 +1046,7 @@ fn core_frozen_inits() -> impl Iterator { crate_name = "rustpython_compiler_core" ); - let aliases = FROZEN_ORIGNAME_ALIASES.get_or_init(|| { - HashMap::from([ - ("_frozen_importlib", "importlib._bootstrap"), - ( - "_frozen_importlib_external", - "importlib._bootstrap_external", - ), - ]) - }); - - iter.map(|(name, mut module)| { - if let Some(origname) = aliases.get(name) { - module.origname = *origname; - } - (name, module) - }) + iter } #[test]