1#[cfg(stageleft_runtime)]
7use std::marker::PhantomData;
8
9use super::Slicable;
10#[cfg(stageleft_runtime)]
11use crate::forward_handle::{CycleCollection, CycleCollectionWithInitial};
12use crate::forward_handle::{TickCycle, TickCycleHandle};
13use crate::live_collections::boundedness::{Bounded, Boundedness, Unbounded};
14use crate::live_collections::keyed_singleton::{
15 BoundedValue, KeyedSingletonBound, KeyedSingletonSnapshotBound,
16};
17use crate::live_collections::optional::OptionalBound;
18use crate::live_collections::singleton::SingletonBound;
19use crate::live_collections::stream::{ExactlyOnce, Ordering, Retries, TotalOrder};
20use crate::location::Location;
21use crate::location::tick::{DeferTick, Tick};
22use crate::nondet::{NonDet, nondet};
23
24pub struct Default<T> {
29 pub(crate) collection: T,
30 pub(crate) nondet: NonDet,
31}
32
33impl<T> Default<T> {
34 pub fn new(collection: T, nondet: NonDet) -> Self {
36 Self { collection, nondet }
37 }
38}
39
40#[doc(hidden)]
42#[deprecated(
43 note = "use `use::batch(...)` for stream-like collections or `use::snapshot(...)` for singleton-like collections instead"
44)]
45pub fn default<T>(t: T, nondet: NonDet) -> Default<T> {
46 Default::new(t, nondet)
47}
48
49pub struct Batch<T, H = ()> {
53 pub(crate) collection: T,
54 pub(crate) nondet: NonDet<H>,
55}
56
57impl<T, H> Batch<T, H> {
58 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
60 Self { collection, nondet }
61 }
62}
63
64pub fn batch<T, H>(t: T, nondet: NonDet<H>) -> Batch<T, H> {
69 Batch::new(t, nondet)
70}
71
72pub struct Snapshot<T, H = ()> {
76 pub(crate) collection: T,
77 pub(crate) nondet: NonDet<H>,
78}
79
80impl<T, H> Snapshot<T, H> {
81 pub fn new(collection: T, nondet: NonDet<H>) -> Self {
83 Self { collection, nondet }
84 }
85}
86
87pub fn snapshot<T, H>(t: T, nondet: NonDet<H>) -> Snapshot<T, H> {
93 Snapshot::new(t, nondet)
94}
95
96#[cfg(feature = "tokio")]
102pub struct Time {
103 pub(crate) nondet: NonDet,
104}
105
106#[cfg(feature = "tokio")]
107impl Time {
108 pub fn new(nondet: NonDet) -> Self {
110 Self { nondet }
111 }
112}
113
114#[cfg(feature = "tokio")]
121pub fn time(nondet: NonDet) -> Time {
122 Time::new(nondet)
123}
124
125pub struct Atomic<T> {
129 pub(crate) collection: T,
130 pub(crate) nondet: NonDet,
131}
132
133impl<T> Atomic<T> {
134 pub fn new(collection: T, nondet: NonDet) -> Self {
136 Self { collection, nondet }
137 }
138}
139
140pub fn atomic<T>(t: T, nondet: NonDet) -> Atomic<T> {
142 Atomic::new(t, nondet)
143}
144
145#[cfg(stageleft_runtime)]
158pub fn state<'t, S, L>(tick: &'t Tick<L>) -> StateBuilder<'t, S, L> {
159 StateBuilder {
160 tick,
161 _phantom: PhantomData,
162 }
163}
164
165#[cfg(stageleft_runtime)]
167pub struct StateBuilder<'t, S, L> {
168 tick: &'t Tick<L>,
169 _phantom: PhantomData<S>,
170}
171
172#[cfg(stageleft_runtime)]
173impl<'t, 'a, S, L: Location<'a>> StateBuilder<'t, S, L> {
174 #[expect(
182 private_bounds,
183 reason = "only Hydro collections can implement CycleCollectionWithInitial"
184 )]
185 pub fn build(self, initial_fn: impl FnOnce(&'t Tick<L>) -> S) -> (TickCycleHandle<'a, S>, S)
186 where
187 S: CycleCollectionWithInitial<'a, TickCycle, Location = Tick<L::DropConsistency>>,
188 {
189 let initial = initial_fn(self.tick);
190 initial.location().clone().cycle_with_initial(initial)
191 }
192}
193
194#[cfg(stageleft_runtime)]
202pub fn state_null<'t, S, L>(tick: &'t Tick<L>) -> StateNullBuilder<'t, S, L> {
203 StateNullBuilder {
204 tick,
205 _phantom: PhantomData,
206 }
207}
208
209#[cfg(stageleft_runtime)]
211pub struct StateNullBuilder<'t, S, L> {
212 tick: &'t Tick<L>,
213 _phantom: PhantomData<S>,
214}
215
216#[cfg(stageleft_runtime)]
217impl<'t, 'a, S, L: Location<'a>> StateNullBuilder<'t, S, L> {
218 #[expect(
220 private_bounds,
221 reason = "only Hydro collections can implement CycleCollection"
222 )]
223 pub fn build(self) -> (TickCycleHandle<'a, S>, S)
224 where
225 S: CycleCollection<'a, TickCycle, Location = Tick<L::DropConsistency>> + DeferTick,
226 {
227 self.tick.cycle::<S, _>()
228 }
229}
230
231#[cfg(feature = "tokio")]
236impl<'a, L: Location<'a>> Slicable<'a, L> for Time {
237 type Slice =
238 crate::live_collections::Singleton<tokio::time::Instant, Tick<L::DropConsistency>, Bounded>;
239 type Backtrace = crate::compile::ir::backtrace::Backtrace;
240
241 fn get_location(&self) -> L {
242 unreachable!(
243 "`use::time(...)` carries no collection; it cannot be the first `use` of a `sliced!` block"
244 )
245 }
246 fn slice(self, tick: &Tick<L>, backtrace: Self::Backtrace) -> Self::Slice {
247 let out = tick.current_tick_instant(self.nondet);
248 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
249 out
250 }
251}
252
253impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
261 Slicable<'a, L::DropConsistency> for Default<crate::live_collections::Stream<T, L, B, O, R>>
262{
263 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
264 type Backtrace = crate::compile::ir::backtrace::Backtrace;
265
266 fn get_location(&self) -> L::DropConsistency {
267 self.collection.location().drop_consistency()
268 }
269 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
270 let _ = self.nondet;
271 let out = self.collection.batch(
272 tick,
273 nondet!(),
274 );
275 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
276 out
277 }
278}
279
280impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
281 for Default<crate::live_collections::Singleton<T, L, B>>
282{
283 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
284 type Backtrace = crate::compile::ir::backtrace::Backtrace;
285
286 fn get_location(&self) -> L::DropConsistency {
287 self.collection.location().drop_consistency()
288 }
289 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
290 let _ = self.nondet;
291 let out = self.collection.snapshot(
292 tick,
293 nondet!(),
294 );
295 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
296 out
297 }
298}
299
300impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
301 for Default<crate::live_collections::Optional<T, L, B>>
302{
303 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
304 type Backtrace = crate::compile::ir::backtrace::Backtrace;
305
306 fn get_location(&self) -> L::DropConsistency {
307 self.collection.location().drop_consistency()
308 }
309 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
310 let out = self.collection.snapshot(tick, self.nondet);
311 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
312 out
313 }
314}
315
316impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
317 Slicable<'a, L::DropConsistency>
318 for Default<crate::live_collections::KeyedStream<K, V, L, B, O, R>>
319{
320 type Slice =
321 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
322 type Backtrace = crate::compile::ir::backtrace::Backtrace;
323
324 fn get_location(&self) -> L::DropConsistency {
325 self.collection.location().drop_consistency()
326 }
327 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
328 let _ = self.nondet;
329 let out = self.collection.batch(
330 tick,
331 nondet!(),
332 );
333 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
334 out
335 }
336}
337
338impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound<ValueBound = Unbounded>>
339 Slicable<'a, L::DropConsistency>
340 for Default<crate::live_collections::KeyedSingleton<K, V, L, B>>
341{
342 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
343 type Backtrace = crate::compile::ir::backtrace::Backtrace;
344
345 fn get_location(&self) -> L::DropConsistency {
346 self.collection.location().drop_consistency()
347 }
348 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
349 let _ = self.nondet;
350 let out = self.collection.snapshot(
351 tick,
352 nondet!(),
353 );
354 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
355 out
356 }
357}
358
359impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
360 for Default<crate::live_collections::KeyedSingleton<K, V, L, BoundedValue>>
361{
362 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
363 type Backtrace = crate::compile::ir::backtrace::Backtrace;
364
365 fn get_location(&self) -> L::DropConsistency {
366 self.collection.location().drop_consistency()
367 }
368 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
369 let _ = self.nondet;
370 let out = self.collection.batch(
371 tick,
372 nondet!(),
373 );
374 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
375 out
376 }
377}
378
379impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
387 Slicable<'a, L::DropConsistency>
388 for Batch<
389 crate::live_collections::Stream<T, L, B, O, R>,
390 Option<crate::sim_hooks::BatchHook<T, O, R, L::SimHookScope>>,
391 >
392{
393 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
394 type Backtrace = crate::compile::ir::backtrace::Backtrace;
395
396 fn get_location(&self) -> L::DropConsistency {
397 self.collection.location().drop_consistency()
398 }
399 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
400 let out = self.collection.batch(tick, self.nondet);
401 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
402 out
403 }
404}
405
406impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
407 Slicable<'a, L::DropConsistency>
408 for Batch<
409 crate::live_collections::KeyedStream<K, V, L, B, O, R>,
410 Option<crate::sim_hooks::KeyedBatchHook<K, V, O, R, L::SimHookScope>>,
411 >
412{
413 type Slice =
414 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
415 type Backtrace = crate::compile::ir::backtrace::Backtrace;
416
417 fn get_location(&self) -> L::DropConsistency {
418 self.collection.location().drop_consistency()
419 }
420 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
421 let out = self.collection.batch(tick, self.nondet);
422 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
423 out
424 }
425}
426
427impl<'a, K, V, L: Location<'a>, B: KeyedSingletonBound<ValueBound = Bounded>>
428 Slicable<'a, L::DropConsistency>
429 for Batch<
430 crate::live_collections::KeyedSingleton<K, V, L, B>,
431 Option<crate::sim_hooks::KeyedBatchHook<K, V, TotalOrder, ExactlyOnce, L::SimHookScope>>,
432 >
433{
434 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
435 type Backtrace = crate::compile::ir::backtrace::Backtrace;
436
437 fn get_location(&self) -> L::DropConsistency {
438 self.collection.location().drop_consistency()
439 }
440 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
441 let out = self.collection.batch(tick, self.nondet);
442 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
443 out
444 }
445}
446
447impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
455 for Snapshot<
456 crate::live_collections::Singleton<T, L, B>,
457 Option<crate::sim_hooks::SnapshotHook<T, L::SimHookScope>>,
458 >
459{
460 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
461 type Backtrace = crate::compile::ir::backtrace::Backtrace;
462
463 fn get_location(&self) -> L::DropConsistency {
464 self.collection.location().drop_consistency()
465 }
466 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
467 let out = self.collection.snapshot(tick, self.nondet);
468 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
469 out
470 }
471}
472
473impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
474 for Snapshot<crate::live_collections::Optional<T, L, B>>
475{
476 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
477 type Backtrace = crate::compile::ir::backtrace::Backtrace;
478
479 fn get_location(&self) -> L::DropConsistency {
480 self.collection.location().drop_consistency()
481 }
482 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
483 let out = self.collection.snapshot(tick, self.nondet);
484 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
485 out
486 }
487}
488
489impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound> Slicable<'a, L::DropConsistency>
490 for Snapshot<
491 crate::live_collections::KeyedSingleton<K, V, L, B>,
492 Option<crate::sim_hooks::KeyedSnapshotHook<K, V, L::SimHookScope>>,
493 >
494{
495 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
496 type Backtrace = crate::compile::ir::backtrace::Backtrace;
497
498 fn get_location(&self) -> L::DropConsistency {
499 self.collection.location().drop_consistency()
500 }
501 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
502 let out = self.collection.snapshot(tick, self.nondet);
503 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
504 out
505 }
506}
507
508impl<'a, T, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
513 Slicable<'a, L::DropConsistency>
514 for Atomic<crate::live_collections::Stream<T, crate::location::Atomic<L>, B, O, R>>
515{
516 type Slice = crate::live_collections::Stream<T, Tick<L::DropConsistency>, Bounded, O, R>;
517 type Backtrace = crate::compile::ir::backtrace::Backtrace;
518 fn get_location(&self) -> L::DropConsistency {
519 self.collection.location().tick.l.drop_consistency()
520 }
521
522 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
523 let _ = self.nondet;
524 let out = self.collection.batch_atomic(
525 tick,
526 nondet!(),
527 );
528 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
529 out
530 }
531}
532
533impl<'a, T, L: Location<'a>, B: SingletonBound> Slicable<'a, L::DropConsistency>
534 for Atomic<crate::live_collections::Singleton<T, crate::location::Atomic<L>, B>>
535{
536 type Slice = crate::live_collections::Singleton<T, Tick<L::DropConsistency>, Bounded>;
537 type Backtrace = crate::compile::ir::backtrace::Backtrace;
538 fn get_location(&self) -> L::DropConsistency {
539 self.collection.location().tick.l.drop_consistency()
540 }
541
542 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
543 let _ = self.nondet;
544 let out = self.collection.snapshot_atomic(
545 tick,
546 nondet!(),
547 );
548 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
549 out
550 }
551}
552
553impl<'a, T, L: Location<'a>, B: OptionalBound> Slicable<'a, L::DropConsistency>
554 for Atomic<crate::live_collections::Optional<T, crate::location::Atomic<L>, B>>
555{
556 type Slice = crate::live_collections::Optional<T, Tick<L::DropConsistency>, Bounded>;
557 type Backtrace = crate::compile::ir::backtrace::Backtrace;
558 fn get_location(&self) -> L::DropConsistency {
559 self.collection.location().tick.l.drop_consistency()
560 }
561
562 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
563 let out = self.collection.snapshot_atomic(tick, self.nondet);
564 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
565 out
566 }
567}
568
569impl<'a, K, V, L: Location<'a>, B: Boundedness, O: Ordering, R: Retries>
570 Slicable<'a, L::DropConsistency>
571 for Atomic<crate::live_collections::KeyedStream<K, V, crate::location::Atomic<L>, B, O, R>>
572{
573 type Slice =
574 crate::live_collections::KeyedStream<K, V, Tick<L::DropConsistency>, Bounded, O, R>;
575 type Backtrace = crate::compile::ir::backtrace::Backtrace;
576 fn get_location(&self) -> L::DropConsistency {
577 self.collection.location().tick.l.drop_consistency()
578 }
579
580 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
581 let out = self.collection.batch_atomic(tick, self.nondet);
582 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
583 out
584 }
585}
586
587impl<'a, K, V, L: Location<'a>, B: KeyedSingletonSnapshotBound<ValueBound = Unbounded>>
588 Slicable<'a, L::DropConsistency>
589 for Atomic<crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, B>>
590{
591 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
592 type Backtrace = crate::compile::ir::backtrace::Backtrace;
593 fn get_location(&self) -> L::DropConsistency {
594 self.collection.location().tick.l.drop_consistency()
595 }
596
597 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
598 let out = self.collection.snapshot_atomic(tick, self.nondet);
599 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
600 out
601 }
602}
603
604impl<'a, K, V, L: Location<'a>> Slicable<'a, L::DropConsistency>
605 for Atomic<
606 crate::live_collections::KeyedSingleton<K, V, crate::location::Atomic<L>, BoundedValue>,
607 >
608{
609 type Slice = crate::live_collections::KeyedSingleton<K, V, Tick<L::DropConsistency>, Bounded>;
610 type Backtrace = crate::compile::ir::backtrace::Backtrace;
611 fn get_location(&self) -> L::DropConsistency {
612 self.collection.location().tick.l.drop_consistency()
613 }
614
615 fn slice(self, tick: &Tick<L::DropConsistency>, backtrace: Self::Backtrace) -> Self::Slice {
616 let out = self.collection.batch_atomic(tick, self.nondet);
617 out.ir_node.borrow_mut().op_metadata_mut().backtrace = backtrace;
618 out
619 }
620}