Skip to content

Commit 4016b4d

Browse files
committed
Bind interpreter queues with ordinary FromArgs structs
Use the shared Clinic validation from #9563 and derive queue signatures directly. Keep raw inputs alive through numeric conversions, preserve queue-specific diagnostics and defaults, and remove ArgSpec/Cell binding, parsed vectors, and redundant input clones. Assisted-by: OpenAI Codex:model version not exposed
1 parent f0df2ca commit 4016b4d

1 file changed

Lines changed: 80 additions & 107 deletions

File tree

‎crates/vm/src/stdlib/_interpqueues.rs‎

Lines changed: 80 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ pub(crate) use _interpqueues::{
1010
#[pymodule]
1111
pub(crate) mod _interpqueues {
1212
use crate::{
13-
AsObject, Py, PyObject, PyPayload, PyResult, VirtualMachine,
13+
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
1414
builtins::{PyBaseExceptionRef, PyModule, PyType, PyTypeRef},
15-
function::{ArgSpec, FuncArgs},
15+
function::OptionalArg,
1616
types::Constructor,
1717
vm::crossinterp::{Fallback, SharedValue, UnboundOp},
1818
};
1919
use alloc::{collections::BTreeMap, collections::VecDeque, sync::Arc};
20-
use core::cell::Cell;
2120
use num_traits::{Signed, ToPrimitive};
2221
use parking_lot::Mutex;
2322
use std::sync::OnceLock;
@@ -339,23 +338,11 @@ pub(crate) mod _interpqueues {
339338
Err(vm.new_overflow_error(format!("max queue ID is {}, got {repr}", i64::MAX)))
340339
}
341340

342-
fn qid_arg(args: &FuncArgs, func: &'static str, vm: &VirtualMachine) -> PyResult<i64> {
343-
let qid = Cell::new(None);
344-
ArgSpec {
345-
fname: func,
346-
keywords: &["qid"],
347-
required: 1,
348-
max_positional: 1,
341+
fn optional_int_arg(arg: &OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<i32> {
342+
match arg {
343+
OptionalArg::Present(obj) => int_arg(obj, vm),
344+
OptionalArg::Missing => Ok(-1),
349345
}
350-
.parse_with(
351-
args,
352-
|_, obj, vm| {
353-
qid.set(Some(parse_qid(obj, vm)?));
354-
Ok(())
355-
},
356-
vm,
357-
)?;
358-
Ok(qid.get().unwrap())
359346
}
360347

361348
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
@@ -365,39 +352,58 @@ pub(crate) mod _interpqueues {
365352
Ok(())
366353
}
367354

355+
// Keep the original inputs alive while applying the queue-specific converters.
356+
#[derive(FromArgs)]
357+
struct QueueIdArgs {
358+
#[pyarg(any)]
359+
qid: PyObjectRef,
360+
}
361+
362+
#[derive(FromArgs)]
363+
struct CreateArgs {
364+
#[pyarg(any)]
365+
maxsize: PyObjectRef,
366+
#[pyarg(any, optional, py_default = "-1")]
367+
unboundop: OptionalArg<PyObjectRef>,
368+
#[pyarg(any, optional, py_default = "-1")]
369+
fallback: OptionalArg<PyObjectRef>,
370+
}
371+
372+
#[derive(FromArgs)]
373+
struct PutArgs {
374+
#[pyarg(any)]
375+
qid: PyObjectRef,
376+
#[pyarg(any)]
377+
obj: PyObjectRef,
378+
#[pyarg(any, optional, py_default = "-1")]
379+
unboundop: OptionalArg<PyObjectRef>,
380+
#[pyarg(any, optional, py_default = "-1")]
381+
fallback: OptionalArg<PyObjectRef>,
382+
}
383+
384+
#[derive(FromArgs)]
385+
struct RegisterHeapTypesArgs {
386+
#[pyarg(any)]
387+
queuetype: PyObjectRef,
388+
#[pyarg(any)]
389+
emptyerror: PyObjectRef,
390+
#[pyarg(any)]
391+
fullerror: PyObjectRef,
392+
}
393+
368394
#[pyfunction]
369-
fn create(args: FuncArgs, vm: &VirtualMachine) -> PyResult<i64> {
370-
let maxsize = Cell::new(None);
371-
let unboundarg = Cell::new(None);
372-
let fallbackarg = Cell::new(None);
373-
ArgSpec {
374-
fname: "create",
375-
keywords: &["maxsize", "unboundop", "fallback"],
376-
required: 1,
377-
max_positional: 3,
378-
}
379-
.parse_with(
380-
&args,
381-
|i, obj, vm| {
382-
match i {
383-
0 => maxsize.set(Some(ssize_arg(obj, vm)?)),
384-
1 => unboundarg.set(Some(int_arg(obj, vm)?)),
385-
2 => fallbackarg.set(Some(int_arg(obj, vm)?)),
386-
_ => unreachable!(),
387-
}
388-
Ok(())
389-
},
390-
vm,
391-
)?;
392-
let unboundop = resolve_unboundop(unboundarg.get().unwrap_or(-1), UnboundOp::Replace, vm)?;
393-
let fallback =
394-
resolve_fallback(fallbackarg.get().unwrap_or(-1), Fallback::Full.as_i32(), vm)?;
395-
queue_create(maxsize.get().unwrap(), unboundop, fallback).map_err(|err| err.into_py(-1, vm))
395+
fn create(args: CreateArgs, vm: &VirtualMachine) -> PyResult<i64> {
396+
let maxsize = ssize_arg(&args.maxsize, vm)?;
397+
let unboundarg = optional_int_arg(&args.unboundop, vm)?;
398+
let fallbackarg = optional_int_arg(&args.fallback, vm)?;
399+
let unboundop = resolve_unboundop(unboundarg, UnboundOp::Replace, vm)?;
400+
let fallback = resolve_fallback(fallbackarg, Fallback::Full.as_i32(), vm)?;
401+
queue_create(maxsize, unboundop, fallback).map_err(|err| err.into_py(-1, vm))
396402
}
397403

398404
#[pyfunction]
399-
fn destroy(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
400-
let qid = qid_arg(&args, "destroy", vm)?;
405+
fn destroy(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
406+
let qid = parse_qid(&args.qid, vm)?;
401407
queue_destroy(qid).map_err(|err| err.into_py(qid, vm))
402408
}
403409

@@ -429,33 +435,10 @@ pub(crate) mod _interpqueues {
429435
}
430436

431437
#[pyfunction]
432-
fn put(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
433-
let qid = Cell::new(None);
434-
let unboundarg = Cell::new(None);
435-
let fallbackarg = Cell::new(None);
436-
let parsed = ArgSpec {
437-
fname: "put",
438-
keywords: &["qid", "obj", "unboundop", "fallback"],
439-
required: 2,
440-
max_positional: 4,
441-
}
442-
.parse_with(
443-
&args,
444-
|i, obj, vm| {
445-
match i {
446-
0 => qid.set(Some(parse_qid(obj, vm)?)),
447-
2 => unboundarg.set(Some(int_arg(obj, vm)?)),
448-
3 => fallbackarg.set(Some(int_arg(obj, vm)?)),
449-
_ => {}
450-
}
451-
Ok(())
452-
},
453-
vm,
454-
)?;
455-
let qid = qid.get().unwrap();
456-
let obj = parsed[1].as_deref().unwrap();
457-
let unboundarg = unboundarg.get().unwrap_or(-1);
458-
let fallbackarg = fallbackarg.get().unwrap_or(-1);
438+
fn put(args: PutArgs, vm: &VirtualMachine) -> PyResult<()> {
439+
let qid = parse_qid(&args.qid, vm)?;
440+
let unboundarg = optional_int_arg(&args.unboundop, vm)?;
441+
let fallbackarg = optional_int_arg(&args.fallback, vm)?;
459442
// The queue is only consulted when one of the arguments needs its default.
460443
let (default_unboundop, default_fallback) = if unboundarg < 0 || fallbackarg < 0 {
461444
let (unboundop, fallback) = queue_defaults(qid).map_err(|err| err.into_py(qid, vm))?;
@@ -465,7 +448,7 @@ pub(crate) mod _interpqueues {
465448
};
466449
let unboundop = resolve_unboundop(unboundarg, default_unboundop, vm)?;
467450
let fallback = resolve_fallback(fallbackarg, default_fallback, vm)?;
468-
let value = SharedValue::from_object(obj, fallback, vm)?;
451+
let value = SharedValue::from_object(&args.obj, fallback, vm)?;
469452
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
470453
let mut state = queue.lock();
471454
if !state.alive {
@@ -484,8 +467,8 @@ pub(crate) mod _interpqueues {
484467
}
485468

486469
#[pyfunction]
487-
fn get(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
488-
let qid = qid_arg(&args, "get", vm)?;
470+
fn get(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult {
471+
let qid = parse_qid(&args.qid, vm)?;
489472
let item = {
490473
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
491474
let mut state = queue.lock();
@@ -511,20 +494,20 @@ pub(crate) mod _interpqueues {
511494
}
512495

513496
#[pyfunction]
514-
fn bind(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
515-
let qid = qid_arg(&args, "bind", vm)?;
497+
fn bind(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
498+
let qid = parse_qid(&args.qid, vm)?;
516499
queue_bind(qid).map_err(|err| err.into_py(qid, vm))
517500
}
518501

519502
#[pyfunction]
520-
fn release(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
521-
let qid = qid_arg(&args, "release", vm)?;
503+
fn release(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
504+
let qid = parse_qid(&args.qid, vm)?;
522505
queue_release(qid).map_err(|err| err.into_py(qid, vm))
523506
}
524507

525508
#[pyfunction]
526-
fn get_maxsize(args: FuncArgs, vm: &VirtualMachine) -> PyResult<isize> {
527-
let qid = qid_arg(&args, "get_maxsize", vm)?;
509+
fn get_maxsize(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<isize> {
510+
let qid = parse_qid(&args.qid, vm)?;
528511
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
529512
let state = queue.lock();
530513
if !state.alive {
@@ -534,8 +517,8 @@ pub(crate) mod _interpqueues {
534517
}
535518

536519
#[pyfunction]
537-
fn get_queue_defaults(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
538-
let qid = qid_arg(&args, "get_queue_defaults", vm)?;
520+
fn get_queue_defaults(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult {
521+
let qid = parse_qid(&args.qid, vm)?;
539522
let (unboundop, fallback) = queue_defaults(qid).map_err(|err| err.into_py(qid, vm))?;
540523
Ok(vm
541524
.ctx
@@ -547,8 +530,8 @@ pub(crate) mod _interpqueues {
547530
}
548531

549532
#[pyfunction]
550-
fn is_full(args: FuncArgs, vm: &VirtualMachine) -> PyResult<bool> {
551-
let qid = qid_arg(&args, "is_full", vm)?;
533+
fn is_full(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<bool> {
534+
let qid = parse_qid(&args.qid, vm)?;
552535
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
553536
let state = queue.lock();
554537
if !state.alive {
@@ -558,8 +541,8 @@ pub(crate) mod _interpqueues {
558541
}
559542

560543
#[pyfunction]
561-
fn get_count(args: FuncArgs, vm: &VirtualMachine) -> PyResult<usize> {
562-
let qid = qid_arg(&args, "get_count", vm)?;
544+
fn get_count(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<usize> {
545+
let qid = parse_qid(&args.qid, vm)?;
563546
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
564547
let state = queue.lock();
565548
if !state.alive {
@@ -569,29 +552,19 @@ pub(crate) mod _interpqueues {
569552
}
570553

571554
#[pyfunction]
572-
fn _register_heap_types(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
573-
let parsed = ArgSpec {
574-
fname: "_register_heap_types",
575-
keywords: &["queuetype", "emptyerror", "fullerror"],
576-
required: 3,
577-
max_positional: 3,
578-
}
579-
.parse(&args, vm)?;
580-
let queue = parsed[0]
581-
.clone()
582-
.unwrap()
555+
fn _register_heap_types(args: RegisterHeapTypesArgs, vm: &VirtualMachine) -> PyResult<()> {
556+
let queue = args
557+
.queuetype
583558
.downcast::<PyType>()
584559
.map_err(|_| vm.new_type_error("expected a type for 'queuetype'"))?;
585-
let empty = parsed[1]
586-
.clone()
587-
.unwrap()
560+
let empty = args
561+
.emptyerror
588562
.downcast::<PyType>()
589563
.ok()
590564
.filter(|ty| ty.fast_issubclass(vm.ctx.exceptions.base_exception_type))
591565
.ok_or_else(|| vm.new_type_error("expected an exception type for 'emptyerror'"))?;
592-
let full = parsed[2]
593-
.clone()
594-
.unwrap()
566+
let full = args
567+
.fullerror
595568
.downcast::<PyType>()
596569
.ok()
597570
.filter(|ty| ty.fast_issubclass(vm.ctx.exceptions.base_exception_type))

0 commit comments

Comments
 (0)