MCPcopy Index your code
hub / github.com/RustPython/RustPython / dedup_and_flatten_args

Function dedup_and_flatten_args

crates/vm/src/builtins/union.rs:288–362  ·  view source on GitHub ↗
(args: &Py<PyTuple>, vm: &VirtualMachine)

Source from the content-addressed store, hash-verified

286}
287
288fn dedup_and_flatten_args(args: &Py<PyTuple>, vm: &VirtualMachine) -> PyResult<UnionComponents> {
289 let args = flatten_args(args, vm);
290
291 // Use set-based deduplication like CPython:
292 // - For hashable elements: use Python's set semantics (hash + equality)
293 // - For unhashable elements: use equality comparison
294 //
295 // This avoids calling __eq__ when hashes differ, so `int | BadType`
296 // doesn't raise even if BadType.__eq__ raises.
297
298 let mut new_args: Vec<PyObjectRef> = Vec::with_capacity(args.len());
299
300 // Track hashable elements using a Python set (uses hash + equality)
301 let hashable_set = PySet::default().into_ref(&vm.ctx);
302 let mut hashable_list: Vec<PyObjectRef> = Vec::new();
303 let mut unhashable_list: Vec<PyObjectRef> = Vec::new();
304
305 for arg in &*args {
306 // Try to hash the element first
307 match arg.hash(vm) {
308 Ok(_) => {
309 // Element is hashable - use set for deduplication
310 // Set membership uses hash first, then equality only if hashes match
311 let contains = vm
312 .call_method(hashable_set.as_ref(), "__contains__", (arg.clone(),))
313 .and_then(|r| r.try_to_bool(vm))?;
314 if !contains {
315 hashable_set.add(arg.clone(), vm)?;
316 hashable_list.push(arg.clone());
317 new_args.push(arg.clone());
318 }
319 }
320 Err(_) => {
321 // Element is unhashable - use equality comparison
322 let mut is_duplicate = false;
323 for existing in &unhashable_list {
324 match existing.rich_compare_bool(arg, PyComparisonOp::Eq, vm) {
325 Ok(true) => {
326 is_duplicate = true;
327 break;
328 }
329 Ok(false) => continue,
330 Err(e) => return Err(e),
331 }
332 }
333 if !is_duplicate {
334 unhashable_list.push(arg.clone());
335 new_args.push(arg.clone());
336 }
337 }
338 }
339 }
340
341 new_args.shrink_to_fit();
342
343 // Create hashable_args frozenset if there are hashable elements
344 let hashable_args = if !hashable_list.is_empty() {
345 Some(PyFrozenSet::from_iter(vm, hashable_list.into_iter())?.into_ref(&vm.ctx))

Callers 2

make_parametersFunction · 0.85
make_unionFunction · 0.85

Calls 15

flatten_argsFunction · 0.85
newFunction · 0.85
try_to_boolMethod · 0.80
rich_compare_boolMethod · 0.80
shrink_to_fitMethod · 0.80
ErrClass · 0.50
SomeClass · 0.50
lenMethod · 0.45
into_refMethod · 0.45
hashMethod · 0.45
call_methodMethod · 0.45
as_refMethod · 0.45

Tested by

no test coverage detected