From c14e49007c8772673f6ac75bd5c324390b1c33fa Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Sun, 12 Jul 2026 22:55:28 +0530 Subject: [PATCH 1/8] Add proof of concept for overload! macro Signed-off-by: Ajay Singh --- splat-overload/src/lib.rs | 87 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/splat-overload/src/lib.rs b/splat-overload/src/lib.rs index 793dee2..a432ea6 100644 --- a/splat-overload/src/lib.rs +++ b/splat-overload/src/lib.rs @@ -1 +1,86 @@ -//! Delete this comment and add the actual code here +use proc_macro::TokenStream; +use quote::quote; +use syn::{ + parse::{Parse, ParseStream}, + parse_macro_input, + ItemFn, + FnArg, + Pat, + Result, +}; + +struct OverloadInput { + functions: Vec, +} + +impl Parse for OverloadInput { + fn parse(input: ParseStream) -> Result { + let mut functions = Vec::new(); + while !input.is_empty() { + functions.push(input.parse::()?); + } + Ok(OverloadInput { functions }) + } +} + +#[proc_macro] +pub fn overload(input: TokenStream) -> TokenStream { + let OverloadInput { functions } = parse_macro_input!(input as OverloadInput); + + + let fn_name = &functions[0].sig.ident; + + + let trait_name = quote::format_ident!( + "{}Args", + fn_name.to_string() + .chars() + .enumerate() + .map(|(i, c)| if i == 0 { c.to_uppercase().next().unwrap() } else { c }) + .collect::() + ); + + + let mut impls = Vec::new(); + for func in &functions { + for arg in &func.sig.inputs { + if let FnArg::Typed(pat_type) = arg { + let ty = &pat_type.ty; + let block = &func.block; + + + let arg_name = if let Pat::Ident(pat_ident) = &*pat_type.pat { + let ident = &pat_ident.ident; + quote! { #ident } + } else { + quote! { _arg } + }; + + impls.push(quote! { + impl #trait_name for (#ty,) { + fn call(self) { + let #arg_name = self.0; + #block + } + } + }); + } + } + } + + + let generated = quote! { + trait #trait_name: std::marker::Tuple { + fn call(self); + } + + #(#impls)* + + fn #fn_name(#[splat] args: T) { + args.call() + } + }; + + generated.into() +} + From b9f2089200cba59a4cfcfc5db72b1bb2d07cd0c0 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 14 Jul 2026 16:03:30 +0530 Subject: [PATCH 2/8] Fix Cargo.toml dependencies for splat-overload Signed-off-by: Ajay Singh --- Cargo.lock | 39 +++++++++++++++++++++++++++++++++++---- Cargo.toml | 6 ++++-- splat-overload/Cargo.toml | 9 ++++++--- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba697e0..5c79c02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,14 +3,45 @@ version = 4 [[package]] -name = "example" -version = "1.1.0" +name = "proc-macro2" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a23e249717cd6d24a8f3fcd9639403948df1227fe303a106396597a68277e" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] [[package]] name = "splat-overload" version = "0.0.0" dependencies = [ - "example", + "proc-macro2", + "quote", + "syn", ] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" diff --git a/Cargo.toml b/Cargo.toml index b9804b5..0fa6d10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,5 +26,7 @@ repository = "https://github.com/rustfoundation/overloading-macros" rust-version = "1.99" [workspace.dependencies] -# Delete this package and replace it with the actual dependencies -example = "1.1.0" \ No newline at end of file + +syn = { version = "2.0", features = ["full"] } +quote = "1.0" +proc-macro2 = "1.0" \ No newline at end of file diff --git a/splat-overload/Cargo.toml b/splat-overload/Cargo.toml index 4dfc053..2ebc909 100644 --- a/splat-overload/Cargo.toml +++ b/splat-overload/Cargo.toml @@ -1,4 +1,3 @@ -# Modify the workspace Cargo.toml instead of this file (if possible) [package] name = "splat-overload" version.workspace = true @@ -11,6 +10,10 @@ readme.workspace = true repository.workspace = true rust-version.workspace = true +[lib] +proc-macro = true + [dependencies] -# Delete this package and replace it with the actual dependencies -example.workspace = true +syn.workspace = true +quote.workspace = true +proc-macro2.workspace = true From 904c1c448e1d20c2253254e661256b873e1bdd7d Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 14 Jul 2026 21:35:37 +0530 Subject: [PATCH 3/8] Add support for handling multiple function arguments Signed-off-by: Ajay Singh --- splat-overload/src/lib.rs | 49 +++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/splat-overload/src/lib.rs b/splat-overload/src/lib.rs index a432ea6..2e955ab 100644 --- a/splat-overload/src/lib.rs +++ b/splat-overload/src/lib.rs @@ -1,12 +1,9 @@ use proc_macro::TokenStream; use quote::quote; use syn::{ + FnArg, ItemFn, Pat, Result, parse::{Parse, ParseStream}, parse_macro_input, - ItemFn, - FnArg, - Pat, - Result, }; struct OverloadInput { @@ -27,48 +24,55 @@ impl Parse for OverloadInput { pub fn overload(input: TokenStream) -> TokenStream { let OverloadInput { functions } = parse_macro_input!(input as OverloadInput); - let fn_name = &functions[0].sig.ident; - let trait_name = quote::format_ident!( "{}Args", - fn_name.to_string() + fn_name + .to_string() .chars() .enumerate() - .map(|(i, c)| if i == 0 { c.to_uppercase().next().unwrap() } else { c }) + .map(|(i, c)| if i == 0 { + c.to_uppercase().next().unwrap() + } else { + c + }) .collect::() ); - let mut impls = Vec::new(); for func in &functions { - for arg in &func.sig.inputs { + // Collect All arguments and names + let mut arg_types = Vec::new(); + let mut arg_names = Vec::new(); + let mut arg_indices = Vec::new(); + let block = &func.block; + for (i, arg) in func.sig.inputs.iter().enumerate() { if let FnArg::Typed(pat_type) = arg { let ty = &pat_type.ty; - let block = &func.block; + arg_types.push(quote! { #ty }); - let arg_name = if let Pat::Ident(pat_ident) = &*pat_type.pat { let ident = &pat_ident.ident; quote! { #ident } } else { quote! { _arg } }; + arg_names.push(arg_name); - impls.push(quote! { - impl #trait_name for (#ty,) { - fn call(self) { - let #arg_name = self.0; - #block - } - } - }); + let index = syn::Index::from(i); + arg_indices.push(quote! { self.#index }); } } + impls.push(quote! { + impl #trait_name for (#(#arg_types),*,) { + fn call(self) { + #(let #arg_names = #arg_indices;)* + #block + } + } + }); } - - let generated = quote! { trait #trait_name: std::marker::Tuple { fn call(self); @@ -83,4 +87,3 @@ pub fn overload(input: TokenStream) -> TokenStream { generated.into() } - From abdc608b7389d4338865260e8264478165aabe96 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Tue, 14 Jul 2026 21:36:26 +0530 Subject: [PATCH 4/8] Fix formatting and add test files Signed-off-by: Ajay Singh --- Cargo.lock | 7 +++++ Cargo.toml | 2 ++ rust-toolchain.toml | 2 ++ splat-overload-test/Cargo.toml | 7 +++++ splat-overload-test/rust-toolchain.toml | 2 ++ splat-overload-test/src/bin/multiple-args.rs | 23 ++++++++++++++++ .../src/bin/multiple-mixed-args.rs | 27 +++++++++++++++++++ 7 files changed, 70 insertions(+) create mode 100644 rust-toolchain.toml create mode 100644 splat-overload-test/Cargo.toml create mode 100644 splat-overload-test/rust-toolchain.toml create mode 100644 splat-overload-test/src/bin/multiple-args.rs create mode 100644 splat-overload-test/src/bin/multiple-mixed-args.rs diff --git a/Cargo.lock b/Cargo.lock index 5c79c02..9254a98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,13 @@ dependencies = [ "syn", ] +[[package]] +name = "splat-overload-test" +version = "0.1.0" +dependencies = [ + "splat-overload", +] + [[package]] name = "syn" version = "2.0.118" diff --git a/Cargo.toml b/Cargo.toml index 0fa6d10..6033ba1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,11 @@ resolver = "3" members = [ "splat-overload", + "splat-overload-test" ] default-members = [ "splat-overload", + "splat-overload-test" ] [workspace.package] diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/splat-overload-test/Cargo.toml b/splat-overload-test/Cargo.toml new file mode 100644 index 0000000..0f37e13 --- /dev/null +++ b/splat-overload-test/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "splat-overload-test" +version = "0.1.0" +edition = "2021" + +[dependencies] +splat-overload = { path = "../splat-overload" } diff --git a/splat-overload-test/rust-toolchain.toml b/splat-overload-test/rust-toolchain.toml new file mode 100644 index 0000000..5d56faf --- /dev/null +++ b/splat-overload-test/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/splat-overload-test/src/bin/multiple-args.rs b/splat-overload-test/src/bin/multiple-args.rs new file mode 100644 index 0000000..aaea75d --- /dev/null +++ b/splat-overload-test/src/bin/multiple-args.rs @@ -0,0 +1,23 @@ +#![feature(splat)] +#![feature(tuple_trait)] +#![allow(incomplete_features)] + +use splat_overload::overload; + +overload! { + fn foo(x: i32, y: f64) { + println!("i32: {}, f64: {}", x, y); + } + fn foo(x: bool, y: i32, z: f64) { + println!("bool: {}, i32: {}, f64: {}", x, y, z); + } + fn foo(a: i32, b: f64, c: bool, d: u8) { + println!("i32: {}, f64: {}, bool: {}, u8: {}", a, b, c, d); + } +} + +fn main() { + foo(42, 3.14); + foo(true, 42, 3.14); + foo(42, 3.14, true, 255); +} \ No newline at end of file diff --git a/splat-overload-test/src/bin/multiple-mixed-args.rs b/splat-overload-test/src/bin/multiple-mixed-args.rs new file mode 100644 index 0000000..2e1e79a --- /dev/null +++ b/splat-overload-test/src/bin/multiple-mixed-args.rs @@ -0,0 +1,27 @@ +#![feature(splat)] +#![feature(tuple_trait)] +#![allow(incomplete_features)] + +use splat_overload::overload; + +overload! { + fn calculate(a: i32, b: i32) { + println!("sum: {}", a + b); + } + fn calculate(a: f64, b: f64, c: f64) { + println!("average: {}", (a + b + c) / 3.0); + } + fn calculate(x: i32, y: i32, z: i32, w: i32) { + println!("product: {}", x * y * z * w); + } + fn calculate(a: f64, b: f64, c: f64, d: f64, e: f64) { + println!("max would need std: {} {} {} {} {}", a, b, c, d, e); + } +} + +fn main() { + calculate(10, 20); + calculate(1.0, 2.0, 3.0); + calculate(2, 3, 4, 5); + calculate(1.0, 2.0, 3.0, 4.0, 5.0); +} From 37e340759b2c2ada5281c8829b046422aa4b0298 Mon Sep 17 00:00:00 2001 From: teor Date: Wed, 15 Jul 2026 12:58:40 +1000 Subject: [PATCH 5/8] Ignore clippy approximate constants check --- splat-overload-test/src/bin/multiple-args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/splat-overload-test/src/bin/multiple-args.rs b/splat-overload-test/src/bin/multiple-args.rs index aaea75d..ca54b8d 100644 --- a/splat-overload-test/src/bin/multiple-args.rs +++ b/splat-overload-test/src/bin/multiple-args.rs @@ -1,6 +1,6 @@ #![feature(splat)] #![feature(tuple_trait)] -#![allow(incomplete_features)] +#![allow(incomplete_features, clippy::approx_constant)] use splat_overload::overload; From 7fa68ad05683b4c979bd55ad155a7394b5a54fe6 Mon Sep 17 00:00:00 2001 From: Ajay Singh Date: Thu, 16 Jul 2026 08:57:30 +0530 Subject: [PATCH 6/8] Fix CI errors Signed-off-by: Ajay Singh --- splat-overload-test/src/bin/multiple-args.rs | 14 +++++++------- .../src/bin/multiple-mixed-args.rs | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/splat-overload-test/src/bin/multiple-args.rs b/splat-overload-test/src/bin/multiple-args.rs index ca54b8d..cee9f89 100644 --- a/splat-overload-test/src/bin/multiple-args.rs +++ b/splat-overload-test/src/bin/multiple-args.rs @@ -5,14 +5,14 @@ use splat_overload::overload; overload! { - fn foo(x: i32, y: f64) { - println!("i32: {}, f64: {}", x, y); + fn foo(x: i32, y: f64) { + println!("i32: {}, f64: {}", x, y); } - fn foo(x: bool, y: i32, z: f64) { - println!("bool: {}, i32: {}, f64: {}", x, y, z); + fn foo(x: bool, y: i32, z: f64) { + println!("bool: {}, i32: {}, f64: {}", x, y, z); } - fn foo(a: i32, b: f64, c: bool, d: u8) { - println!("i32: {}, f64: {}, bool: {}, u8: {}", a, b, c, d); + fn foo(a: i32, b: f64, c: bool, d: u8) { + println!("i32: {}, f64: {}, bool: {}, u8: {}", a, b, c, d); } } @@ -20,4 +20,4 @@ fn main() { foo(42, 3.14); foo(true, 42, 3.14); foo(42, 3.14, true, 255); -} \ No newline at end of file +} diff --git a/splat-overload-test/src/bin/multiple-mixed-args.rs b/splat-overload-test/src/bin/multiple-mixed-args.rs index 2e1e79a..0d79f0e 100644 --- a/splat-overload-test/src/bin/multiple-mixed-args.rs +++ b/splat-overload-test/src/bin/multiple-mixed-args.rs @@ -5,17 +5,17 @@ use splat_overload::overload; overload! { - fn calculate(a: i32, b: i32) { - println!("sum: {}", a + b); + fn calculate(a: i32, b: i32) { + println!("sum: {}", a + b); } - fn calculate(a: f64, b: f64, c: f64) { - println!("average: {}", (a + b + c) / 3.0); + fn calculate(a: f64, b: f64, c: f64) { + println!("average: {}", (a + b + c) / 3.0); } - fn calculate(x: i32, y: i32, z: i32, w: i32) { - println!("product: {}", x * y * z * w); + fn calculate(x: i32, y: i32, z: i32, w: i32) { + println!("product: {}", x * y * z * w); } - fn calculate(a: f64, b: f64, c: f64, d: f64, e: f64) { - println!("max would need std: {} {} {} {} {}", a, b, c, d, e); + fn calculate(a: f64, b: f64, c: f64, d: f64, e: f64) { + println!("max would need std: {} {} {} {} {}", a, b, c, d, e); } } From a097ad778abe47016735e31021dc7969aebb1150 Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 17 Jul 2026 07:57:19 +1000 Subject: [PATCH 7/8] Add 3-part dependency versions --- Cargo.toml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6033ba1..421e64d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,11 +24,7 @@ keywords = [ license = "MIT OR APACHE-2.0" readme = "README.md" repository = "https://github.com/rustfoundation/overloading-macros" -# Requires #[splat] which was introduced just before 1.99 branched -rust-version = "1.99" - [workspace.dependencies] - -syn = { version = "2.0", features = ["full"] } -quote = "1.0" -proc-macro2 = "1.0" \ No newline at end of file +syn = { version = "2.0.119", features = ["full"] } +quote = "1.0.46" +proc-macro2 = "1.0.106" \ No newline at end of file From a0d90ce652873672a8f5f3355af3a613aa64174d Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 17 Jul 2026 07:59:09 +1000 Subject: [PATCH 8/8] Replace accidentally deleted rust-version --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 421e64d..32d23ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ keywords = [ license = "MIT OR APACHE-2.0" readme = "README.md" repository = "https://github.com/rustfoundation/overloading-macros" +# Requires #[splat] which was introduced just before 1.99 branched +rust-version = "1.99" [workspace.dependencies] syn = { version = "2.0.119", features = ["full"] } quote = "1.0.46"