// This method goes through all the errors and try to group certain types
// of error together, for the purpose of suggesting explicit lifetime
// parameters to the user. This is done so that we can have a more
// complete view of what lifetimes should be the same.
// If the return value is an empty vector, it means that processing
// failed (so the return value of this method should not be used)
This method goes through all the errors and try to group certain types
of error together, for the purpose of suggesting explicit lifetime
parameters to the user. This is done so that we can have a more
complete view of what lifetimes should be the same.
If the return value is an empty vector, it means that processing
failed (so the return value of this method should not be used)
This method goes through all the errors and try to group certain types of error together for the purpose of suggesting explicit lifetime parameters to the user . This is done so that we can have a more complete view of what lifetimes should be the same . If the return value is an empty vector it means that processing failed ( so the return value of this method should not be used )
fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
                      -> Vec<RegionResolutionError<'tcx>> {
        debug!("process_errors()");
        let mut var_origins = Vec::new();
        let mut trace_origins = Vec::new();
        let mut same_regions = Vec::new();
        let mut processed_errors = Vec::new();
        for error in errors {
            match error.clone() {
                ConcreteFailure(origin, sub, sup) => {
                    debug!("processing ConcreteFailure");
                    let trace = match origin {
                        infer::Subtype(trace) => Some(trace),
                        _ => None,
                    };
                    match free_regions_from_same_fn(self.tcx, sub, sup) {
                        Some(ref same_frs) if trace.is_some() => {
                            let trace = trace.unwrap();
                            let terr = TypeError::RegionsDoesNotOutlive(sup,
                                                                        sub);
                            trace_origins.push((trace, terr));
                            append_to_same_regions(&mut same_regions, same_frs);
                        }
                        _ => processed_errors.push((*error).clone()),
                    }
                }
                SubSupConflict(var_origin, _, sub_r, _, sup_r) => {
                    debug!("processing SubSupConflict sub: {:?} sup: {:?}", sub_r, sup_r);
                    match free_regions_from_same_fn(self.tcx, sub_r, sup_r) {
                        Some(ref same_frs) => {
                            var_origins.push(var_origin);
                            append_to_same_regions(&mut same_regions, same_frs);
                        }
                        None => processed_errors.push((*error).clone()),
                    }
                }
                SupSupConflict(..) => processed_errors.push((*error).clone()),
                _ => ()  // This shouldn't happen
            }
        }
        if !same_regions.is_empty() {
            let common_scope_id = same_regions[0].scope_id;
            for sr in &same_regions {
                // Since ProcessedErrors is used to reconstruct the function
                // declaration, we want to make sure that they are, in fact,
                // from the same scope
                if sr.scope_id != common_scope_id {
                    debug!("returning empty result from process_errors because
                            {} != {}", sr.scope_id, common_scope_id);
                    return vec!();
                }
            }
            let pe = ProcessedErrors(var_origins, trace_origins, same_regions);
            debug!("errors processed: {:?}", pe);
            processed_errors.push(pe);
        }
        return processed_errors;
        struct FreeRegionsFromSameFn {
            sub_fr: ty::FreeRegion,
            sup_fr: ty::FreeRegion,
            scope_id: ast::NodeId
        }
        impl FreeRegionsFromSameFn {
            fn new(sub_fr: ty::FreeRegion,
                   sup_fr: ty::FreeRegion,
                   scope_id: ast::NodeId)
                   -> FreeRegionsFromSameFn {
                FreeRegionsFromSameFn {
                    sub_fr: sub_fr,
                    sup_fr: sup_fr,
                    scope_id: scope_id
                }
            }
        }
        fn free_regions_from_same_fn(tcx: &ty::ctxt,
                                     sub: Region,
                                     sup: Region)
                                     -> Option<FreeRegionsFromSameFn> {
            debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
            let (scope_id, fr1, fr2) = match (sub, sup) {
                (ReFree(fr1), ReFree(fr2)) => {
                    if fr1.scope != fr2.scope {
                        return None
                    }
                    assert!(fr1.scope == fr2.scope);
                    (fr1.scope.node_id(&tcx.region_maps), fr1, fr2)
                },
                _ => return None
            };
            let parent = tcx.map.get_parent(scope_id);
            let parent_node = tcx.map.find(parent);
            match parent_node {
                Some(node) => match node {
                    ast_map::NodeItem(item) => match item.node {
                        hir::ItemFn(..) => {
                            Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
                        },
                        _ => None
                    },
                    ast_map::NodeImplItem(..) |
                    ast_map::NodeTraitItem(..) => {
                        Some(FreeRegionsFromSameFn::new(fr1, fr2, scope_id))
                    },
                    _ => None
                },
                None => {
                    debug!("no parent node of scope_id {}", scope_id);
                    None
                }
            }
        }
        fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
                                  same_frs: &FreeRegionsFromSameFn) {
            let scope_id = same_frs.scope_id;
            let (sub_fr, sup_fr) = (same_frs.sub_fr, same_frs.sup_fr);
            for sr in &mut *same_regions {
                if sr.contains(&sup_fr.bound_region)
                   && scope_id == sr.scope_id {
                    sr.push(sub_fr.bound_region);
                    return
                }
            }
            same_regions.push(SameRegions {
                scope_id: scope_id,
                regions: vec!(sub_fr.bound_region, sup_fr.bound_region)
            })
        }
    }
fn process_errors ( & self , errors : & Vec < RegionResolutionError < ' tcx > > ) -> Vec < RegionResolutionError < ' tcx > > { debug ! ( " " ) ; let mut var_origins = Vec :: new ( ) ; let mut trace_origins = Vec :: new ( ) ; let mut same_regions = Vec :: new ( ) ; let mut processed_errors = Vec :: new ( ) ; for error in errors { match error . clone ( ) { ConcreteFailure ( origin , sub , sup ) => { debug ! ( " " ) ; let trace = match origin { infer :: Subtype ( trace ) => Some ( trace ) , _ => None , } ; match free_regions_from_same_fn ( self . tcx , sub , sup ) { Some ( ref same_frs ) if trace . is_some ( ) => { let trace = trace . unwrap ( ) ; let terr = TypeError :: RegionsDoesNotOutlive ( sup , sub ) ; trace_origins . push ( ( trace , terr ) ) ; append_to_same_regions ( & mut same_regions , same_frs ) ; } _ => processed_errors . push ( ( * error ) . clone ( ) ) , } } SubSupConflict ( var_origin , _ , sub_r , _ , sup_r ) => { debug ! ( " " sub_r sup_r ) ; match free_regions_from_same_fn ( self . tcx , sub_r , sup_r ) { Some ( ref same_frs ) => { var_origins . push ( var_origin ) ; append_to_same_regions ( & mut same_regions , same_frs ) ; } None => processed_errors . push ( ( * error ) . clone ( ) ) , } } SupSupConflict ( .. ) => processed_errors . push ( ( * error ) . clone ( ) ) , _ => ( ) // This shouldn't happen } } if ! same_regions . is_empty ( ) { let common_scope_id = same_regions [ 0 ] . scope_id ; for sr in & same_regions { // Since ProcessedErrors is used to reconstruct the function // declaration, we want to make sure that they are, in fact, // from the same scope if sr . scope_id != common_scope_id { debug ! ( " " sr scope_id common_scope_id ) ; return vec ! ( ) ; } } let pe = ProcessedErrors ( var_origins , trace_origins , same_regions ) ; debug ! ( " " pe ) ; processed_errors . push ( pe ) ; } return processed_errors ; struct FreeRegionsFromSameFn { sub_fr : ty :: FreeRegion , sup_fr : ty :: FreeRegion , scope_id : ast :: NodeId } impl FreeRegionsFromSameFn { fn new ( sub_fr : ty :: FreeRegion , sup_fr : ty :: FreeRegion , scope_id : ast :: NodeId ) -> FreeRegionsFromSameFn { FreeRegionsFromSameFn { sub_fr : sub_fr , sup_fr : sup_fr , scope_id : scope_id } } } fn free_regions_from_same_fn ( tcx : & ty :: ctxt , sub : Region , sup : Region ) -> Option < FreeRegionsFromSameFn > { debug ! ( " " sub sup ) ; let ( scope_id , fr1 , fr2 ) = match ( sub , sup ) { ( ReFree ( fr1 ) , ReFree ( fr2 ) ) => { if fr1 . scope != fr2 . scope { return None } assert ! ( fr1 scope fr2 scope ) ; ( fr1 . scope . node_id ( & tcx . region_maps ) , fr1 , fr2 ) } , _ => return None } ; let parent = tcx . map . get_parent ( scope_id ) ; let parent_node = tcx . map . find ( parent ) ; match parent_node { Some ( node ) => match node { ast_map :: NodeItem ( item ) => match item . node { hir :: ItemFn ( .. ) => { Some ( FreeRegionsFromSameFn :: new ( fr1 , fr2 , scope_id ) ) } , _ => None } , ast_map :: NodeImplItem ( .. ) | ast_map :: NodeTraitItem ( .. ) => { Some ( FreeRegionsFromSameFn :: new ( fr1 , fr2 , scope_id ) ) } , _ => None } , None => { debug ! ( " " scope_id ) ; None } } } fn append_to_same_regions ( same_regions : & mut Vec < SameRegions > , same_frs : & FreeRegionsFromSameFn ) { let scope_id = same_frs . scope_id ; let ( sub_fr , sup_fr ) = ( same_frs . sub_fr , same_frs . sup_fr ) ; for sr in & mut * same_regions { if sr . contains ( & sup_fr . bound_region ) && scope_id == sr . scope_id { sr . push ( sub_fr . bound_region ) ; return } } same_regions . push ( SameRegions { scope_id : scope_id , regions : vec ! ( sub_fr bound_region sup_fr bound_region ) } ) } }
This method goes through all the errors and try to group certain types
of error together, for the purpose of suggesting explicit lifetime
parameters to the user.
This method goes through all the errors and try to group certain types of error together for the purpose of suggesting explicit lifetime parameters to the user .
&self
errors
&Vec<RegionResolutionError<'tcx>>