fn breakable_to_preconditions(cfg: &Cfg, breaks_from: Index, breaks_to: Index) -> Dnf {
        let node = &cfg[breaks_from];
        // For most nodes, `BreakableTo` is inductive on its continuation.
        match &node.expr {
            // Trivially, `Send`, `Recv`, and `Type` will only break to a loop if their continuation
            // does... as obviously they do not break. Though its behavior is undefined, we assume
            // `Error` also behaves this way.
            Ir::Send(_) | Ir::Recv(_) | Ir::Type(_) | Ir::Error => match node.next {
                Some(cont) => Dnf::only_if(vec![Constraint::BreakableTo {
                    breaks_from: cont,
                    breaks_to,
                }]),
                None => Dnf::trivially_false(),
            },
            // `Call` and `Split` may break from within, but that doesn't actually count as them
            // being breakable to a loop. Instead, similarly to `Send`, `Recv`, and `Type`, they are
            // `BreakableTo` only if their continuation is, but we must also know whether they are
            // passable (so that we can know if control flow can reach that break if it is present.)
            Ir::Call(_) | Ir::Split { .. } => {
                let mut conj = vec![Constraint::Passable(breaks_from)];
                conj.extend(node.next.map(|cont| Constraint::BreakableTo {
                    breaks_from: cont,
                    breaks_to,
                }));
                Dnf::only_if(conj)
            }
            // `Choose` and `Offer` break only if any arm breaks.
            Ir::Choose(choices) | Ir::Offer(choices) => Dnf(choices
                .iter()
                .filter_map(Option::as_ref)
                .chain(node.next.as_ref())
                .map(|&c| {
                    vec![Constraint::BreakableTo {
                        breaks_from: c,
                        breaks_to,
                    }]
                })
                .collect()),
            // A loop only breaks to another loop in one of two cases: 1.) it contains a break
            // targeting the loop in question. 2.) it is passable, and once it is passed, its
            // continuation may break to the target.
            Ir::Loop(body) => {
                // Option 1.: the loop's body is `BreakableTo` the loop in question.
                let mut disj = vec![vec![Constraint::BreakableTo {
                    breaks_from: body
                        .expect("loop bodies should be nonempty after scope resolution"),
                    breaks_to,
                }]];

                // If there is a continuation, then option 2.: the loop's continuation is
                // `BreakableTo` the loop in question.
                if let Some(cont) = node.next {
                    disj.push(vec![
                        Constraint::Passable(breaks_from),
                        Constraint::BreakableTo {
                            breaks_from: cont,
                            breaks_to,
                        },
                    ]);
                }

                Dnf(disj)
            }
            // If we find a break here to the target loop, we've solved this constraint.
            Ir::Break(of_loop) if *of_loop == breaks_to => Dnf::trivially_true(),
            // Any other breaks can be ignored. `Continue` nodes may also be ignored, as they simply
            // repeat nodes we've already seen.
            Ir::Break(_) | Ir::Continue(_) => Dnf::trivially_false(),
        }
    }
/// Compute the preconditions for a `BreakableTo` constraint.
Compute the preconditions for a `BreakableTo` constraint.
Compute the preconditions for a ` BreakableTo ` constraint .
fn breakable_to_preconditions(cfg: &Cfg, breaks_from: Index, breaks_to: Index) -> Dnf {
        let node = &cfg[breaks_from];
        // For most nodes, `BreakableTo` is inductive on its continuation.
        match &node.expr {
            // Trivially, `Send`, `Recv`, and `Type` will only break to a loop if their continuation
            // does... as obviously they do not break. Though its behavior is undefined, we assume
            // `Error` also behaves this way.
            Ir::Send(_) | Ir::Recv(_) | Ir::Type(_) | Ir::Error => match node.next {
                Some(cont) => Dnf::only_if(vec![Constraint::BreakableTo {
                    breaks_from: cont,
                    breaks_to,
                }]),
                None => Dnf::trivially_false(),
            },
            // `Call` and `Split` may break from within, but that doesn't actually count as them
            // being breakable to a loop. Instead, similarly to `Send`, `Recv`, and `Type`, they are
            // `BreakableTo` only if their continuation is, but we must also know whether they are
            // passable (so that we can know if control flow can reach that break if it is present.)
            Ir::Call(_) | Ir::Split { .. } => {
                let mut conj = vec![Constraint::Passable(breaks_from)];
                conj.extend(node.next.map(|cont| Constraint::BreakableTo {
                    breaks_from: cont,
                    breaks_to,
                }));
                Dnf::only_if(conj)
            }
            // `Choose` and `Offer` break only if any arm breaks.
            Ir::Choose(choices) | Ir::Offer(choices) => Dnf(choices
                .iter()
                .filter_map(Option::as_ref)
                .chain(node.next.as_ref())
                .map(|&c| {
                    vec![Constraint::BreakableTo {
                        breaks_from: c,
                        breaks_to,
                    }]
                })
                .collect()),
            // A loop only breaks to another loop in one of two cases: 1.) it contains a break
            // targeting the loop in question. 2.) it is passable, and once it is passed, its
            // continuation may break to the target.
            Ir::Loop(body) => {
                // Option 1.: the loop's body is `BreakableTo` the loop in question.
                let mut disj = vec![vec![Constraint::BreakableTo {
                    breaks_from: body
                        .expect("loop bodies should be nonempty after scope resolution"),
                    breaks_to,
                }]];
                // If there is a continuation, then option 2.: the loop's continuation is
                // `BreakableTo` the loop in question.
                if let Some(cont) = node.next {
                    disj.push(vec![
                        Constraint::Passable(breaks_from),
                        Constraint::BreakableTo {
                            breaks_from: cont,
                            breaks_to,
                        },
                    ]);
                }
                Dnf(disj)
            }
            // If we find a break here to the target loop, we've solved this constraint.
            Ir::Break(of_loop) if *of_loop == breaks_to => Dnf::trivially_true(),
            // Any other breaks can be ignored. `Continue` nodes may also be ignored, as they simply
            // repeat nodes we've already seen.
            Ir::Break(_) | Ir::Continue(_) => Dnf::trivially_false(),
        }
    }
fn breakable_to_preconditions ( cfg : & Cfg , breaks_from : Index , breaks_to : Index ) -> Dnf { let node = & cfg [ breaks_from ] ; // For most nodes, `BreakableTo` is inductive on its continuation. match & node . expr { // Trivially, `Send`, `Recv`, and `Type` will only break to a loop if their continuation // does... as obviously they do not break. Though its behavior is undefined, we assume // `Error` also behaves this way. Ir :: Send ( _ ) | Ir :: Recv ( _ ) | Ir :: Type ( _ ) | Ir :: Error => match node . next { Some ( cont ) => Dnf :: only_if ( vec ! [ Constraint BreakableTo { breaks_from cont breaks_to } ] ) , None => Dnf :: trivially_false ( ) , } , // `Call` and `Split` may break from within, but that doesn't actually count as them // being breakable to a loop. Instead, similarly to `Send`, `Recv`, and `Type`, they are // `BreakableTo` only if their continuation is, but we must also know whether they are // passable (so that we can know if control flow can reach that break if it is present.) Ir :: Call ( _ ) | Ir :: Split { .. } => { let mut conj = vec ! [ Constraint Passable ( breaks_from ) ] ; conj . extend ( node . next . map ( | cont | Constraint :: BreakableTo { breaks_from : cont , breaks_to , } ) ) ; Dnf :: only_if ( conj ) } // `Choose` and `Offer` break only if any arm breaks. Ir :: Choose ( choices ) | Ir :: Offer ( choices ) => Dnf ( choices . iter ( ) . filter_map ( Option :: as_ref ) . chain ( node . next . as_ref ( ) ) . map ( | & c | { vec ! [ Constraint BreakableTo { breaks_from c breaks_to } ] } ) . collect ( ) ) , // A loop only breaks to another loop in one of two cases: 1.) it contains a break // targeting the loop in question. 2.) it is passable, and once it is passed, its // continuation may break to the target. Ir :: Loop ( body ) => { // Option 1.: the loop's body is `BreakableTo` the loop in question. let mut disj = vec ! [ vec [ Constraint BreakableTo { breaks_from body expect ( " " ) breaks_to } ] ] ; // If there is a continuation, then option 2.: the loop's continuation is // `BreakableTo` the loop in question. if let Some ( cont ) = node . next { disj . push ( vec ! [ Constraint Passable ( breaks_from ) Constraint BreakableTo { breaks_from cont breaks_to } ] ) ; } Dnf ( disj ) } // If we find a break here to the target loop, we've solved this constraint. Ir :: Break ( of_loop ) if * of_loop == breaks_to => Dnf :: trivially_true ( ) , // Any other breaks can be ignored. `Continue` nodes may also be ignored, as they simply // repeat nodes we've already seen. Ir :: Break ( _ ) | Ir :: Continue ( _ ) => Dnf :: trivially_false ( ) , } }
Compute the preconditions for a `BreakableTo` constraint.
Compute the preconditions for a ` BreakableTo ` constraint .
cfg
&Cfg
breaks_from
Index
breaks_to
Index