fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
        let mut subtys = ty0.walk();
        while let Some(ty) = subtys.next() {
            match ty.sty {
                ty::TyBool |
                ty::TyChar |
                ty::TyInt(..) |
                ty::TyUint(..) |
                ty::TyFloat(..) |
                ty::TyError |
                ty::TyStr |
                ty::TyNever |
                ty::TyParam(_) => {
                    // WfScalar, WfParameter, etc
                }

                ty::TySlice(subty) |
                ty::TyArray(subty, _) => {
                    self.require_sized(subty, traits::SliceOrArrayElem);
                }

                ty::TyTuple(ref tys, _) => {
                    if let Some((_last, rest)) = tys.split_last() {
                        for elem in rest {
                            self.require_sized(elem, traits::TupleElem);
                        }
                    }
                }

                ty::TyRawPtr(_) => {
                    // simple cases that are WF if their type args are WF
                }

                ty::TyProjection(data) => {
                    subtys.skip_current_subtree(); // subtree handled by compute_projection
                    self.compute_projection(data);
                }

                ty::TyAdt(def, substs) => {
                    // WfNominalType
                    let obligations = self.nominal_obligations(def.did, substs);
                    self.out.extend(obligations);
                }

                ty::TyRef(r, mt) => {
                    // WfReference
                    if !r.has_escaping_regions() && !mt.ty.has_escaping_regions() {
                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                        self.out.push(
                            traits::Obligation::new(
                                cause,
                                ty::Predicate::TypeOutlives(
                                    ty::Binder(
                                        ty::OutlivesPredicate(mt.ty, r)))));
                    }
                }

                ty::TyClosure(..) => {
                    // the types in a closure are always the types of
                    // local variables (or possibly references to local
                    // variables), we'll walk those.
                    //
                    // (Though, local variables are probably not
                    // needed, as they are separately checked w/r/t
                    // WFedness.)
                }

                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                    // let the loop iterate into the argument/return
                    // types appearing in the fn signature
                }

                ty::TyAnon(..) => {
                    // all of the requirements on type parameters
                    // should've been checked by the instantiation
                    // of whatever returned this exact `impl Trait`.
                }

                ty::TyDynamic(data, r) => {
                    // WfObject
                    //
                    // Here, we defer WF checking due to higher-ranked
                    // regions. This is perhaps not ideal.
                    self.from_object_ty(ty, data, r);

                    // FIXME(#27579) RFC also considers adding trait
                    // obligations that don't refer to Self and
                    // checking those

                    let cause = self.cause(traits::MiscObligation);

                    let component_traits =
                        data.auto_traits().chain(data.principal().map(|p| p.def_id()));
                    self.out.extend(
                        component_traits.map(|did| traits::Obligation::new(
                            cause.clone(),
                            ty::Predicate::ObjectSafe(did)
                        ))
                    );
                }

                // Inference variables are the complicated case, since we don't
                // know what type they are. We do two things:
                //
                // 1. Check if they have been resolved, and if so proceed with
                //    THAT type.
                // 2. If not, check whether this is the type that we
                //    started with (ty0). In that case, we've made no
                //    progress at all, so return false. Otherwise,
                //    we've at least simplified things (i.e., we went
                //    from `Vec<$0>: WF` to `$0: WF`, so we can
                //    register a pending obligation and keep
                //    moving. (Goal is that an "inductive hypothesis"
                //    is satisfied to ensure termination.)
                ty::TyInfer(_) => {
                    let ty = self.infcx.shallow_resolve(ty);
                    if let ty::TyInfer(_) = ty.sty { // not yet resolved...
                        if ty == ty0 { // ...this is the type we started from! no progress.
                            return false;
                        }

                        let cause = self.cause(traits::MiscObligation);
                        self.out.push( // ...not the type we started from, so we made progress.
                            traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
                    } else {
                        // Yes, resolved, proceed with the
                        // result. Should never return false because
                        // `ty` is not a TyInfer.
                        assert!(self.compute(ty));
                    }
                }
            }
        }

        // if we made it through that loop above, we made progress!
        return true;
    }
/// Push new obligations into `out`. Returns true if it was able
/// to generate all the predicates needed to validate that `ty0`
/// is WF. Returns false if `ty0` is an unresolved type variable,
/// in which case we are not able to simplify at all.
Push new obligations into `out`. Returns true if it was able
to generate all the predicates needed to validate that `ty0`
is WF. Returns false if `ty0` is an unresolved type variable,
in which case we are not able to simplify at all.
Push new obligations into ` out ` . Returns true if it was able to generate all the predicates needed to validate that ` ty0 ` is WF . Returns false if ` ty0 ` is an unresolved type variable in which case we are not able to simplify at all .
fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
        let mut subtys = ty0.walk();
        while let Some(ty) = subtys.next() {
            match ty.sty {
                ty::TyBool |
                ty::TyChar |
                ty::TyInt(..) |
                ty::TyUint(..) |
                ty::TyFloat(..) |
                ty::TyError |
                ty::TyStr |
                ty::TyNever |
                ty::TyParam(_) => {
                    // WfScalar, WfParameter, etc
                }
                ty::TySlice(subty) |
                ty::TyArray(subty, _) => {
                    self.require_sized(subty, traits::SliceOrArrayElem);
                }
                ty::TyTuple(ref tys, _) => {
                    if let Some((_last, rest)) = tys.split_last() {
                        for elem in rest {
                            self.require_sized(elem, traits::TupleElem);
                        }
                    }
                }
                ty::TyRawPtr(_) => {
                    // simple cases that are WF if their type args are WF
                }
                ty::TyProjection(data) => {
                    subtys.skip_current_subtree(); // subtree handled by compute_projection
                    self.compute_projection(data);
                }
                ty::TyAdt(def, substs) => {
                    // WfNominalType
                    let obligations = self.nominal_obligations(def.did, substs);
                    self.out.extend(obligations);
                }
                ty::TyRef(r, mt) => {
                    // WfReference
                    if !r.has_escaping_regions() && !mt.ty.has_escaping_regions() {
                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                        self.out.push(
                            traits::Obligation::new(
                                cause,
                                ty::Predicate::TypeOutlives(
                                    ty::Binder(
                                        ty::OutlivesPredicate(mt.ty, r)))));
                    }
                }
                ty::TyClosure(..) => {
                    // the types in a closure are always the types of
                    // local variables (or possibly references to local
                    // variables), we'll walk those.
                    //
                    // (Though, local variables are probably not
                    // needed, as they are separately checked w/r/t
                    // WFedness.)
                }
                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                    // let the loop iterate into the argument/return
                    // types appearing in the fn signature
                }
                ty::TyAnon(..) => {
                    // all of the requirements on type parameters
                    // should've been checked by the instantiation
                    // of whatever returned this exact `impl Trait`.
                }
                ty::TyDynamic(data, r) => {
                    // WfObject
                    //
                    // Here, we defer WF checking due to higher-ranked
                    // regions. This is perhaps not ideal.
                    self.from_object_ty(ty, data, r);
                    // FIXME(#27579) RFC also considers adding trait
                    // obligations that don't refer to Self and
                    // checking those
                    let cause = self.cause(traits::MiscObligation);
                    let component_traits =
                        data.auto_traits().chain(data.principal().map(|p| p.def_id()));
                    self.out.extend(
                        component_traits.map(|did| traits::Obligation::new(
                            cause.clone(),
                            ty::Predicate::ObjectSafe(did)
                        ))
                    );
                }
                // Inference variables are the complicated case, since we don't
                // know what type they are. We do two things:
                //
                // 1. Check if they have been resolved, and if so proceed with
                //    THAT type.
                // 2. If not, check whether this is the type that we
                //    started with (ty0). In that case, we've made no
                //    progress at all, so return false. Otherwise,
                //    we've at least simplified things (i.e., we went
                //    from `Vec<$0>: WF` to `$0: WF`, so we can
                //    register a pending obligation and keep
                //    moving. (Goal is that an "inductive hypothesis"
                //    is satisfied to ensure termination.)
                ty::TyInfer(_) => {
                    let ty = self.infcx.shallow_resolve(ty);
                    if let ty::TyInfer(_) = ty.sty { // not yet resolved...
                        if ty == ty0 { // ...this is the type we started from! no progress.
                            return false;
                        }
                        let cause = self.cause(traits::MiscObligation);
                        self.out.push( // ...not the type we started from, so we made progress.
                            traits::Obligation::new(cause, ty::Predicate::WellFormed(ty)));
                    } else {
                        // Yes, resolved, proceed with the
                        // result. Should never return false because
                        // `ty` is not a TyInfer.
                        assert!(self.compute(ty));
                    }
                }
            }
        }
        // if we made it through that loop above, we made progress!
        return true;
    }
fn compute ( & mut self , ty0 : Ty < ' tcx > ) -> bool { let mut subtys = ty0 . walk ( ) ; while let Some ( ty ) = subtys . next ( ) { match ty . sty { ty :: TyBool | ty :: TyChar | ty :: TyInt ( .. ) | ty :: TyUint ( .. ) | ty :: TyFloat ( .. ) | ty :: TyError | ty :: TyStr | ty :: TyNever | ty :: TyParam ( _ ) => { // WfScalar, WfParameter, etc } ty :: TySlice ( subty ) | ty :: TyArray ( subty , _ ) => { self . require_sized ( subty , traits :: SliceOrArrayElem ) ; } ty :: TyTuple ( ref tys , _ ) => { if let Some ( ( _last , rest ) ) = tys . split_last ( ) { for elem in rest { self . require_sized ( elem , traits :: TupleElem ) ; } } } ty :: TyRawPtr ( _ ) => { // simple cases that are WF if their type args are WF } ty :: TyProjection ( data ) => { subtys . skip_current_subtree ( ) ; // subtree handled by compute_projection self . compute_projection ( data ) ; } ty :: TyAdt ( def , substs ) => { // WfNominalType let obligations = self . nominal_obligations ( def . did , substs ) ; self . out . extend ( obligations ) ; } ty :: TyRef ( r , mt ) => { // WfReference if ! r . has_escaping_regions ( ) && ! mt . ty . has_escaping_regions ( ) { let cause = self . cause ( traits :: ReferenceOutlivesReferent ( ty ) ) ; self . out . push ( traits :: Obligation :: new ( cause , ty :: Predicate :: TypeOutlives ( ty :: Binder ( ty :: OutlivesPredicate ( mt . ty , r ) ) ) ) ) ; } } ty :: TyClosure ( .. ) => { // the types in a closure are always the types of // local variables (or possibly references to local // variables), we'll walk those. // // (Though, local variables are probably not // needed, as they are separately checked w/r/t // WFedness.) } ty :: TyFnDef ( .. ) | ty :: TyFnPtr ( _ ) => { // let the loop iterate into the argument/return // types appearing in the fn signature } ty :: TyAnon ( .. ) => { // all of the requirements on type parameters // should've been checked by the instantiation // of whatever returned this exact `impl Trait`. } ty :: TyDynamic ( data , r ) => { // WfObject // // Here, we defer WF checking due to higher-ranked // regions. This is perhaps not ideal. self . from_object_ty ( ty , data , r ) ; // FIXME(#27579) RFC also considers adding trait // obligations that don't refer to Self and // checking those let cause = self . cause ( traits :: MiscObligation ) ; let component_traits = data . auto_traits ( ) . chain ( data . principal ( ) . map ( | p | p . def_id ( ) ) ) ; self . out . extend ( component_traits . map ( | did | traits :: Obligation :: new ( cause . clone ( ) , ty :: Predicate :: ObjectSafe ( did ) ) ) ) ; } // Inference variables are the complicated case, since we don't // know what type they are. We do two things: // // 1. Check if they have been resolved, and if so proceed with //    THAT type. // 2. If not, check whether this is the type that we //    started with (ty0). In that case, we've made no //    progress at all, so return false. Otherwise, //    we've at least simplified things (i.e., we went //    from `Vec<$0>: WF` to `$0: WF`, so we can //    register a pending obligation and keep //    moving. (Goal is that an "inductive hypothesis" //    is satisfied to ensure termination.) ty :: TyInfer ( _ ) => { let ty = self . infcx . shallow_resolve ( ty ) ; if let ty :: TyInfer ( _ ) = ty . sty { // not yet resolved... if ty == ty0 { // ...this is the type we started from! no progress. return false ; } let cause = self . cause ( traits :: MiscObligation ) ; self . out . push ( // ...not the type we started from, so we made progress. traits :: Obligation :: new ( cause , ty :: Predicate :: WellFormed ( ty ) ) ) ; } else { // Yes, resolved, proceed with the // result. Should never return false because // `ty` is not a TyInfer. assert ! ( self compute ( ty ) ) ; } } } } // if we made it through that loop above, we made progress! return true ; }
Push new obligations into `out`.
Push new obligations into ` out ` .
&mut self
ty0
Ty<'tcx>
&mut self
ty0
Ty<'tcx>