mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Keep functools Placeholder identity in interpreter state (#9198)
Fresh _functools imports must not replace the singleton returned for existing Placeholder objects. Share initialization within each interpreter and return the published winner under racing imports. Assisted-by: OpenAI Codex: model version unavailable
This commit is contained in:
1 parent
23da4ac248
commit
fc853015d1
3 files changed
+14
-13
No files matched your search
@@ -179,16 +179,19 @@ mod _functools {
|
||||
}
|
||||
}
|
||||
|
||||
// Placeholder singleton for partial arguments
|
||||
// The singleton is stored as _instance on the type class
|
||||
// Keep identity in interpreter state, not on the shared static type.
|
||||
#[pyattr]
|
||||
#[allow(non_snake_case)]
|
||||
fn Placeholder(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let cell = &vm.state.functools_placeholder;
|
||||
if let Some(placeholder) = cell.get() {
|
||||
return placeholder.clone();
|
||||
}
|
||||
// Allocate outside the cell initializer: allocation may trigger GC.
|
||||
// Another thread can publish first; always return the published winner.
|
||||
let placeholder = PyPlaceholderType.into_pyobject(vm);
|
||||
// Store the singleton on the type class for slot_new to find
|
||||
let typ = placeholder.class();
|
||||
typ.set_attr(vm.ctx.intern_str("_instance"), placeholder.clone());
|
||||
placeholder
|
||||
let _ = cell.set(placeholder);
|
||||
cell.get().expect("Placeholder was initialized").clone()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
@@ -199,16 +202,11 @@ mod _functools {
|
||||
impl Constructor for PyPlaceholderType {
|
||||
type Args = FuncArgs;
|
||||
|
||||
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
fn slot_new(_cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
if !args.args.is_empty() || !args.kwargs.is_empty() {
|
||||
return Err(vm.new_type_error("_PlaceholderType takes no arguments"));
|
||||
}
|
||||
// Return the singleton stored on the type class
|
||||
if let Some(instance) = cls.get_attr(vm.ctx.intern_str("_instance")) {
|
||||
return Ok(instance);
|
||||
}
|
||||
// Fallback: create a new instance (shouldn't happen for base type after module init)
|
||||
Ok(Self.into_pyobject(vm))
|
||||
Ok(Placeholder(vm))
|
||||
}
|
||||
|
||||
fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
|
||||
|
||||
@@ -169,6 +169,7 @@ where
|
||||
import_time_header: AtomicBool::new(false),
|
||||
lazy_imports,
|
||||
struct_format_cache: crate::buffer::FormatSpecCache::default(),
|
||||
functools_placeholder: Default::default(),
|
||||
finalizing: AtomicBool::new(false),
|
||||
#[cfg(feature = "threading")]
|
||||
finalizing_thread_ident: AtomicCell::new(0),
|
||||
|
||||
@@ -879,6 +879,8 @@ pub struct PyGlobalState {
|
||||
pub(crate) import_time_header: AtomicBool,
|
||||
pub(crate) lazy_imports: crate::lazy_import::LazyImportsState,
|
||||
pub struct_format_cache: crate::buffer::FormatSpecCache,
|
||||
/// Placeholder identity shared by all threads and fresh imports in this interpreter.
|
||||
pub(crate) functools_placeholder: crate::common::lock::OnceCell<PyObjectRef>,
|
||||
pub finalizing: AtomicBool,
|
||||
/// The thread performing finalization, which need not be the process main thread.
|
||||
#[cfg(feature = "threading")]
|
||||
|
||||
Reference in new issue
Block a user