Skip to content
Merged

Py new #6402

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
set/tuple
  • Loading branch information
youknowone committed Dec 11, 2025
commit f9e2fb4d32fc09b053ca0f573716a7cfaaedbc33
44 changes: 26 additions & 18 deletions crates/vm/src/builtins/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -918,35 +918,43 @@ impl Representable for PySet {
}

impl Constructor for PyFrozenSet {
type Args = OptionalArg<PyObjectRef>;
type Args = Vec<PyObjectRef>;

fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
let iterable: Self::Args = args.bind(vm)?;
let elements = if let OptionalArg::Present(iterable) = iterable {
let iterable = if cls.is(vm.ctx.types.frozenset_type) {
match iterable.downcast_exact::<Self>(vm) {
Ok(fs) => return Ok(fs.into_pyref().into()),
Err(iterable) => iterable,
}
} else {
iterable
};
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;

// Optimizations for exact frozenset type
if cls.is(vm.ctx.types.frozenset_type) {
// Return exact frozenset as-is
if let OptionalArg::Present(ref input) = iterable
&& let Ok(fs) = input.clone().downcast_exact::<PyFrozenSet>(vm)
{
return Ok(fs.into_pyref().into());
}

// Return empty frozenset singleton
if iterable.is_missing() {
return Ok(vm.ctx.empty_frozenset.clone().into());
}
}

let elements: Vec<PyObjectRef> = if let OptionalArg::Present(iterable) = iterable {
iterable.try_to_value(vm)?
} else {
vec![]
};

// Return empty fs if iterable passed is empty and only for exact fs types.
// Return empty frozenset singleton for exact frozenset types (when iterable was empty)
if elements.is_empty() && cls.is(vm.ctx.types.frozenset_type) {
Ok(vm.ctx.empty_frozenset.clone().into())
} else {
Self::from_iter(vm, elements)
.and_then(|o| o.into_ref_with_type(vm, cls).map(Into::into))
return Ok(vm.ctx.empty_frozenset.clone().into());
}

let payload = Self::py_new(&cls, elements, vm)?;
payload.into_ref_with_type(vm, cls).map(Into::into)
}

fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
unreachable!("use slot_new")
fn py_new(_cls: &Py<PyType>, elements: Self::Args, vm: &VirtualMachine) -> PyResult<Self> {
Self::from_iter(vm, elements)
}
}

Expand Down
48 changes: 28 additions & 20 deletions crates/vm/src/builtins/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,37 +110,45 @@ impl_from_into_pytuple!(A, B, C, D, E, F, G);
pub type PyTupleRef = PyRef<PyTuple>;

impl Constructor for PyTuple {
type Args = OptionalArg<PyObjectRef>;
type Args = Vec<PyObjectRef>;

fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
let iterable: Self::Args = args.bind(vm)?;
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;

// Optimizations for exact tuple type
if cls.is(vm.ctx.types.tuple_type) {
// Return exact tuple as-is
if let OptionalArg::Present(ref input) = iterable
&& let Ok(tuple) = input.clone().downcast_exact::<PyTuple>(vm)
{
return Ok(tuple.into_pyref().into());
}

// Return empty tuple singleton
if iterable.is_missing() {
return Ok(vm.ctx.empty_tuple.clone().into());
}
}

let elements = if let OptionalArg::Present(iterable) = iterable {
let iterable = if cls.is(vm.ctx.types.tuple_type) {
match iterable.downcast_exact::<Self>(vm) {
Ok(tuple) => return Ok(tuple.into_pyref().into()),
Err(iterable) => iterable,
}
} else {
iterable
};
iterable.try_to_value(vm)?
} else {
vec![]
};
// Return empty tuple only for exact tuple types if the iterable is empty.

// Return empty tuple singleton for exact tuple types (when iterable was empty)
if elements.is_empty() && cls.is(vm.ctx.types.tuple_type) {
Ok(vm.ctx.empty_tuple.clone().into())
} else {
Self {
elements: elements.into_boxed_slice(),
}
.into_ref_with_type(vm, cls)
.map(Into::into)
return Ok(vm.ctx.empty_tuple.clone().into());
}

let payload = Self::py_new(&cls, elements, vm)?;
payload.into_ref_with_type(vm, cls).map(Into::into)
}

fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
unreachable!("use slot_new")
fn py_new(_cls: &Py<PyType>, elements: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
Ok(Self {
elements: elements.into_boxed_slice(),
})
}
}

Expand Down