Skip to content

Commit 00878be

Browse files
youknowdotcodex
authored andcommitted
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 05daf00 commit 00878be

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;
@@ -337,23 +336,11 @@ pub(crate) mod _interpqueues {
337336
Err(vm.new_overflow_error(format!("max queue ID is {}, got {repr}", i64::MAX)))
338337
}
339338

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

359346
#[expect(clippy::unnecessary_wraps, reason = "Needs to comply with a signature")]
@@ -363,39 +350,58 @@ pub(crate) mod _interpqueues {
363350
Ok(())
364351
}
365352

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

396402
#[pyfunction]
397-
fn destroy(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
398-
let qid = qid_arg(&args, "destroy", vm)?;
403+
fn destroy(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
404+
let qid = parse_qid(&args.qid, vm)?;
399405
queue_destroy(qid).map_err(|err| err.into_py(qid, vm))
400406
}
401407

@@ -427,33 +433,10 @@ pub(crate) mod _interpqueues {
427433
}
428434

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

484467
#[pyfunction]
485-
fn get(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
486-
let qid = qid_arg(&args, "get", vm)?;
468+
fn get(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult {
469+
let qid = parse_qid(&args.qid, vm)?;
487470
let item = {
488471
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
489472
let mut state = queue.lock();
@@ -509,20 +492,20 @@ pub(crate) mod _interpqueues {
509492
}
510493

511494
#[pyfunction]
512-
fn bind(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
513-
let qid = qid_arg(&args, "bind", vm)?;
495+
fn bind(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
496+
let qid = parse_qid(&args.qid, vm)?;
514497
queue_bind(qid).map_err(|err| err.into_py(qid, vm))
515498
}
516499

517500
#[pyfunction]
518-
fn release(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
519-
let qid = qid_arg(&args, "release", vm)?;
501+
fn release(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<()> {
502+
let qid = parse_qid(&args.qid, vm)?;
520503
queue_release(qid).map_err(|err| err.into_py(qid, vm))
521504
}
522505

523506
#[pyfunction]
524-
fn get_maxsize(args: FuncArgs, vm: &VirtualMachine) -> PyResult<isize> {
525-
let qid = qid_arg(&args, "get_maxsize", vm)?;
507+
fn get_maxsize(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<isize> {
508+
let qid = parse_qid(&args.qid, vm)?;
526509
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
527510
let state = queue.lock();
528511
if !state.alive {
@@ -532,8 +515,8 @@ pub(crate) mod _interpqueues {
532515
}
533516

534517
#[pyfunction]
535-
fn get_queue_defaults(args: FuncArgs, vm: &VirtualMachine) -> PyResult {
536-
let qid = qid_arg(&args, "get_queue_defaults", vm)?;
518+
fn get_queue_defaults(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult {
519+
let qid = parse_qid(&args.qid, vm)?;
537520
let (unboundop, fallback) = queue_defaults(qid).map_err(|err| err.into_py(qid, vm))?;
538521
Ok(vm
539522
.ctx
@@ -545,8 +528,8 @@ pub(crate) mod _interpqueues {
545528
}
546529

547530
#[pyfunction]
548-
fn is_full(args: FuncArgs, vm: &VirtualMachine) -> PyResult<bool> {
549-
let qid = qid_arg(&args, "is_full", vm)?;
531+
fn is_full(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<bool> {
532+
let qid = parse_qid(&args.qid, vm)?;
550533
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
551534
let state = queue.lock();
552535
if !state.alive {
@@ -556,8 +539,8 @@ pub(crate) mod _interpqueues {
556539
}
557540

558541
#[pyfunction]
559-
fn get_count(args: FuncArgs, vm: &VirtualMachine) -> PyResult<usize> {
560-
let qid = qid_arg(&args, "get_count", vm)?;
542+
fn get_count(args: QueueIdArgs, vm: &VirtualMachine) -> PyResult<usize> {
543+
let qid = parse_qid(&args.qid, vm)?;
561544
let queue = queue_lookup(qid).map_err(|err| err.into_py(qid, vm))?;
562545
let state = queue.lock();
563546
if !state.alive {
@@ -567,29 +550,19 @@ pub(crate) mod _interpqueues {
567550
}
568551

569552
#[pyfunction]
570-
fn _register_heap_types(args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
571-
let parsed = ArgSpec {
572-
fname: "_register_heap_types",
573-
keywords: &["queuetype", "emptyerror", "fullerror"],
574-
required: 3,
575-
max_positional: 3,
576-
}
577-
.parse(&args, vm)?;
578-
let queue = parsed[0]
579-
.clone()
580-
.unwrap()
553+
fn _register_heap_types(args: RegisterHeapTypesArgs, vm: &VirtualMachine) -> PyResult<()> {
554+
let queue = args
555+
.queuetype
581556
.downcast::<PyType>()
582557
.map_err(|_| vm.new_type_error("expected a type for 'queuetype'"))?;
583-
let empty = parsed[1]
584-
.clone()
585-
.unwrap()
558+
let empty = args
559+
.emptyerror
586560
.downcast::<PyType>()
587561
.ok()
588562
.filter(|ty| ty.fast_issubclass(vm.ctx.exceptions.base_exception_type))
589563
.ok_or_else(|| vm.new_type_error("expected an exception type for 'emptyerror'"))?;
590-
let full = parsed[2]
591-
.clone()
592-
.unwrap()
564+
let full = args
565+
.fullerror
593566
.downcast::<PyType>()
594567
.ok()
595568
.filter(|ty| ty.fast_issubclass(vm.ctx.exceptions.base_exception_type))

0 commit comments

Comments
 (0)