pub fn distribute_over_target_joins<F, G>(
        &mut self,
        target_path: Rc<Path>,
        join_prefix: Rc<AbstractValue>,
        strong_update: &F,
        weak_update: &G,
    ) where
        F: Fn(&mut Self, Rc<Path>),
        G: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>),
    {
        trace!(
            "target_path {:?} join_prefix {:?}",
            target_path,
            join_prefix
        );
        if let Some((join_condition, true_path, false_path)) =
            self.current_environment.try_to_split(&target_path)
        {
            if join_prefix.as_bool_if_known().unwrap_or(false) {
                //todo: if the strong update is a move, the weak updates below do not see the values
                //rooted at the source path because they have moved. On the other hand, if the strong
                //update is done after the weak updates, then the strong update can't help to refine
                //the weak values.
                // For now we work around this problem by always copying.
                strong_update(self, target_path);
            }
            // The value path contains an abstract value that was constructed with a join.
            // In this case, we split the path into two and perform weak updates on them.
            // Rather than do it here, we recurse until there are no more joins.
            self.distribute_over_target_joins(
                true_path,
                join_prefix.and(join_condition.clone()),
                strong_update,
                weak_update,
            );
            self.distribute_over_target_joins(
                false_path,
                join_prefix.and(join_condition.logical_not()),
                strong_update,
                weak_update,
            );
        } else {
            // Get here for a path with no joins.
            if join_prefix.as_bool_if_known().unwrap_or(false) {
                // This is the root call, so just do a strong update and return to the caller.
                strong_update(self, target_path)
            } else {
                // This is a recursive call, do the weak update and return to the caller.
                // The caller will do the strong update if it is the root call.
                weak_update(self, target_path, join_prefix);
            }
        }
    }
/// If the target path if of the form if c { p1 } else { p2 } then it is an alias for either
/// p1 or p2, so updating the target path must weakly update p1 and p2 as well.
If the target path if of the form if c { p1 } else { p2 } then it is an alias for either
p1 or p2, so updating the target path must weakly update p1 and p2 as well.
If the target path if of the form if c { p1 } else { p2 } then it is an alias for either p1 or p2 so updating the target path must weakly update p1 and p2 as well .
pub fn distribute_over_target_joins<F, G>(
        &mut self,
        target_path: Rc<Path>,
        join_prefix: Rc<AbstractValue>,
        strong_update: &F,
        weak_update: &G,
    ) where
        F: Fn(&mut Self, Rc<Path>),
        G: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>),
    {
        trace!(
            "target_path {:?} join_prefix {:?}",
            target_path,
            join_prefix
        );
        if let Some((join_condition, true_path, false_path)) =
            self.current_environment.try_to_split(&target_path)
        {
            if join_prefix.as_bool_if_known().unwrap_or(false) {
                //todo: if the strong update is a move, the weak updates below do not see the values
                //rooted at the source path because they have moved. On the other hand, if the strong
                //update is done after the weak updates, then the strong update can't help to refine
                //the weak values.
                // For now we work around this problem by always copying.
                strong_update(self, target_path);
            }
            // The value path contains an abstract value that was constructed with a join.
            // In this case, we split the path into two and perform weak updates on them.
            // Rather than do it here, we recurse until there are no more joins.
            self.distribute_over_target_joins(
                true_path,
                join_prefix.and(join_condition.clone()),
                strong_update,
                weak_update,
            );
            self.distribute_over_target_joins(
                false_path,
                join_prefix.and(join_condition.logical_not()),
                strong_update,
                weak_update,
            );
        } else {
            // Get here for a path with no joins.
            if join_prefix.as_bool_if_known().unwrap_or(false) {
                // This is the root call, so just do a strong update and return to the caller.
                strong_update(self, target_path)
            } else {
                // This is a recursive call, do the weak update and return to the caller.
                // The caller will do the strong update if it is the root call.
                weak_update(self, target_path, join_prefix);
            }
        }
    }
pub fn distribute_over_target_joins < F , G > ( & mut self , target_path : Rc < Path > , join_prefix : Rc < AbstractValue > , strong_update : & F , weak_update : & G , ) where F : Fn ( & mut Self , Rc < Path > ) , G : Fn ( & mut Self , Rc < Path > , Rc < AbstractValue > ) , { trace ! ( " " target_path join_prefix ) ; if let Some ( ( join_condition , true_path , false_path ) ) = self . current_environment . try_to_split ( & target_path ) { if join_prefix . as_bool_if_known ( ) . unwrap_or ( false ) { //todo: if the strong update is a move, the weak updates below do not see the values //rooted at the source path because they have moved. On the other hand, if the strong //update is done after the weak updates, then the strong update can't help to refine //the weak values. // For now we work around this problem by always copying. strong_update ( self , target_path ) ; } // The value path contains an abstract value that was constructed with a join. // In this case, we split the path into two and perform weak updates on them. // Rather than do it here, we recurse until there are no more joins. self . distribute_over_target_joins ( true_path , join_prefix . and ( join_condition . clone ( ) ) , strong_update , weak_update , ) ; self . distribute_over_target_joins ( false_path , join_prefix . and ( join_condition . logical_not ( ) ) , strong_update , weak_update , ) ; } else { // Get here for a path with no joins. if join_prefix . as_bool_if_known ( ) . unwrap_or ( false ) { // This is the root call, so just do a strong update and return to the caller. strong_update ( self , target_path ) } else { // This is a recursive call, do the weak update and return to the caller. // The caller will do the strong update if it is the root call. weak_update ( self , target_path , join_prefix ) ; } } }
If the target path if of the form if c { p1 } else { p2 } then it is an alias for either
p1 or p2, so updating the target path must weakly update p1 and p2 as well.
If the target path if of the form if c { p1 } else { p2 } then it is an alias for either p1 or p2 so updating the target path must weakly update p1 and p2 as well .
&mut self
target_path
Rc<Path>
join_prefix
Rc<AbstractValue>
strong_update
&F
weak_update
&G
&mut self
target_path
Rc<Path>
join_prefix
Rc<AbstractValue>
strong_update
&F
weak_update
&G