Here's a wild syntax that doesn't seem possible, but with fn_traits, is!
fn main() {
rm();
rm.recursive();
rm.recursive.dir();
rm.recursive.dir.verbose();
}
The above could be generated using a simple proc macro:
#[i_am_the_proc_macro]
struct rm {
recursive: bool,
dir: bool,
verbose: bool
}
Once you have rm.recursive, you can only access the dir and verbose flags on it. You can use any order! rm.recursive.dir(), rm.dir.recursive.verbose()...
Where is this useful? I don't know.. maybe a fancy library for ergonomically writing scripts in Rust, that implements this interface for common utilities like ls and rm.
But it will destroy your compile times! Compilation time complexity, with n being the number of fields in your struct, is O(n!)...
This is how it works (Playground):
const rm: rm_base = rm_base {
recursive: rm_r {
dir: rm_rd { verbose: rm_rdv {} },
verbose: rm_rv { dir: rm_rvd {} },
},
dir: rm_d {
recursive: rm_dr { verbose: rm_drv {} },
verbose: rm_dv {
recursive: rm_dvr {},
},
},
verbose: rm_v {
recursive: rm_vr { dir: rm_vrd {} },
dir: rm_vd {
recursive: rm_vdr {},
},
},
};
Each one of those sub-structs implements the Fn trait
The implementation of the methods is the following:
#![feature(fn_traits)]
#![feature(unboxed_closures)]
macro_rules! node {
($name:ident, $r:expr, $d:expr, $v:expr; $($fname:ident: $ftype:ident => ($nr:expr, $nd:expr, $nv:expr)),*) => {
struct $name { $(pub $fname: $ftype),* }
impl $name { $(pub fn $fname(self) { })* }
impl FnOnce<()> for $name { type Output = (); extern "rust-call" fn call_once(self, a: ()) { } }
};
}
node!(rm_base, false, false, false; recursive: rm_r => (true, false, false), dir: rm_d => (false, true, false), verbose: rm_v => (false, false, true));
node!(rm_r, true, false, false; dir: rm_rd => (true, true, false), verbose: rm_rv => (true, false, true));
node!(rm_d, false, true, false; recursive: rm_dr => (true, true, false), verbose: rm_dv => (false, true, true));
node!(rm_v, false, false, true; recursive: rm_vr => (true, false, true), dir: rm_vd => (false, true, true));
node!(rm_rd, true, true, false; verbose: rm_rdv => (true, true, true));
node!(rm_rv, true, false, true; dir: rm_rvd => (true, true, true));
node!(rm_dr, true, true, false; verbose: rm_drv => (true, true, true));
node!(rm_dv, false, true, true; recursive: rm_dvr => (true, true, true));
node!(rm_vr, true, false, true; dir: rm_vrd => (true, true, true));
node!(rm_vd, false, true, true; recursive: rm_vdr => (true, true, true));
node!(rm_rdv, true, true, true;);
node!(rm_rvd, true, true, true;);
node!(rm_drv, true, true, true;);
node!(rm_dvr, true, true, true;);
node!(rm_vrd, true, true, true;);
node!(rm_vdr, true, true, true;);