fn main() { // Example usage let lamp_topology = LampTopology {}; let k8s_score = K8sScore {}; let docker_topology = DockerTopology{}; // Type-safe execution let maestro = Maestro::new(Box::new(docker_topology)); maestro.execute(&k8s_score); // This will work // This would fail at compile time if we tried: // let dummy_topology = DummyTopology {}; // let maestro = Maestro::new(Box::new(dummy_topology)); // maestro.execute(&k8s_score); // Error: expected LampTopology, found DummyTopology } // Base trait for all topologies trait Topology { // Common topology methods could go here fn topology_type(&self) -> &str; } struct DummyTopology {} impl Topology for DummyTopology { fn topology_type(&self) -> &str { "Dummy" } } struct LampTopology {} impl Topology for LampTopology { fn topology_type(&self) -> &str { "LAMP" } } struct DockerTopology {} impl Topology for DockerTopology { fn topology_type(&self) -> &str { todo!("DockerTopology") } } // The Score trait with an associated type for the required topology trait Score { type RequiredTopology: Topology + ?Sized; fn execute(&self, topology: &Self::RequiredTopology); fn score_type(&self) -> &str; } // A score that requires LampTopology struct K8sScore {} impl Score for K8sScore { type RequiredTopology = DockerTopology; fn execute(&self, topology: &Self::RequiredTopology) { println!("Executing K8sScore on {} topology", topology.topology_type()); // Implementation details... } fn score_type(&self) -> &str { "K8s" } } // A generic maestro that can work with any topology type struct Maestro { topology: Box, } impl Maestro { pub fn new(topology: Box) -> Self { Maestro { topology } } // Execute a score that requires this specific topology type pub fn execute>(&self, score: &S) { println!("Maestro executing {} score", score.score_type()); score.execute(&*self.topology); } }