fn_traits and unboxed_closures combine to make roundabout polymorphic functions!

99 points thehoseisleaking
#![feature(fn_traits)]
#![feature(unboxed_closures)]

#[allow(non_camel_case_types)]
struct add;

impl FnOnce<(usize, usize)> for add {
    type Output = usize;
    
    extern "rust-call" fn call_once(self, (a, b): (usize, usize)) -> usize {
        a + b
    }
}

impl FnOnce<(u32, u32, u32)> for add {
    type Output = usize;
    
    extern "rust-call" fn call_once(self, (a, b, c): (u32, u32, u32)) -> usize {
        (a + b + c) as _
    }
}

impl FnOnce<(&str, &str)> for add {
    type Output = String;
    
    extern "rust-call" fn call_once(self, (a, b): (&str, &str)) -> String {
        let mut res = a.to_owned();
        res += b;
        res
    }
}

fn main() {
    dbg!(add(34, 35));
    dbg!(add(23, 23, 23));
    dbg!(add("hello ", "world!"));
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/playground`
[src/main.rs:34] add(34, 35) = 69
[src/main.rs:35] add(23, 23, 23) = 69
[src/main.rs:36] add("hello ", "world!") = "hello world!"

Is it cursed? Yes! Is it overly verbose? Also yes! But it does work nonetheless to create "functions" that are able to be called using multiple types of data.