Announces a dependence on an analysis `A`. This ensures that `A` will be performed, and before any analysis that invokes this method.
(&mut self, analysis: A)
| 282 | /// This ensures that `A` will be performed, and before any analysis that |
| 283 | /// invokes this method. |
| 284 | pub fn require<A: Analysis>(&mut self, analysis: A) { |
| 285 | // The method recursively descends through required analyses, first |
| 286 | // installing each in `result.analyses` and second in `result.order`. |
| 287 | // The first is an obligation, and serves as an indication that we have |
| 288 | // found a cycle in dependencies. |
| 289 | let type_id = TypeId::of::<Bundle<A>>(); |
| 290 | if !self.result.order.contains(&type_id) { |
| 291 | // If we have not sequenced `type_id` but have a bundle, it means |
| 292 | // we are in the process of fulfilling its requirements: a cycle. |
| 293 | if self.result.analyses.contains_key(&type_id) { |
| 294 | panic!("Cyclic dependency detected: {}", std::any::type_name::<A>()); |
| 295 | } |
| 296 | // Insert the analysis bundle first, so that we can detect cycles. |
| 297 | self.result.analyses.insert( |
| 298 | type_id, |
| 299 | Box::new(Bundle::<A> { |
| 300 | analysis, |
| 301 | results: Vec::new(), |
| 302 | fuel: 100, |
| 303 | allow_optimistic: self.features.enable_letrec_fixpoint_analysis, |
| 304 | }), |
| 305 | ); |
| 306 | A::announce_dependencies(self); |
| 307 | // All dependencies are successfully sequenced; sequence `type_id`. |
| 308 | self.result.order.push(type_id); |
| 309 | } |
| 310 | } |
| 311 | /// Complete the building: perform analyses and return the resulting `Derivation`. |
| 312 | pub fn visit(mut self, expr: &MirRelationExpr) -> Derived { |
| 313 | // A stack of expressions to process (`Ok`) and let bindings to fill (`Err`). |
no test coverage detected