pub fn non_patterned_copy_or_move_elements<F>(
        &mut self,
        target_path: Rc<Path>,
        source_path: Rc<Path>,
        root_rustc_type: Ty<'tcx>,
        move_elements: bool,
        update: F,
    ) where
        F: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>),
    {
        trace!("non_patterned_copy_or_move_elements(target_path {:?}, source_path {:?}, root_rustc_type {:?})", target_path, source_path, root_rustc_type);
        let value = self.lookup_path_and_refine_result(source_path.clone(), root_rustc_type);
        if let Expression::Variable { path, .. } = &value.expression {
            if path.eq(&source_path) {
                // The source value is not known and we need to take additional precautions:
                let source_type = self
                    .type_visitor()
                    .get_path_rustc_type(&source_path, self.current_span);
                if matches!(source_type.kind(), TyKind::Array(t, _) if *t == root_rustc_type) {
                    // During path refinement, the original source path was of the intermediate form *&p.
                    // Mostly, this can just be canonicalized to just p, but if p has an array type
                    // and *&p is not used as a qualifier, then *&p represents the first element of the array
                    // if &p is the refinement of a pointer obtained from the array via array::as_ptr.
                    let zero = Rc::new(0u128.into());
                    let first_element = Path::new_index(path.clone(), zero);
                    self.non_patterned_copy_or_move_elements(
                        target_path,
                        first_element,
                        root_rustc_type,
                        move_elements,
                        update,
                    );
                    return;
                }
            }
        }
        if let Expression::CompileTimeConstant(ConstantDomain::Str(s)) = &value.expression {
            // The value is a string literal. See if the target will treat it as &[u8].
            if let TyKind::Ref(_, ty, _) = root_rustc_type.kind() {
                if let TyKind::Slice(elem_ty) = ty.kind() {
                    if let TyKind::Uint(UintTy::U8) = elem_ty.kind() {
                        self.expand_aliased_string_literals_if_appropriate(
                            &target_path,
                            &value,
                            s,
                            update,
                        );
                        return;
                    }
                }
            }
        }
        let target_type = ExpressionType::from(root_rustc_type.kind());
        let mut no_children = true;
        // If a non primitive parameter is just returned from a function, for example,
        // there will be no entries rooted with target_path in the final environment.
        // This will lead to an incorrect summary of the function, since only the paths
        // in the final environment are used construct the summary. We work around this
        // by creating an entry for the non primitive (unknown) value. The caller will
        // be saddled with removing it. This case corresponds to no_children being true.
        if target_type == ExpressionType::NonPrimitive || target_type == ExpressionType::Function {
            // First look at paths that are rooted in rpath.
            let value_map = self.current_environment.value_map.clone();
            for (path, value) in value_map
                .iter()
                .filter(|(p, _)| p.is_rooted_by(&source_path))
            {
                check_for_early_return!(self);
                if matches!(&value.expression, Expression::HeapBlockLayout { .. })
                    && !target_path.is_rooted_by_non_local_structure()
                {
                    continue;
                }
                let qualified_path = path
                    .replace_root(&source_path, target_path.clone())
                    .canonicalize(&self.current_environment);
                if move_elements {
                    trace!("moving child {:?} to {:?}", value, qualified_path);
                    self.current_environment.value_map =
                        self.current_environment.value_map.remove(path);
                } else {
                    trace!("copying child {:?} to {:?}", value, qualified_path);
                };
                update(self, qualified_path, value.clone());
                no_children = false;
            }
            if let Expression::InitialParameterValue { path, .. }
            | Expression::Variable { path, .. } = &value.expression
            {
                if path.is_rooted_by_parameter() {
                    update(self, target_path.clone(), value.clone());
                    no_children = false;
                }
            }
        }
        if target_type != ExpressionType::NonPrimitive
            || no_children
            || root_rustc_type.is_closure()
        {
            // Just copy/move (rpath, value) itself.
            if move_elements {
                trace!("moving {:?} to {:?}", value, target_path);
                self.current_environment.value_map =
                    self.current_environment.value_map.remove(&source_path);
            } else {
                trace!("copying {:?} to {:?}", value, target_path);
            }
            update(self, target_path, value);
        }
    }
/// Copies/moves all paths rooted in source_path to corresponding paths rooted in target_path.
Copies/moves all paths rooted in source_path to corresponding paths rooted in target_path.
Copies / moves all paths rooted in source_path to corresponding paths rooted in target_path .
pub fn non_patterned_copy_or_move_elements<F>(
        &mut self,
        target_path: Rc<Path>,
        source_path: Rc<Path>,
        root_rustc_type: Ty<'tcx>,
        move_elements: bool,
        update: F,
    ) where
        F: Fn(&mut Self, Rc<Path>, Rc<AbstractValue>),
    {
        trace!("non_patterned_copy_or_move_elements(target_path {:?}, source_path {:?}, root_rustc_type {:?})", target_path, source_path, root_rustc_type);
        let value = self.lookup_path_and_refine_result(source_path.clone(), root_rustc_type);
        if let Expression::Variable { path, .. } = &value.expression {
            if path.eq(&source_path) {
                // The source value is not known and we need to take additional precautions:
                let source_type = self
                    .type_visitor()
                    .get_path_rustc_type(&source_path, self.current_span);
                if matches!(source_type.kind(), TyKind::Array(t, _) if *t == root_rustc_type) {
                    // During path refinement, the original source path was of the intermediate form *&p.
                    // Mostly, this can just be canonicalized to just p, but if p has an array type
                    // and *&p is not used as a qualifier, then *&p represents the first element of the array
                    // if &p is the refinement of a pointer obtained from the array via array::as_ptr.
                    let zero = Rc::new(0u128.into());
                    let first_element = Path::new_index(path.clone(), zero);
                    self.non_patterned_copy_or_move_elements(
                        target_path,
                        first_element,
                        root_rustc_type,
                        move_elements,
                        update,
                    );
                    return;
                }
            }
        }
        if let Expression::CompileTimeConstant(ConstantDomain::Str(s)) = &value.expression {
            // The value is a string literal. See if the target will treat it as &[u8].
            if let TyKind::Ref(_, ty, _) = root_rustc_type.kind() {
                if let TyKind::Slice(elem_ty) = ty.kind() {
                    if let TyKind::Uint(UintTy::U8) = elem_ty.kind() {
                        self.expand_aliased_string_literals_if_appropriate(
                            &target_path,
                            &value,
                            s,
                            update,
                        );
                        return;
                    }
                }
            }
        }
        let target_type = ExpressionType::from(root_rustc_type.kind());
        let mut no_children = true;
        // If a non primitive parameter is just returned from a function, for example,
        // there will be no entries rooted with target_path in the final environment.
        // This will lead to an incorrect summary of the function, since only the paths
        // in the final environment are used construct the summary. We work around this
        // by creating an entry for the non primitive (unknown) value. The caller will
        // be saddled with removing it. This case corresponds to no_children being true.
        if target_type == ExpressionType::NonPrimitive || target_type == ExpressionType::Function {
            // First look at paths that are rooted in rpath.
            let value_map = self.current_environment.value_map.clone();
            for (path, value) in value_map
                .iter()
                .filter(|(p, _)| p.is_rooted_by(&source_path))
            {
                check_for_early_return!(self);
                if matches!(&value.expression, Expression::HeapBlockLayout { .. })
                    && !target_path.is_rooted_by_non_local_structure()
                {
                    continue;
                }
                let qualified_path = path
                    .replace_root(&source_path, target_path.clone())
                    .canonicalize(&self.current_environment);
                if move_elements {
                    trace!("moving child {:?} to {:?}", value, qualified_path);
                    self.current_environment.value_map =
                        self.current_environment.value_map.remove(path);
                } else {
                    trace!("copying child {:?} to {:?}", value, qualified_path);
                };
                update(self, qualified_path, value.clone());
                no_children = false;
            }
            if let Expression::InitialParameterValue { path, .. }
            | Expression::Variable { path, .. } = &value.expression
            {
                if path.is_rooted_by_parameter() {
                    update(self, target_path.clone(), value.clone());
                    no_children = false;
                }
            }
        }
        if target_type != ExpressionType::NonPrimitive
            || no_children
            || root_rustc_type.is_closure()
        {
            // Just copy/move (rpath, value) itself.
            if move_elements {
                trace!("moving {:?} to {:?}", value, target_path);
                self.current_environment.value_map =
                    self.current_environment.value_map.remove(&source_path);
            } else {
                trace!("copying {:?} to {:?}", value, target_path);
            }
            update(self, target_path, value);
        }
    }
pub fn non_patterned_copy_or_move_elements < F > ( & mut self , target_path : Rc < Path > , source_path : Rc < Path > , root_rustc_type : Ty < ' tcx > , move_elements : bool , update : F , ) where F : Fn ( & mut Self , Rc < Path > , Rc < AbstractValue > ) , { trace ! ( " " target_path source_path root_rustc_type ) ; let value = self . lookup_path_and_refine_result ( source_path . clone ( ) , root_rustc_type ) ; if let Expression :: Variable { path , .. } = & value . expression { if path . eq ( & source_path ) { // The source value is not known and we need to take additional precautions: let source_type = self . type_visitor ( ) . get_path_rustc_type ( & source_path , self . current_span ) ; if matches ! ( source_type kind ( ) TyKind Array ( t ) if t root_rustc_type ) { // During path refinement, the original source path was of the intermediate form *&p. // Mostly, this can just be canonicalized to just p, but if p has an array type // and *&p is not used as a qualifier, then *&p represents the first element of the array // if &p is the refinement of a pointer obtained from the array via array::as_ptr. let zero = Rc :: new ( 0u128 . into ( ) ) ; let first_element = Path :: new_index ( path . clone ( ) , zero ) ; self . non_patterned_copy_or_move_elements ( target_path , first_element , root_rustc_type , move_elements , update , ) ; return ; } } } if let Expression :: CompileTimeConstant ( ConstantDomain :: Str ( s ) ) = & value . expression { // The value is a string literal. See if the target will treat it as &[u8]. if let TyKind :: Ref ( _ , ty , _ ) = root_rustc_type . kind ( ) { if let TyKind :: Slice ( elem_ty ) = ty . kind ( ) { if let TyKind :: Uint ( UintTy :: U8 ) = elem_ty . kind ( ) { self . expand_aliased_string_literals_if_appropriate ( & target_path , & value , s , update , ) ; return ; } } } } let target_type = ExpressionType :: from ( root_rustc_type . kind ( ) ) ; let mut no_children = true ; // If a non primitive parameter is just returned from a function, for example, // there will be no entries rooted with target_path in the final environment. // This will lead to an incorrect summary of the function, since only the paths // in the final environment are used construct the summary. We work around this // by creating an entry for the non primitive (unknown) value. The caller will // be saddled with removing it. This case corresponds to no_children being true. if target_type == ExpressionType :: NonPrimitive || target_type == ExpressionType :: Function { // First look at paths that are rooted in rpath. let value_map = self . current_environment . value_map . clone ( ) ; for ( path , value ) in value_map . iter ( ) . filter ( | ( p , _ ) | p . is_rooted_by ( & source_path ) ) { check_for_early_return ! ( self ) ; if matches ! ( value expression Expression HeapBlockLayout { } ) && ! target_path . is_rooted_by_non_local_structure ( ) { continue ; } let qualified_path = path . replace_root ( & source_path , target_path . clone ( ) ) . canonicalize ( & self . current_environment ) ; if move_elements { trace ! ( " " value qualified_path ) ; self . current_environment . value_map = self . current_environment . value_map . remove ( path ) ; } else { trace ! ( " " value qualified_path ) ; } ; update ( self , qualified_path , value . clone ( ) ) ; no_children = false ; } if let Expression :: InitialParameterValue { path , .. } | Expression :: Variable { path , .. } = & value . expression { if path . is_rooted_by_parameter ( ) { update ( self , target_path . clone ( ) , value . clone ( ) ) ; no_children = false ; } } } if target_type != ExpressionType :: NonPrimitive || no_children || root_rustc_type . is_closure ( ) { // Just copy/move (rpath, value) itself. if move_elements { trace ! ( " " value target_path ) ; self . current_environment . value_map = self . current_environment . value_map . remove ( & source_path ) ; } else { trace ! ( " " value target_path ) ; } update ( self , target_path , value ) ; } }
Copies/moves all paths rooted in source_path to corresponding paths rooted in target_path.
Copies / moves all paths rooted in source_path to corresponding paths rooted in target_path .
&mut self
target_path
Rc<Path>
source_path
Rc<Path>
root_rustc_type
Ty<'tcx>
move_elements
bool
update
F
&mut self
target_path
Rc<Path>
source_path
Rc<Path>
root_rustc_type
Ty<'tcx>
move_elements
bool
update
F