Skip to content

Commit 2719731

Browse files
committed
set/tuple
1 parent 05b7690 commit 2719731

File tree

2 files changed

+54
-38
lines changed

2 files changed

+54
-38
lines changed

crates/vm/src/builtins/set.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -918,35 +918,43 @@ impl Representable for PySet {
918918
}
919919

920920
impl Constructor for PyFrozenSet {
921-
type Args = OptionalArg<PyObjectRef>;
921+
type Args = Vec<PyObjectRef>;
922922

923923
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
924-
let iterable: Self::Args = args.bind(vm)?;
925-
let elements = if let OptionalArg::Present(iterable) = iterable {
926-
let iterable = if cls.is(vm.ctx.types.frozenset_type) {
927-
match iterable.downcast_exact::<Self>(vm) {
928-
Ok(fs) => return Ok(fs.into_pyref().into()),
929-
Err(iterable) => iterable,
930-
}
931-
} else {
932-
iterable
933-
};
924+
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;
925+
926+
// Optimizations for exact frozenset type
927+
if cls.is(vm.ctx.types.frozenset_type) {
928+
// Return exact frozenset as-is
929+
if let OptionalArg::Present(ref input) = iterable
930+
&& let Ok(fs) = input.clone().downcast_exact::<PyFrozenSet>(vm)
931+
{
932+
return Ok(fs.into_pyref().into());
933+
}
934+
935+
// Return empty frozenset singleton
936+
if iterable.is_missing() {
937+
return Ok(vm.ctx.empty_frozenset.clone().into());
938+
}
939+
}
940+
941+
let elements: Vec<PyObjectRef> = if let OptionalArg::Present(iterable) = iterable {
934942
iterable.try_to_value(vm)?
935943
} else {
936944
vec![]
937945
};
938946

939-
// Return empty fs if iterable passed is empty and only for exact fs types.
947+
// Return empty frozenset singleton for exact frozenset types (when iterable was empty)
940948
if elements.is_empty() && cls.is(vm.ctx.types.frozenset_type) {
941-
Ok(vm.ctx.empty_frozenset.clone().into())
942-
} else {
943-
Self::from_iter(vm, elements)
944-
.and_then(|o| o.into_ref_with_type(vm, cls).map(Into::into))
949+
return Ok(vm.ctx.empty_frozenset.clone().into());
945950
}
951+
952+
let payload = Self::py_new(&cls, elements, vm)?;
953+
payload.into_ref_with_type(vm, cls).map(Into::into)
946954
}
947955

948-
fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
949-
unreachable!("use slot_new")
956+
fn py_new(_cls: &Py<PyType>, elements: Self::Args, vm: &VirtualMachine) -> PyResult<Self> {
957+
Self::from_iter(vm, elements)
950958
}
951959
}
952960

crates/vm/src/builtins/tuple.rs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -110,37 +110,45 @@ impl_from_into_pytuple!(A, B, C, D, E, F, G);
110110
pub type PyTupleRef = PyRef<PyTuple>;
111111

112112
impl Constructor for PyTuple {
113-
type Args = OptionalArg<PyObjectRef>;
113+
type Args = Vec<PyObjectRef>;
114114

115115
fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
116-
let iterable: Self::Args = args.bind(vm)?;
116+
let iterable: OptionalArg<PyObjectRef> = args.bind(vm)?;
117+
118+
// Optimizations for exact tuple type
119+
if cls.is(vm.ctx.types.tuple_type) {
120+
// Return exact tuple as-is
121+
if let OptionalArg::Present(ref input) = iterable
122+
&& let Ok(tuple) = input.clone().downcast_exact::<PyTuple>(vm)
123+
{
124+
return Ok(tuple.into_pyref().into());
125+
}
126+
127+
// Return empty tuple singleton
128+
if iterable.is_missing() {
129+
return Ok(vm.ctx.empty_tuple.clone().into());
130+
}
131+
}
132+
117133
let elements = if let OptionalArg::Present(iterable) = iterable {
118-
let iterable = if cls.is(vm.ctx.types.tuple_type) {
119-
match iterable.downcast_exact::<Self>(vm) {
120-
Ok(tuple) => return Ok(tuple.into_pyref().into()),
121-
Err(iterable) => iterable,
122-
}
123-
} else {
124-
iterable
125-
};
126134
iterable.try_to_value(vm)?
127135
} else {
128136
vec![]
129137
};
130-
// Return empty tuple only for exact tuple types if the iterable is empty.
138+
139+
// Return empty tuple singleton for exact tuple types (when iterable was empty)
131140
if elements.is_empty() && cls.is(vm.ctx.types.tuple_type) {
132-
Ok(vm.ctx.empty_tuple.clone().into())
133-
} else {
134-
Self {
135-
elements: elements.into_boxed_slice(),
136-
}
137-
.into_ref_with_type(vm, cls)
138-
.map(Into::into)
141+
return Ok(vm.ctx.empty_tuple.clone().into());
139142
}
143+
144+
let payload = Self::py_new(&cls, elements, vm)?;
145+
payload.into_ref_with_type(vm, cls).map(Into::into)
140146
}
141147

142-
fn py_new(_cls: &Py<PyType>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
143-
unreachable!("use slot_new")
148+
fn py_new(_cls: &Py<PyType>, elements: Self::Args, _vm: &VirtualMachine) -> PyResult<Self> {
149+
Ok(Self {
150+
elements: elements.into_boxed_slice(),
151+
})
144152
}
145153
}
146154

0 commit comments

Comments
 (0)