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

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

                ty::TyArray(subty, len) => {
                    self.require_sized(subty, traits::SliceOrArrayElem);
                    assert_eq!(len.ty, self.infcx.tcx.types.usize);
                    self.compute_const(len);
                }

                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, rty, _) => {
                    // WfReference
                    if !r.has_escaping_regions() && !rty.has_escaping_regions() {
                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                        self.out.push(
                            traits::Obligation::new(
                                cause,
                                param_env,
                                ty::Predicate::TypeOutlives(
                                    ty::Binder::dummy(
                                        ty::OutlivesPredicate(rty, r)))));
                    }
                }

                ty::TyGenerator(..) => {
                    // Walk ALL the types in the generator: this will
                    // include the upvar types as well as the yield
                    // type. Note that this is mildly distinct from
                    // the closure case, where we have to be careful
                    // about the signature of the closure. We don't
                    // have the problem of implied bounds here since
                    // generators don't take arguments.
                }

                ty::TyClosure(def_id, substs) => {
                    // Only check the upvar types for WF, not the rest
                    // of the types within. This is needed because we
                    // capture the signature and it may not be WF
                    // without the implied bounds. Consider a closure
                    // like `|x: &'a T|` -- it may be that `T: 'a` is
                    // not known to hold in the creator's context (and
                    // indeed the closure may not be invoked by its
                    // creator, but rather turned to someone who *can*
                    // verify that).
                    //
                    // The special treatment of closures here really
                    // ought not to be necessary either; the problem
                    // is related to #25860 -- there is no way for us
                    // to express a fn type complete with the implied
                    // bounds that it is assuming. I think in reality
                    // the WF rules around fn are a bit messed up, and
                    // that is the rot problem: `fn(&'a T)` should
                    // probably always be WF, because it should be
                    // shorthand for something like `where(T: 'a) {
                    // fn(&'a T) }`, as discussed in #25860.
                    //
                    // Note that we are also skipping the generic
                    // types. This is consistent with the `outlives`
                    // code, but anyway doesn't matter: within the fn
                    // body where they are created, the generics will
                    // always be WF, and outside of that fn body we
                    // are not directly inspecting closure types
                    // anyway, except via auto trait matching (which
                    // only inspects the upvar types).
                    subtys.skip_current_subtree(); // subtree handled by compute_projection
                    for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
                        self.compute(upvar_ty);
                    }
                }

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

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

                    // for named existential types we still need to check them
                    if super::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
                        let obligations = self.nominal_obligations(did, substs);
                        self.out.extend(obligations);
                    }
                }

                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(),
                            param_env,
                            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,
                                                    self.param_env,
                                                    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();
        let param_env = self.param_env;
        while let Some(ty) = subtys.next() {
            match ty.sty {
                ty::TyBool |
                ty::TyChar |
                ty::TyInt(..) |
                ty::TyUint(..) |
                ty::TyFloat(..) |
                ty::TyError |
                ty::TyStr |
                ty::TyGeneratorWitness(..) |
                ty::TyNever |
                ty::TyParam(_) |
                ty::TyForeign(..) => {
                    // WfScalar, WfParameter, etc
                }
                ty::TySlice(subty) => {
                    self.require_sized(subty, traits::SliceOrArrayElem);
                }
                ty::TyArray(subty, len) => {
                    self.require_sized(subty, traits::SliceOrArrayElem);
                    assert_eq!(len.ty, self.infcx.tcx.types.usize);
                    self.compute_const(len);
                }
                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, rty, _) => {
                    // WfReference
                    if !r.has_escaping_regions() && !rty.has_escaping_regions() {
                        let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
                        self.out.push(
                            traits::Obligation::new(
                                cause,
                                param_env,
                                ty::Predicate::TypeOutlives(
                                    ty::Binder::dummy(
                                        ty::OutlivesPredicate(rty, r)))));
                    }
                }
                ty::TyGenerator(..) => {
                    // Walk ALL the types in the generator: this will
                    // include the upvar types as well as the yield
                    // type. Note that this is mildly distinct from
                    // the closure case, where we have to be careful
                    // about the signature of the closure. We don't
                    // have the problem of implied bounds here since
                    // generators don't take arguments.
                }
                ty::TyClosure(def_id, substs) => {
                    // Only check the upvar types for WF, not the rest
                    // of the types within. This is needed because we
                    // capture the signature and it may not be WF
                    // without the implied bounds. Consider a closure
                    // like `|x: &'a T|` -- it may be that `T: 'a` is
                    // not known to hold in the creator's context (and
                    // indeed the closure may not be invoked by its
                    // creator, but rather turned to someone who *can*
                    // verify that).
                    //
                    // The special treatment of closures here really
                    // ought not to be necessary either; the problem
                    // is related to #25860 -- there is no way for us
                    // to express a fn type complete with the implied
                    // bounds that it is assuming. I think in reality
                    // the WF rules around fn are a bit messed up, and
                    // that is the rot problem: `fn(&'a T)` should
                    // probably always be WF, because it should be
                    // shorthand for something like `where(T: 'a) {
                    // fn(&'a T) }`, as discussed in #25860.
                    //
                    // Note that we are also skipping the generic
                    // types. This is consistent with the `outlives`
                    // code, but anyway doesn't matter: within the fn
                    // body where they are created, the generics will
                    // always be WF, and outside of that fn body we
                    // are not directly inspecting closure types
                    // anyway, except via auto trait matching (which
                    // only inspects the upvar types).
                    subtys.skip_current_subtree(); // subtree handled by compute_projection
                    for upvar_ty in substs.upvar_tys(def_id, self.infcx.tcx) {
                        self.compute(upvar_ty);
                    }
                }
                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                    // let the loop iterate into the argument/return
                    // types appearing in the fn signature
                }
                ty::TyAnon(did, substs) => {
                    // all of the requirements on type parameters
                    // should've been checked by the instantiation
                    // of whatever returned this exact `impl Trait`.
                    // for named existential types we still need to check them
                    if super::is_impl_trait_defn(self.infcx.tcx, did).is_none() {
                        let obligations = self.nominal_obligations(did, substs);
                        self.out.extend(obligations);
                    }
                }
                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(),
                            param_env,
                            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,
                                                    self.param_env,
                                                    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 ( ) ; let param_env = self . param_env ; while let Some ( ty ) = subtys . next ( ) { match ty . sty { ty :: TyBool | ty :: TyChar | ty :: TyInt ( .. ) | ty :: TyUint ( .. ) | ty :: TyFloat ( .. ) | ty :: TyError | ty :: TyStr | ty :: TyGeneratorWitness ( .. ) | ty :: TyNever | ty :: TyParam ( _ ) | ty :: TyForeign ( .. ) => { // WfScalar, WfParameter, etc } ty :: TySlice ( subty ) => { self . require_sized ( subty , traits :: SliceOrArrayElem ) ; } ty :: TyArray ( subty , len ) => { self . require_sized ( subty , traits :: SliceOrArrayElem ) ; assert_eq ! ( len ty self infcx tcx types usize ) ; self . compute_const ( len ) ; } 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 , rty , _ ) => { // WfReference if ! r . has_escaping_regions ( ) && ! rty . has_escaping_regions ( ) { let cause = self . cause ( traits :: ReferenceOutlivesReferent ( ty ) ) ; self . out . push ( traits :: Obligation :: new ( cause , param_env , ty :: Predicate :: TypeOutlives ( ty :: Binder :: dummy ( ty :: OutlivesPredicate ( rty , r ) ) ) ) ) ; } } ty :: TyGenerator ( .. ) => { // Walk ALL the types in the generator: this will // include the upvar types as well as the yield // type. Note that this is mildly distinct from // the closure case, where we have to be careful // about the signature of the closure. We don't // have the problem of implied bounds here since // generators don't take arguments. } ty :: TyClosure ( def_id , substs ) => { // Only check the upvar types for WF, not the rest // of the types within. This is needed because we // capture the signature and it may not be WF // without the implied bounds. Consider a closure // like `|x: &'a T|` -- it may be that `T: 'a` is // not known to hold in the creator's context (and // indeed the closure may not be invoked by its // creator, but rather turned to someone who *can* // verify that). // // The special treatment of closures here really // ought not to be necessary either; the problem // is related to #25860 -- there is no way for us // to express a fn type complete with the implied // bounds that it is assuming. I think in reality // the WF rules around fn are a bit messed up, and // that is the rot problem: `fn(&'a T)` should // probably always be WF, because it should be // shorthand for something like `where(T: 'a) { // fn(&'a T) }`, as discussed in #25860. // // Note that we are also skipping the generic // types. This is consistent with the `outlives` // code, but anyway doesn't matter: within the fn // body where they are created, the generics will // always be WF, and outside of that fn body we // are not directly inspecting closure types // anyway, except via auto trait matching (which // only inspects the upvar types). subtys . skip_current_subtree ( ) ; // subtree handled by compute_projection for upvar_ty in substs . upvar_tys ( def_id , self . infcx . tcx ) { self . compute ( upvar_ty ) ; } } ty :: TyFnDef ( .. ) | ty :: TyFnPtr ( _ ) => { // let the loop iterate into the argument/return // types appearing in the fn signature } ty :: TyAnon ( did , substs ) => { // all of the requirements on type parameters // should've been checked by the instantiation // of whatever returned this exact `impl Trait`. // for named existential types we still need to check them if super :: is_impl_trait_defn ( self . infcx . tcx , did ) . is_none ( ) { let obligations = self . nominal_obligations ( did , substs ) ; self . out . extend ( obligations ) ; } } 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 ( ) , param_env , 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 , self . param_env , 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>