pub fn nearest_common_ancestor(&self,
                                   scope_a: CodeExtent,
                                   scope_b: CodeExtent)
                                   -> CodeExtent {
        if scope_a == scope_b { return scope_a; }

        /// [1] The initial values for `a_buf` and `b_buf` are not used.
        /// The `ancestors_of` function will return some prefix that
        /// is re-initialized with new values (or else fallback to a
        /// heap-allocated vector).
        let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
        let mut a_vec: Vec<CodeExtent> = vec![];
        let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
        let mut b_vec: Vec<CodeExtent> = vec![];
        let scope_map = &self.scope_map;
        let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
        let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
        let mut a_index = a_ancestors.len() - 1;
        let mut b_index = b_ancestors.len() - 1;

        // Here, [ab]_ancestors is a vector going from narrow to broad.
        // The end of each vector will be the item where the scope is
        // defined; if there are any common ancestors, then the tails of
        // the vector will be the same.  So basically we want to walk
        // backwards from the tail of each vector and find the first point
        // where they diverge.  If one vector is a suffix of the other,
        // then the corresponding scope is a superscope of the other.

        if a_ancestors[a_index] != b_ancestors[b_index] {
            // In this case, the two regions belong to completely
            // different functions.  Compare those fn for lexical
            // nesting. The reasoning behind this is subtle.  See the
            // "Modeling closures" section of the README in
            // infer::region_inference for more details.
            let a_root_scope = a_ancestors[a_index];
            let b_root_scope = a_ancestors[a_index];
            return match (a_root_scope, b_root_scope) {
                (CodeExtent::DestructionScope(a_root_id),
                 CodeExtent::DestructionScope(b_root_id)) => {
                    if self.fn_is_enclosed_by(a_root_id, b_root_id) {
                        // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
                        scope_b
                    } else if self.fn_is_enclosed_by(b_root_id, a_root_id) {
                        // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
                        scope_a
                    } else {
                        // neither fn encloses the other
                        bug!()
                    }
                }
                _ => {
                    // root ids are always Misc right now
                    bug!()
                }
            };
        }

        loop {
            // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index]
            // for all indices between a_index and the end of the array
            if a_index == 0 { return scope_a; }
            if b_index == 0 { return scope_b; }
            a_index -= 1;
            b_index -= 1;
            if a_ancestors[a_index] != b_ancestors[b_index] {
                return a_ancestors[a_index + 1];
            }
        }

        fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
                                  scope: CodeExtent,
                                  buf: &'a mut [CodeExtent; 32],
                                  vec: &'a mut Vec<CodeExtent>)
                                  -> &'a [CodeExtent] {
            // debug!("ancestors_of(scope={:?})", scope);
            let mut scope = scope;

            let mut i = 0;
            while i < 32 {
                buf[i] = scope;
                match scope_map.get(&scope) {
                    Some(&superscope) => scope = superscope,
                    _ => return &buf[..i+1]
                }
                i += 1;
            }

            *vec = Vec::with_capacity(64);
            vec.extend_from_slice(buf);
            loop {
                vec.push(scope);
                match scope_map.get(&scope) {
                    Some(&superscope) => scope = superscope,
                    _ => return &*vec
                }
            }
        }
    }
/// Finds the nearest common ancestor (if any) of two scopes.  That is, finds the smallest
/// scope which is greater than or equal to both `scope_a` and `scope_b`.
Finds the nearest common ancestor (if any) of two scopes.  That is, finds the smallest
scope which is greater than or equal to both `scope_a` and `scope_b`.
Finds the nearest common ancestor ( if any ) of two scopes . That is finds the smallest scope which is greater than or equal to both ` scope_a ` and ` scope_b ` .
pub fn nearest_common_ancestor(&self,
                                   scope_a: CodeExtent,
                                   scope_b: CodeExtent)
                                   -> CodeExtent {
        if scope_a == scope_b { return scope_a; }
        /// [1] The initial values for `a_buf` and `b_buf` are not used.
        /// The `ancestors_of` function will return some prefix that
        /// is re-initialized with new values (or else fallback to a
        /// heap-allocated vector).
        let mut a_buf: [CodeExtent; 32] = [scope_a /* [1] */; 32];
        let mut a_vec: Vec<CodeExtent> = vec![];
        let mut b_buf: [CodeExtent; 32] = [scope_b /* [1] */; 32];
        let mut b_vec: Vec<CodeExtent> = vec![];
        let scope_map = &self.scope_map;
        let a_ancestors = ancestors_of(scope_map, scope_a, &mut a_buf, &mut a_vec);
        let b_ancestors = ancestors_of(scope_map, scope_b, &mut b_buf, &mut b_vec);
        let mut a_index = a_ancestors.len() - 1;
        let mut b_index = b_ancestors.len() - 1;
        // Here, [ab]_ancestors is a vector going from narrow to broad.
        // The end of each vector will be the item where the scope is
        // defined; if there are any common ancestors, then the tails of
        // the vector will be the same.  So basically we want to walk
        // backwards from the tail of each vector and find the first point
        // where they diverge.  If one vector is a suffix of the other,
        // then the corresponding scope is a superscope of the other.
        if a_ancestors[a_index] != b_ancestors[b_index] {
            // In this case, the two regions belong to completely
            // different functions.  Compare those fn for lexical
            // nesting. The reasoning behind this is subtle.  See the
            // "Modeling closures" section of the README in
            // infer::region_inference for more details.
            let a_root_scope = a_ancestors[a_index];
            let b_root_scope = a_ancestors[a_index];
            return match (a_root_scope, b_root_scope) {
                (CodeExtent::DestructionScope(a_root_id),
                 CodeExtent::DestructionScope(b_root_id)) => {
                    if self.fn_is_enclosed_by(a_root_id, b_root_id) {
                        // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
                        scope_b
                    } else if self.fn_is_enclosed_by(b_root_id, a_root_id) {
                        // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
                        scope_a
                    } else {
                        // neither fn encloses the other
                        bug!()
                    }
                }
                _ => {
                    // root ids are always Misc right now
                    bug!()
                }
            };
        }
        loop {
            // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index]
            // for all indices between a_index and the end of the array
            if a_index == 0 { return scope_a; }
            if b_index == 0 { return scope_b; }
            a_index -= 1;
            b_index -= 1;
            if a_ancestors[a_index] != b_ancestors[b_index] {
                return a_ancestors[a_index + 1];
            }
        }
        fn ancestors_of<'a, 'tcx>(scope_map: &FxHashMap<CodeExtent, CodeExtent>,
                                  scope: CodeExtent,
                                  buf: &'a mut [CodeExtent; 32],
                                  vec: &'a mut Vec<CodeExtent>)
                                  -> &'a [CodeExtent] {
            // debug!("ancestors_of(scope={:?})", scope);
            let mut scope = scope;
            let mut i = 0;
            while i < 32 {
                buf[i] = scope;
                match scope_map.get(&scope) {
                    Some(&superscope) => scope = superscope,
                    _ => return &buf[..i+1]
                }
                i += 1;
            }
            *vec = Vec::with_capacity(64);
            vec.extend_from_slice(buf);
            loop {
                vec.push(scope);
                match scope_map.get(&scope) {
                    Some(&superscope) => scope = superscope,
                    _ => return &*vec
                }
            }
        }
    }
pub fn nearest_common_ancestor ( & self , scope_a : CodeExtent , scope_b : CodeExtent ) -> CodeExtent { if scope_a == scope_b { return scope_a ; } /// [1] The initial values for `a_buf` and `b_buf` are not used. /// The `ancestors_of` function will return some prefix that /// is re-initialized with new values (or else fallback to a /// heap-allocated vector). let mut a_buf : [ CodeExtent ; 32 ] = [ scope_a /* [1] */ ; 32 ] ; let mut a_vec : Vec < CodeExtent > = vec ! [ ] ; let mut b_buf : [ CodeExtent ; 32 ] = [ scope_b /* [1] */ ; 32 ] ; let mut b_vec : Vec < CodeExtent > = vec ! [ ] ; let scope_map = & self . scope_map ; let a_ancestors = ancestors_of ( scope_map , scope_a , & mut a_buf , & mut a_vec ) ; let b_ancestors = ancestors_of ( scope_map , scope_b , & mut b_buf , & mut b_vec ) ; let mut a_index = a_ancestors . len ( ) - 1 ; let mut b_index = b_ancestors . len ( ) - 1 ; // Here, [ab]_ancestors is a vector going from narrow to broad. // The end of each vector will be the item where the scope is // defined; if there are any common ancestors, then the tails of // the vector will be the same.  So basically we want to walk // backwards from the tail of each vector and find the first point // where they diverge.  If one vector is a suffix of the other, // then the corresponding scope is a superscope of the other. if a_ancestors [ a_index ] != b_ancestors [ b_index ] { // In this case, the two regions belong to completely // different functions.  Compare those fn for lexical // nesting. The reasoning behind this is subtle.  See the // "Modeling closures" section of the README in // infer::region_inference for more details. let a_root_scope = a_ancestors [ a_index ] ; let b_root_scope = a_ancestors [ a_index ] ; return match ( a_root_scope , b_root_scope ) { ( CodeExtent :: DestructionScope ( a_root_id ) , CodeExtent :: DestructionScope ( b_root_id ) ) => { if self . fn_is_enclosed_by ( a_root_id , b_root_id ) { // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` scope_b } else if self . fn_is_enclosed_by ( b_root_id , a_root_id ) { // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b` scope_a } else { // neither fn encloses the other bug ! ( ) } } _ => { // root ids are always Misc right now bug ! ( ) } } ; } loop { // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index] // for all indices between a_index and the end of the array if a_index == 0 { return scope_a ; } if b_index == 0 { return scope_b ; } a_index -= 1 ; b_index -= 1 ; if a_ancestors [ a_index ] != b_ancestors [ b_index ] { return a_ancestors [ a_index + 1 ] ; } } fn ancestors_of < ' a , ' tcx > ( scope_map : & FxHashMap < CodeExtent , CodeExtent > , scope : CodeExtent , buf : & ' a mut [ CodeExtent ; 32 ] , vec : & ' a mut Vec < CodeExtent > ) -> & ' a [ CodeExtent ] { // debug!("ancestors_of(scope={:?})", scope); let mut scope = scope ; let mut i = 0 ; while i < 32 { buf [ i ] = scope ; match scope_map . get ( & scope ) { Some ( & superscope ) => scope = superscope , _ => return & buf [ .. i + 1 ] } i += 1 ; } * vec = Vec :: with_capacity ( 64 ) ; vec . extend_from_slice ( buf ) ; loop { vec . push ( scope ) ; match scope_map . get ( & scope ) { Some ( & superscope ) => scope = superscope , _ => return & * vec } } } }
Finds the nearest common ancestor (if any) of two scopes.
Finds the nearest common ancestor ( if any ) of two scopes .
&self
scope_a
CodeExtent
scope_b
CodeExtent
&self
scope_a
CodeExtent
scope_b
CodeExtent