From 827041c1b6aa1303b57fe7e365423ac30bdcaba3 Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Tue, 17 Feb 2026 21:34:40 +0100 Subject: [PATCH] chore: clean up in preparation for release --- Cargo.toml | 5 ++- benches/comparisons/diamond_pattern.rs | 2 +- benches/comparisons/etl_pipeline.rs | 2 +- benches/patterns/diamond.rs | 2 +- benches/realistic/etl.rs | 2 +- benches/realistic/mixed.rs | 2 +- dagx-macros/src/lib.rs | 54 ++++---------------------- dagx-test/LICENSE | 21 ++++++++++ examples/01_basic.rs | 2 +- examples/03_fan_in.rs | 2 +- examples/04_parallel_computation.rs | 18 ++++----- examples/data_pipeline.rs | 10 ++--- scripts/release_check.sh | 49 ++++++----------------- src/builder.rs | 9 ----- src/deps.rs | 30 +++++--------- src/deps/tests.rs | 34 +++------------- src/lib.rs | 11 +++--- src/output.rs | 5 +-- src/runner.rs | 12 +++--- src/task.rs | 9 ----- src/task/tests.rs | 6 --- tests/boundaries/deep_chains.rs | 22 +++++------ tests/cycle_prevention.rs | 2 +- tests/dependencies/tuples.rs | 10 ++--- tests/errors/propagation.rs | 2 +- tests/execution/mod.rs | 2 +- tests/interleaving/mod.rs | 4 +- tests/parallelism/timing.rs | 2 +- 28 files changed, 112 insertions(+), 219 deletions(-) create mode 100644 dagx-test/LICENSE diff --git a/Cargo.toml b/Cargo.toml index 698c97d..76c99e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,8 @@ categories = ["asynchronous", "concurrency", "data-structures"] exclude = [".claude/", ".jj/", "dagx-spec.md"] [features] -default = [] +default = ["derive"] +derive = ["dep:dagx-macros"] tracing = ["dep:tracing"] [workspace.lints.rust] @@ -32,7 +33,7 @@ workspace = true [dependencies] futures-util = { version = "0.3", default-features = false, features = ["std"] } -dagx-macros = { version = "0.3.1", path = "./dagx-macros" } +dagx-macros = { version = "0.3.1", path = "./dagx-macros", optional = true } tracing = { version = "0.1", optional = true } [dev-dependencies] diff --git a/benches/comparisons/diamond_pattern.rs b/benches/comparisons/diamond_pattern.rs index 2088e6f..942b997 100644 --- a/benches/comparisons/diamond_pattern.rs +++ b/benches/comparisons/diamond_pattern.rs @@ -26,7 +26,7 @@ pub fn bench_diamond_pattern(c: &mut Criterion) { .depends_on(a); let d = dag .add_task(task_fn::<(i32, i32), _, _>(|(x, y): (&i32, &i32)| x + y)) - .depends_on((&b, &c)); + .depends_on((b, c)); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/benches/comparisons/etl_pipeline.rs b/benches/comparisons/etl_pipeline.rs index 75fe567..79ae01a 100644 --- a/benches/comparisons/etl_pipeline.rs +++ b/benches/comparisons/etl_pipeline.rs @@ -51,7 +51,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) { result }, )) - .depends_on((&transform1, &transform2, &transform3)); + .depends_on((transform1, transform2, transform3)); // Validate let validate = dag diff --git a/benches/patterns/diamond.rs b/benches/patterns/diamond.rs index 14f1fda..e3685de 100644 --- a/benches/patterns/diamond.rs +++ b/benches/patterns/diamond.rs @@ -22,7 +22,7 @@ pub fn bench_diamond(c: &mut Criterion) { .depends_on(source); dag.add_task(task_fn::<(i32, i32), _, _>(|(l, r): (&i32, &i32)| l + r)) - .depends_on((&left, &right)); + .depends_on((left, right)); } let _output = dag diff --git a/benches/realistic/etl.rs b/benches/realistic/etl.rs index 13381c4..00f63f2 100644 --- a/benches/realistic/etl.rs +++ b/benches/realistic/etl.rs @@ -88,7 +88,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) { ) }, )) - .depends_on((&validate, &scores, &names)); + .depends_on((validate, scores, names)); let _output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/benches/realistic/mixed.rs b/benches/realistic/mixed.rs index e9d2d08..7b55ba9 100644 --- a/benches/realistic/mixed.rs +++ b/benches/realistic/mixed.rs @@ -42,7 +42,7 @@ pub fn bench_mixed_patterns(c: &mut Criterion) { format!("Matches: {}, Total bytes: {}, Count: {}", a1, a2, a3) }, )) - .depends_on((&analysis1, &analysis2, &analysis3)); + .depends_on((analysis1, analysis2, analysis3)); // Stage 4: Fan-out final report to multiple destinations for i in 0..3 { diff --git a/dagx-macros/src/lib.rs b/dagx-macros/src/lib.rs index 2abcc6c..a87adf0 100644 --- a/dagx-macros/src/lib.rs +++ b/dagx-macros/src/lib.rs @@ -155,9 +155,10 @@ use syn::{parse_macro_input, FnArg, Ident, ImplItem, ItemImpl, Pat, PatType, Ret /// impl Task<(i32, i32)> for Add { /// type Output = i32; /// -/// async fn run(&mut self, input: Self::Input) -> Self::Output { -/// let (a, b) = input; -/// Self::run_impl(&a, &b).await +/// async fn run(&mut self, _input: Self::Input) -> Self::Output { +/// let (a, _input) = _input.next(); +/// let (b, _input) = _input.next(); +/// Self::run_impl(a, b).await /// } /// } /// @@ -168,36 +169,6 @@ use syn::{parse_macro_input, FnArg, Ident, ImplItem, ItemImpl, Pat, PatType, Ret /// } /// } /// ``` -/// -/// For stateful tasks (with &mut self): -/// -/// ```ignore -/// // Your code: -/// #[task] -/// impl Counter { -/// async fn run(&mut self, inc: &i32) -> i32 { -/// self.count += inc; -/// self.count -/// } -/// } -/// -/// // Generated: -/// impl Task<(i32)> for Counter { -/// type Output = i32; -/// -/// async fn run(&mut self, input: Self::Input) -> Self::Output { -/// let inc = input; -/// self.run_impl(&inc).await -/// } -/// } -/// -/// impl Counter { -/// async fn run_impl(&mut self, inc: &i32) -> i32 { -/// self.count += inc; -/// self.count -/// } -/// } -/// ``` #[proc_macro_attribute] pub fn task(_attr: TokenStream, item: TokenStream) -> TokenStream { let impl_block = parse_macro_input!(item as ItemImpl); @@ -273,18 +244,7 @@ pub fn task(_attr: TokenStream, item: TokenStream) -> TokenStream { // Extract return type let output_type = match &run_method.sig.output { ReturnType::Default => syn::parse_quote!(()), - ReturnType::Type(_, ty) => { - if let Type::Tuple(_tuple) = &**ty { - return syn::Error::new_spanned( - ty, - "Returning bare tuples from task functions is currently not supported.\n\n\ - Please wrap this in a newtype or struct.", - ) - .into_compile_error() - .into(); - } - ty.clone() - } + ReturnType::Type(_, ty) => ty.clone(), }; // Build Input type based on parameter count @@ -299,7 +259,7 @@ pub fn task(_attr: TokenStream, item: TokenStream) -> TokenStream { let ident = Ident::new(&format!("__dagx_extract_{}", ident), Span::mixed_site()); ( quote! { - let (#ident, input) = input.next(); + let (#ident, _input) = _input.next(); }, ident, ) @@ -333,7 +293,7 @@ pub fn task(_attr: TokenStream, item: TokenStream) -> TokenStream { impl ::dagx::Task<#input_type> for #struct_name { type Output = #output_type; - async fn run(mut self, mut input: ::dagx::TaskInput<'_, #input_type>) -> Self::Output { + async fn run(mut self, mut _input: ::dagx::TaskInput<'_, #input_type>) -> Self::Output { #param_destructure #run_call } diff --git a/dagx-test/LICENSE b/dagx-test/LICENSE new file mode 100644 index 0000000..a4ad6f1 --- /dev/null +++ b/dagx-test/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Stephen Waits + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/examples/01_basic.rs b/examples/01_basic.rs index be8ac2e..097bde2 100644 --- a/examples/01_basic.rs +++ b/examples/01_basic.rs @@ -93,7 +93,7 @@ async fn main() { .add_task(Add { label: "Sum".to_string(), }) - .depends_on((&x, &y)); // Pass handles as a tuple + .depends_on((x, y)); // Pass handles as a tuple // sum is now TaskHandle // Step 6: Execute the DAG diff --git a/examples/03_fan_in.rs b/examples/03_fan_in.rs index 05db4f6..ad915e5 100644 --- a/examples/03_fan_in.rs +++ b/examples/03_fan_in.rs @@ -29,7 +29,7 @@ //! ## Key Concepts //! - **Fan-in**: Multiple tasks' outputs are consumed by a single downstream task //! - **Aggregation**: Combining multiple values into a single result -//! - **Parameter order**: The order in `.depends_on((&a, &b, &c))` must match +//! - **Parameter order**: The order in `.depends_on((a, b, c))` must match //! the function signature `fn run(a: &T1, b: &T2, c: &T3)` //! //! ## Use Cases diff --git a/examples/04_parallel_computation.rs b/examples/04_parallel_computation.rs index 4036740..13f9527 100644 --- a/examples/04_parallel_computation.rs +++ b/examples/04_parallel_computation.rs @@ -52,7 +52,7 @@ //! This proves dagx runs tasks on multiple CPU cores simultaneously. //! ``` -use dagx::{task, DagResult, DagRunner, Task, TaskInput}; +use dagx::{task, DagResult, DagRunner}; use std::time::{Duration, Instant}; use tokio::time::sleep; @@ -149,15 +149,15 @@ async fn main() -> DagResult<()> { let start = Instant::now(); // Run tasks sequentially (not using DAG, just raw execution) - let task1 = ComputeSum::new(1, 251, WORK_DELAY); - let task2 = ComputeSum::new(251, 501, WORK_DELAY); - let task3 = ComputeSum::new(501, 751, WORK_DELAY); - let task4 = ComputeSum::new(751, 1001, WORK_DELAY); + let mut task1 = ComputeSum::new(1, 251, WORK_DELAY); + let mut task2 = ComputeSum::new(251, 501, WORK_DELAY); + let mut task3 = ComputeSum::new(501, 751, WORK_DELAY); + let mut task4 = ComputeSum::new(751, 1001, WORK_DELAY); - let r1 = task1.run(TaskInput::empty()).await; - let r2 = task2.run(TaskInput::empty()).await; - let r3 = task3.run(TaskInput::empty()).await; - let r4 = task4.run(TaskInput::empty()).await; + let r1 = task1.run_impl().await; + let r2 = task2.run_impl().await; + let r3 = task3.run_impl().await; + let r4 = task4.run_impl().await; let result = r1 + r2 + r3 + r4; let elapsed = start.elapsed(); diff --git a/examples/data_pipeline.rs b/examples/data_pipeline.rs index e012fe1..ab38b17 100644 --- a/examples/data_pipeline.rs +++ b/examples/data_pipeline.rs @@ -203,20 +203,18 @@ async fn main() { // Stage 3: Statistical analysis (parallel operations on transformed data) let sum = dag .add_task(ComputeSum) - .depends_on((&transformed_1, &transformed_2, &transformed_3)); + .depends_on((transformed_1, transformed_2, transformed_3)); let product = dag.add_task(ComputeProduct) - .depends_on((&transformed_1, &transformed_2, &transformed_3)); + .depends_on((transformed_1, transformed_2, transformed_3)); let max = dag .add_task(FindMax) - .depends_on((&transformed_1, &transformed_2, &transformed_3)); + .depends_on((transformed_1, transformed_2, transformed_3)); // Stage 4: Final report - let report = dag - .add_task(GenerateReport) - .depends_on((&sum, &product, &max)); + let report = dag.add_task(GenerateReport).depends_on((sum, product, max)); // Execute the pipeline println!("Executing pipeline...\n"); diff --git a/scripts/release_check.sh b/scripts/release_check.sh index e90afbc..835ecdb 100755 --- a/scripts/release_check.sh +++ b/scripts/release_check.sh @@ -88,7 +88,7 @@ check_pass "Zero clippy warnings" echo "" echo "→ Checking for TODO/FIXME/XXX/HACK in source..." -TODO_COUNT=$(grep -r "TODO\|FIXME\|XXX\|HACK" src/ dagx-macros/src/ 2>/dev/null | wc -l) +TODO_COUNT=$(grep -r "TODO\|FIXME\|XXX\|HACK" src/ dagx-macros/src/ dagx-test/src/ 2>/dev/null | wc -l) if [ "$TODO_COUNT" -gt 0 ]; then check_warn "Found $TODO_COUNT TODO/FIXME/HACK comments in source" else @@ -209,6 +209,7 @@ echo "" echo "→ Verifying LICENSE..." [ -f LICENSE ] || check_fail "LICENSE missing" [ -f dagx-macros/LICENSE ] || check_fail "dagx-macros/LICENSE missing" +[ -f dagx-test/LICENSE ] || check_fail "dagx-test/LICENSE missing" check_pass "LICENSE files present in both crates" # ============================================================================= @@ -259,45 +260,13 @@ echo "→ Verifying benchmarks compile..." cargo bench --no-run || check_fail "Benchmarks failed to compile" check_pass "Benchmarks compile successfully" -# ============================================================================= -# CARGO.TOML METADATA VERIFICATION -# ============================================================================= - -section "CARGO.TOML METADATA" - -echo "→ Checking dagx Cargo.toml..." -grep -q 'name = "dagx"' Cargo.toml || check_fail "Package name incorrect" -grep -q "version = \"$VERSION\"" Cargo.toml || check_fail "Version not $VERSION" -grep -q 'edition = "2021"' Cargo.toml || check_fail "Edition not 2021" -grep -q 'license = "MIT"' Cargo.toml || check_fail "License not MIT" -grep -q 'description = "A minimal, type-safe' Cargo.toml || check_fail "Description missing" -grep -q 'repository = "https://github.com/swaits/dagx"' Cargo.toml || check_fail "Repository URL incorrect" -grep -q 'homepage = "https://github.com/swaits/dagx"' Cargo.toml || check_fail "Homepage URL incorrect" -grep -q 'documentation = "https://docs.rs/dagx"' Cargo.toml || check_fail "Documentation URL incorrect" -grep -q 'readme = "README.md"' Cargo.toml || check_fail "README not specified" -grep -q 'keywords = \["dag"' Cargo.toml || check_fail "Keywords missing" -grep -q 'categories = \["asynchronous"' Cargo.toml || check_fail "Categories missing" -check_pass "dagx Cargo.toml metadata complete and correct" - -echo "" -echo "→ Checking dagx-macros Cargo.toml..." -grep -q 'name = "dagx-macros"' dagx-macros/Cargo.toml || check_fail "dagx-macros name incorrect" -grep -q "version = \"$VERSION\"" dagx-macros/Cargo.toml || check_fail "dagx-macros version not $VERSION" -grep -q 'edition = "2021"' dagx-macros/Cargo.toml || check_fail "dagx-macros edition not 2021" -grep -q 'license = "MIT"' dagx-macros/Cargo.toml || check_fail "dagx-macros license not MIT" -grep -q 'description = "Procedural macros for dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros description missing" -grep -q 'repository = "https://github.com/swaits/dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros repository URL incorrect" -grep -q 'homepage = "https://github.com/swaits/dagx"' dagx-macros/Cargo.toml || check_fail "dagx-macros homepage URL incorrect" -grep -q 'documentation = "https://docs.rs/dagx-macros"' dagx-macros/Cargo.toml || check_fail "dagx-macros documentation URL incorrect" -grep -q 'readme = "README.md"' dagx-macros/Cargo.toml || check_fail "dagx-macros README not specified" -check_pass "dagx-macros Cargo.toml metadata complete and correct" - echo "" echo "→ Verifying version consistency..." DAGX_VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2) MACROS_VERSION=$(grep '^version = ' dagx-macros/Cargo.toml | head -1 | cut -d'"' -f2) -if [ "$DAGX_VERSION" != "$MACROS_VERSION" ]; then - check_fail "Version mismatch: dagx=$DAGX_VERSION, dagx-macros=$MACROS_VERSION" +TEST_VERSION=$(grep '^version = ' dagx-test/Cargo.toml | head -1 | cut -d'"' -f2) +if [ "$DAGX_VERSION" != "$MACROS_VERSION" ] || [ "$DAGX_VERSION" != "$TEST_VERSION" ]; then + check_fail "Version mismatch: dagx=$DAGX_VERSION, dagx-macros=$MACROS_VERSION, dagx-test=$TEST_VERSION" else check_pass "Versions match: both are $DAGX_VERSION" fi @@ -344,7 +313,7 @@ fi section "SECURITY CHECKS" echo "→ Checking for sensitive data..." -if grep -r "api[_-]key\|secret\|password\|token" src/ dagx-macros/src/ 2>/dev/null | grep -v "^Binary" | grep -v "token for a node" | grep -q .; then +if grep -r "api[_-]key\|secret\|password\|token" src/ dagx-macros/src/ dagx-test/src 2>/dev/null | grep -v "^Binary" | grep -v "token for a node" | grep -q .; then check_fail "Potential sensitive data found in source" else check_pass "No sensitive data found" @@ -387,7 +356,11 @@ echo "4. Then publish dagx:" echo " cd .." echo " cargo publish" echo "" -echo "5. Push changes and bookmark:" +echo "5. Then publish dagx-test:" +echo " cd dagx-test" +echo " cargo publish" +echo "" +echo "6. Push changes and bookmark:" echo " jj git push" echo "" echo -e "${BLUE}Note: dagx-macros MUST be published before dagx${NC}" diff --git a/src/builder.rs b/src/builder.rs index babe8fd..5e4577d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -212,13 +212,6 @@ impl Clone for TaskHandle { impl Copy for TaskHandle {} -// TaskHandle can be converted from &TaskHandle (for .get() calls) -impl From<&TaskHandle> for TaskHandle { - fn from(handle: &TaskHandle) -> Self { - *handle - } -} - /// Takes a task and converts it to either a TaskBuilder or a TaskHandle, /// depending on whether it has inputs or not. /// @@ -269,8 +262,6 @@ macro_rules! impl_wire_tuple { }; } -// Generate DepsTuple implementations for tuples of size 2-8. -// Supporting up to 8 elements covers the vast majority of use cases. impl_wire_tuple!(T1); impl_wire_tuple!(T1, T2); impl_wire_tuple!(T1, T2, T3); diff --git a/src/deps.rs b/src/deps.rs index 9f82eb1..310d11b 100644 --- a/src/deps.rs +++ b/src/deps.rs @@ -21,21 +21,9 @@ impl DepsTuple<()> for () { } // Implementation for single dependency (all forms) -impl DepsTuple<(O,)> for T -where - T: Into>, -{ +impl DepsTuple<(O,)> for TaskHandle { fn to_node_ids(self) -> Vec { - vec![self.into().id] - } -} - -impl DepsTuple for (T,) -where - T: Into>, -{ - fn to_node_ids(self) -> Vec { - vec![self.0.into().id] + vec![self.id] } } @@ -47,27 +35,27 @@ where /// This allows flexible dependency specification: /// ```ignore /// // Using handles -/// task.depends_on((&handle_a, &handle_b)) +/// task.depends_on((handle_a, handle_b)) /// /// // Using builders directly -/// task.depends_on((&dag.add_task(TaskA), &dag.add_task(TaskB))) +/// task.depends_on((dag.add_task(TaskA), dag.add_task(TaskB))) /// ``` macro_rules! impl_deps_tuple { ($($T:ident : $O:ident),+) => { - // For tuples of any combination of &TaskHandle, TaskHandle, and TaskBuilder - impl<$($T: Into>, $O),+> DepsTuple<($($O,)+)> for ($($T,)+) + impl<$($O),+> DepsTuple<($($O,)+)> for ($(TaskHandle<$O>,)+) { #[allow(non_snake_case)] fn to_node_ids(self) -> Vec { - let ($($T,)+) = self; - vec![$($T.into().id,)+] + let ($($O,)+) = self; + vec![$($O.id,)+] } } }; } -// Generate DepsTuple implementations for tuples of size 2-8. +// Generate DepsTuple implementations for tuples of size 1-8. // Supporting up to 8 elements covers the vast majority of use cases. +impl_deps_tuple!(T1:O1); impl_deps_tuple!(T1:O1, T2:O2); impl_deps_tuple!(T1:O1, T2:O2, T3:O3); impl_deps_tuple!(T1:O1, T2:O2, T3:O3, T4:O4); diff --git a/src/deps/tests.rs b/src/deps/tests.rs index c58af16..d5ba1ff 100644 --- a/src/deps/tests.rs +++ b/src/deps/tests.rs @@ -57,7 +57,7 @@ fn test_deps_tuple_single_handle_tuple_ref() { id: NodeId(7), _phantom: std::marker::PhantomData, }; - let node_ids = (&handle,).to_node_ids(); + let node_ids = (handle,).to_node_ids(); assert_eq!(node_ids.len(), 1); assert_eq!(node_ids[0], NodeId(7)); } @@ -114,7 +114,7 @@ fn test_deps_tuple_multiple_handles() { }; // Test 2-tuple - let node_ids = (&handle1, &handle2).to_node_ids(); + let node_ids = (handle1, handle2).to_node_ids(); assert_eq!(node_ids.len(), 2); assert_eq!(node_ids[0], NodeId(1)); assert_eq!(node_ids[1], NodeId(2)); @@ -124,7 +124,7 @@ fn test_deps_tuple_multiple_handles() { id: NodeId(3), _phantom: std::marker::PhantomData, }; - let node_ids = (&handle1, &handle2, &handle3).to_node_ids(); + let node_ids = (handle1, handle2, handle3).to_node_ids(); assert_eq!(node_ids.len(), 3); assert_eq!(node_ids[0], NodeId(1)); assert_eq!(node_ids[1], NodeId(2)); @@ -162,7 +162,7 @@ fn test_deps_tuple_large_tuples() { } // Test 4-tuple - let node_ids = (&handles[0], &handles[1], &handles[2], &handles[3]).to_node_ids(); + let node_ids = (handles[0], handles[1], handles[2], handles[3]).to_node_ids(); assert_eq!(node_ids.len(), 4); for (i, node_id) in node_ids.iter().enumerate().take(4) { assert_eq!(*node_id, NodeId(i as u32)); @@ -170,14 +170,8 @@ fn test_deps_tuple_large_tuples() { // Test 8-tuple let node_ids = ( - &handles[0], - &handles[1], - &handles[2], - &handles[3], - &handles[4], - &handles[5], - &handles[6], - &handles[7], + handles[0], handles[1], handles[2], handles[3], handles[4], handles[5], handles[6], + handles[7], ) .to_node_ids(); assert_eq!(node_ids.len(), 8); @@ -185,19 +179,3 @@ fn test_deps_tuple_large_tuples() { assert_eq!(*node_id, NodeId(i as u32)); } } - -#[test] -fn test_deps_handle_ref_explicit() { - // Test explicit &TaskHandle DepsTuple impl (line 27-28 in deps.rs) - let handle: TaskHandle = TaskHandle { - id: NodeId(77), - _phantom: std::marker::PhantomData, - }; - - // Create a reference and explicitly call to_node_ids - let handle_ref = &handle; - let node_ids = DepsTuple::<(i32,)>::to_node_ids(handle_ref); - - assert_eq!(node_ids.len(), 1); - assert_eq!(node_ids[0], NodeId(77)); -} diff --git a/src/lib.rs b/src/lib.rs index d7b9a03..da26723 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -320,8 +320,8 @@ //! let mut dag = DagRunner::new(); //! //! let base = dag.add_task(Value(10)).into(); -//! let plus1 = dag.add_task(Add(1)).depends_on(&base); -//! let times2 = dag.add_task(Scale(2)).depends_on(&base); +//! let plus1 = dag.add_task(Add(1)).depends_on(base); +//! let times2 = dag.add_task(Scale(2)).depends_on(base); //! //!let mut output = dag.run(|fut| async move { tokio::spawn(fut).await.unwrap() }).await.unwrap(); //! @@ -656,9 +656,9 @@ //! let data = dag.add_task(FetchData).into(); //! //! // All three tasks get efficient Arc-wrapped sharing automatically -//! let task1 = dag.add_task(ProcessData).depends_on(&data); -//! let task2 = dag.add_task(ProcessData).depends_on(&data); -//! let task3 = dag.add_task(ProcessData).depends_on(&data); +//! let task1 = dag.add_task(ProcessData).depends_on(data); +//! let task2 = dag.add_task(ProcessData).depends_on(data); +//! let task3 = dag.add_task(ProcessData).depends_on(data); //! //!let mut output = dag.run(|fut| async move { tokio::spawn(fut).await.unwrap() }).await.unwrap(); //! # }; @@ -784,4 +784,5 @@ pub use runner::DagRunner; pub use task::{Task, TaskInput}; // Re-export the procedural macro +#[cfg(feature = "derive")] pub use dagx_macros::task; diff --git a/src/output.rs b/src/output.rs index 309ad2f..1614b88 100644 --- a/src/output.rs +++ b/src/output.rs @@ -51,10 +51,7 @@ impl DagOutput { /// assert_eq!(output.get(task).unwrap(), 42); /// # }; /// ``` - pub fn get(&mut self, handle: H) -> DagResult - where - H: Into>, - { + pub fn get(&mut self, handle: TaskHandle) -> DagResult { let handle: TaskHandle = handle.into(); let arc_output = self diff --git a/src/runner.rs b/src/runner.rs index 9d9b019..26f4ec1 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -460,13 +460,13 @@ impl DagRunner { } } } - } - // Return first error if any - if let Some(err) = first_error { - #[cfg(feature = "tracing")] - error!(?err, "DAG execution failed"); - return Err(err); + // Return first error if any + if let Some(err) = first_error { + #[cfg(feature = "tracing")] + error!(?err, "DAG execution failed"); + return Err(err); + } } #[cfg(feature = "tracing")] diff --git a/src/task.rs b/src/task.rs index ff42e47..57e2909 100644 --- a/src/task.rs +++ b/src/task.rs @@ -140,14 +140,5 @@ impl_task_input!(A, B, C, D, E, F); impl_task_input!(A, B, C, D, E, F, G); impl_task_input!(A, B, C, D, E, F, G, H); -impl TaskInput<'static, ()> { - pub fn empty() -> Self { - Self { - inputs: [].iter(), - phantom: PhantomData, - } - } -} - #[cfg(test)] mod tests; diff --git a/src/task/tests.rs b/src/task/tests.rs index 8828fd8..bdd0d1c 100644 --- a/src/task/tests.rs +++ b/src/task/tests.rs @@ -32,9 +32,3 @@ async fn test_custom_task_implementation() { // Can't call run again since task was consumed // This demonstrates the ownership model } - -#[test] -fn test_empty_task_input() { - let empty = TaskInput::empty(); - assert_eq!(empty.inputs.len(), 0); -} diff --git a/tests/boundaries/deep_chains.rs b/tests/boundaries/deep_chains.rs index c38a008..8a70432 100644 --- a/tests/boundaries/deep_chains.rs +++ b/tests/boundaries/deep_chains.rs @@ -41,14 +41,14 @@ async fn test_multiple_parallel_deep_chains() -> DagResult<()> { }, )) .depends_on(( - &chain_ends[0], - &chain_ends[1], - &chain_ends[2], - &chain_ends[3], - &chain_ends[4], - &chain_ends[5], - &chain_ends[6], - &chain_ends[7], + chain_ends[0], + chain_ends[1], + chain_ends[2], + chain_ends[3], + chain_ends[4], + chain_ends[5], + chain_ends[6], + chain_ends[7], )); let mut output = dag @@ -120,7 +120,7 @@ async fn test_deep_binary_tree() -> DagResult<()> { dag.add_task(task_fn::<(i32, i32), _, _>(move |(l, r): (&i32, &i32)| { l + r })) - .depends_on((&left, &right)) + .depends_on((left, right)) } } @@ -152,7 +152,7 @@ async fn test_fibonacci_chain() -> DagResult<()> { for _ in 2..50 { let next = dag .add_task(task_fn::<(i64, i64), _, _>(|(a, b): (&i64, &i64)| a + b)) - .depends_on((&prev2, &prev1)); + .depends_on((prev2, prev1)); prev2 = prev1; prev1 = next; @@ -196,7 +196,7 @@ async fn test_zigzag_dependencies() -> DagResult<()> { // Final task depends on both chains let final_task = dag .add_task(task_fn::<(i32, i32), _, _>(|(a, b): (&i32, &i32)| a + b)) - .depends_on((&chain_a, &chain_b)); + .depends_on((chain_a, chain_b)); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/tests/cycle_prevention.rs b/tests/cycle_prevention.rs index 1c6e6ff..a5c2ed6 100644 --- a/tests/cycle_prevention.rs +++ b/tests/cycle_prevention.rs @@ -267,7 +267,7 @@ async fn test_type_safety_prevents_invalid_graphs() { let t2 = dag.add_task(Transform).depends_on(s2); // Aggregate depends on transforms - let result = dag.add_task(Aggregate).depends_on((&t1, &t2)); + let result = dag.add_task(Aggregate).depends_on((t1, t2)); // Execute and verify let mut output = dag diff --git a/tests/dependencies/tuples.rs b/tests/dependencies/tuples.rs index 51b6385..dbdd8f8 100644 --- a/tests/dependencies/tuples.rs +++ b/tests/dependencies/tuples.rs @@ -54,7 +54,7 @@ async fn test_four_dependencies() -> DagResult<()> { .add_task(task_fn::<(i32, i32, i32, i32), _, _>( |(a, b, c, d): (&i32, &i32, &i32, &i32)| a + b + c + d, )) - .depends_on((&deps[0], &deps[1], &deps[2], &deps[3])); + .depends_on((deps[0], deps[1], deps[2], deps[3])); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) @@ -76,7 +76,7 @@ async fn test_five_dependencies() -> DagResult<()> { .add_task(task_fn::<(i32, i32, i32, i32, i32), _, _>( |(a, b, c, d, e): (&i32, &i32, &i32, &i32, &i32)| a + b + c + d + e, )) - .depends_on((&deps[0], &deps[1], &deps[2], &deps[3], &deps[4])); + .depends_on((deps[0], deps[1], deps[2], deps[3], deps[4])); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) @@ -98,7 +98,7 @@ async fn test_six_dependencies() -> DagResult<()> { .add_task(task_fn::<(i32, i32, i32, i32, i32, i32), _, _>( |(a, b, c, d, e, f): (&i32, &i32, &i32, &i32, &i32, &i32)| a + b + c + d + e + f, )) - .depends_on((&deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5])); + .depends_on((deps[0], deps[1], deps[2], deps[3], deps[4], deps[5])); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) @@ -123,7 +123,7 @@ async fn test_seven_dependencies() -> DagResult<()> { }, )) .depends_on(( - &deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5], &deps[6], + deps[0], deps[1], deps[2], deps[3], deps[4], deps[5], deps[6], )); let mut output = dag @@ -149,7 +149,7 @@ async fn test_eight_dependencies() -> DagResult<()> { }, )) .depends_on(( - &deps[0], &deps[1], &deps[2], &deps[3], &deps[4], &deps[5], &deps[6], &deps[7], + deps[0], deps[1], deps[2], deps[3], deps[4], deps[5], deps[6], deps[7], )); let mut output = dag diff --git a/tests/errors/propagation.rs b/tests/errors/propagation.rs index abd0459..d4d7461 100644 --- a/tests/errors/propagation.rs +++ b/tests/errors/propagation.rs @@ -53,7 +53,7 @@ async fn test_diamond_error_propagation() { .depends_on(source); dag.add_task(task_fn::<(i32, i32), _, _>(|(l, r): (&i32, &i32)| l + r)) - .depends_on((&left, &right)); + .depends_on((left, right)); assert!(matches!( dag.run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/tests/execution/mod.rs b/tests/execution/mod.rs index 88bbb12..4e3e11c 100644 --- a/tests/execution/mod.rs +++ b/tests/execution/mod.rs @@ -54,7 +54,7 @@ async fn test_diamond_dependency() { .depends_on(a); let d = dag .add_task(task_fn::<(i32, i32), _, _>(|(x, y): (&i32, &i32)| x + y)) - .depends_on((&b, &c)); + .depends_on((b, c)); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/tests/interleaving/mod.rs b/tests/interleaving/mod.rs index acd84ef..63177f7 100644 --- a/tests/interleaving/mod.rs +++ b/tests/interleaving/mod.rs @@ -255,7 +255,7 @@ async fn test_layered_interleaving() -> DagResult<()> { dag.add_task(Layer23Task { active: layer_active.clone(), }) - .depends_on((&layer1[idx], &layer1[idx + 1])) + .depends_on((layer1[idx], layer1[idx + 1])) }) .collect(); @@ -264,7 +264,7 @@ async fn test_layered_interleaving() -> DagResult<()> { .add_task(Layer23Task { active: layer_active.clone(), }) - .depends_on((&layer2[0], &layer2[1])); + .depends_on((layer2[0], layer2[1])); let mut output = dag .run(|fut| async move { tokio::spawn(fut).await.unwrap() }) diff --git a/tests/parallelism/timing.rs b/tests/parallelism/timing.rs index 9ecc4d7..1e0e978 100644 --- a/tests/parallelism/timing.rs +++ b/tests/parallelism/timing.rs @@ -140,7 +140,7 @@ async fn test_layers_execute_in_parallel() -> DagResult<()> { a + b + c }, )) - .depends_on((&layer1[0], &layer1[1], &layer1[2])) + .depends_on((layer1[0], layer1[1], layer1[2])) }; let mut output = dag