fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    span: Span,
    for_ty: Ty<'tcx>,
    depth: usize,
    ty: Ty<'tcx>,
) -> Result<DtorckConstraint<'tcx>, NoSolution> {
    debug!(
        "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})",
        span, for_ty, depth, ty
    );

    if depth >= *tcx.sess.recursion_limit.get() {
        return Ok(DtorckConstraint {
            outlives: vec![],
            dtorck_types: vec![],
            overflows: vec![ty],
        });
    }

    let result = match ty.sty {
        ty::Bool
        | ty::Char
        | ty::Int(_)
        | ty::Uint(_)
        | ty::Float(_)
        | ty::Str
        | ty::Never
        | ty::Foreign(..)
        | ty::RawPtr(..)
        | ty::Ref(..)
        | ty::FnDef(..)
        | ty::FnPtr(_)
        | ty::GeneratorWitness(..) => {
            // these types never have a destructor
            Ok(DtorckConstraint::empty())
        }

        ty::Array(ety, _) | ty::Slice(ety) => {
            // single-element containers, behave like their element
            dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
        }

        ty::Tuple(tys) => tys
            .iter()
            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
            .collect(),

        ty::Closure(def_id, substs) => substs
            .upvar_tys(def_id, tcx)
            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
            .collect(),

        ty::Generator(def_id, substs, _movability) => {
            // rust-lang/rust#49918: types can be constructed, stored
            // in the interior, and sit idle when generator yields
            // (and is subsequently dropped).
            //
            // It would be nice to descend into interior of a
            // generator to determine what effects dropping it might
            // have (by looking at any drop effects associated with
            // its interior).
            //
            // However, the interior's representation uses things like
            // GeneratorWitness that explicitly assume they are not
            // traversed in such a manner. So instead, we will
            // simplify things for now by treating all generators as
            // if they were like trait objects, where its upvars must
            // all be alive for the generator's (potential)
            // destructor.
            //
            // In particular, skipping over `_interior` is safe
            // because any side-effects from dropping `_interior` can
            // only take place through references with lifetimes
            // derived from lifetimes attached to the upvars, and we
            // *do* incorporate the upvars here.

            let constraint = DtorckConstraint {
                outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
                dtorck_types: vec![],
                overflows: vec![],
            };
            debug!(
                "dtorck_constraint: generator {:?} => {:?}",
                def_id, constraint
            );

            Ok(constraint)
        }

        ty::Adt(def, substs) => {
            let DtorckConstraint {
                dtorck_types,
                outlives,
                overflows,
            } = tcx.at(span).adt_dtorck_constraint(def.did)?;
            Ok(DtorckConstraint {
                // FIXME: we can try to recursively `dtorck_constraint_on_ty`
                // there, but that needs some way to handle cycles.
                dtorck_types: dtorck_types.subst(tcx, substs),
                outlives: outlives.subst(tcx, substs),
                overflows: overflows.subst(tcx, substs),
            })
        }

        // Objects must be alive in order for their destructor
        // to be called.
        ty::Dynamic(..) => Ok(DtorckConstraint {
            outlives: vec![ty.into()],
            dtorck_types: vec![],
            overflows: vec![],
        }),

        // Types that can't be resolved. Pass them forward.
        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint {
            outlives: vec![],
            dtorck_types: vec![ty],
            overflows: vec![],
        }),

        ty::Infer(..) | ty::Error => {
            // By the time this code runs, all type variables ought to
            // be fully resolved.
            Err(NoSolution)
        }
    };

    debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result);
    result
}
/// Return a set of constraints that needs to be satisfied in
/// order for `ty` to be valid for destruction.
Return a set of constraints that needs to be satisfied in
order for `ty` to be valid for destruction.
Return a set of constraints that needs to be satisfied in order for ` ty ` to be valid for destruction .
fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
    tcx: TyCtxt<'a, 'gcx, 'tcx>,
    span: Span,
    for_ty: Ty<'tcx>,
    depth: usize,
    ty: Ty<'tcx>,
) -> Result<DtorckConstraint<'tcx>, NoSolution> {
    debug!(
        "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})",
        span, for_ty, depth, ty
    );
    if depth >= *tcx.sess.recursion_limit.get() {
        return Ok(DtorckConstraint {
            outlives: vec![],
            dtorck_types: vec![],
            overflows: vec![ty],
        });
    }
    let result = match ty.sty {
        ty::Bool
        | ty::Char
        | ty::Int(_)
        | ty::Uint(_)
        | ty::Float(_)
        | ty::Str
        | ty::Never
        | ty::Foreign(..)
        | ty::RawPtr(..)
        | ty::Ref(..)
        | ty::FnDef(..)
        | ty::FnPtr(_)
        | ty::GeneratorWitness(..) => {
            // these types never have a destructor
            Ok(DtorckConstraint::empty())
        }
        ty::Array(ety, _) | ty::Slice(ety) => {
            // single-element containers, behave like their element
            dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
        }
        ty::Tuple(tys) => tys
            .iter()
            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
            .collect(),
        ty::Closure(def_id, substs) => substs
            .upvar_tys(def_id, tcx)
            .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
            .collect(),
        ty::Generator(def_id, substs, _movability) => {
            // rust-lang/rust#49918: types can be constructed, stored
            // in the interior, and sit idle when generator yields
            // (and is subsequently dropped).
            //
            // It would be nice to descend into interior of a
            // generator to determine what effects dropping it might
            // have (by looking at any drop effects associated with
            // its interior).
            //
            // However, the interior's representation uses things like
            // GeneratorWitness that explicitly assume they are not
            // traversed in such a manner. So instead, we will
            // simplify things for now by treating all generators as
            // if they were like trait objects, where its upvars must
            // all be alive for the generator's (potential)
            // destructor.
            //
            // In particular, skipping over `_interior` is safe
            // because any side-effects from dropping `_interior` can
            // only take place through references with lifetimes
            // derived from lifetimes attached to the upvars, and we
            // *do* incorporate the upvars here.
            let constraint = DtorckConstraint {
                outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(),
                dtorck_types: vec![],
                overflows: vec![],
            };
            debug!(
                "dtorck_constraint: generator {:?} => {:?}",
                def_id, constraint
            );
            Ok(constraint)
        }
        ty::Adt(def, substs) => {
            let DtorckConstraint {
                dtorck_types,
                outlives,
                overflows,
            } = tcx.at(span).adt_dtorck_constraint(def.did)?;
            Ok(DtorckConstraint {
                // FIXME: we can try to recursively `dtorck_constraint_on_ty`
                // there, but that needs some way to handle cycles.
                dtorck_types: dtorck_types.subst(tcx, substs),
                outlives: outlives.subst(tcx, substs),
                overflows: overflows.subst(tcx, substs),
            })
        }
        // Objects must be alive in order for their destructor
        // to be called.
        ty::Dynamic(..) => Ok(DtorckConstraint {
            outlives: vec![ty.into()],
            dtorck_types: vec![],
            overflows: vec![],
        }),
        // Types that can't be resolved. Pass them forward.
        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint {
            outlives: vec![],
            dtorck_types: vec![ty],
            overflows: vec![],
        }),
        ty::Infer(..) | ty::Error => {
            // By the time this code runs, all type variables ought to
            // be fully resolved.
            Err(NoSolution)
        }
    };
    debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result);
    result
}
fn dtorck_constraint_for_ty < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > , span : Span , for_ty : Ty < ' tcx > , depth : usize , ty : Ty < ' tcx > , ) -> Result < DtorckConstraint < ' tcx > , NoSolution > { debug ! ( " " span for_ty depth ty ) ; if depth >= * tcx . sess . recursion_limit . get ( ) { return Ok ( DtorckConstraint { outlives : vec ! [ ] , dtorck_types : vec ! [ ] , overflows : vec ! [ ty ] , } ) ; } let result = match ty . sty { ty :: Bool | ty :: Char | ty :: Int ( _ ) | ty :: Uint ( _ ) | ty :: Float ( _ ) | ty :: Str | ty :: Never | ty :: Foreign ( .. ) | ty :: RawPtr ( .. ) | ty :: Ref ( .. ) | ty :: FnDef ( .. ) | ty :: FnPtr ( _ ) | ty :: GeneratorWitness ( .. ) => { // these types never have a destructor Ok ( DtorckConstraint :: empty ( ) ) } ty :: Array ( ety , _ ) | ty :: Slice ( ety ) => { // single-element containers, behave like their element dtorck_constraint_for_ty ( tcx , span , for_ty , depth + 1 , ety ) } ty :: Tuple ( tys ) => tys . iter ( ) . map ( | ty | dtorck_constraint_for_ty ( tcx , span , for_ty , depth + 1 , ty ) ) . collect ( ) , ty :: Closure ( def_id , substs ) => substs . upvar_tys ( def_id , tcx ) . map ( | ty | dtorck_constraint_for_ty ( tcx , span , for_ty , depth + 1 , ty ) ) . collect ( ) , ty :: Generator ( def_id , substs , _movability ) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when generator yields // (and is subsequently dropped). // // It would be nice to descend into interior of a // generator to determine what effects dropping it might // have (by looking at any drop effects associated with // its interior). // // However, the interior's representation uses things like // GeneratorWitness that explicitly assume they are not // traversed in such a manner. So instead, we will // simplify things for now by treating all generators as // if they were like trait objects, where its upvars must // all be alive for the generator's (potential) // destructor. // // In particular, skipping over `_interior` is safe // because any side-effects from dropping `_interior` can // only take place through references with lifetimes // derived from lifetimes attached to the upvars, and we // *do* incorporate the upvars here. let constraint = DtorckConstraint { outlives : substs . upvar_tys ( def_id , tcx ) . map ( | t | t . into ( ) ) . collect ( ) , dtorck_types : vec ! [ ] , overflows : vec ! [ ] , } ; debug ! ( " " def_id constraint ) ; Ok ( constraint ) } ty :: Adt ( def , substs ) => { let DtorckConstraint { dtorck_types , outlives , overflows , } = tcx . at ( span ) . adt_dtorck_constraint ( def . did ) ? ; Ok ( DtorckConstraint { // FIXME: we can try to recursively `dtorck_constraint_on_ty` // there, but that needs some way to handle cycles. dtorck_types : dtorck_types . subst ( tcx , substs ) , outlives : outlives . subst ( tcx , substs ) , overflows : overflows . subst ( tcx , substs ) , } ) } // Objects must be alive in order for their destructor // to be called. ty :: Dynamic ( .. ) => Ok ( DtorckConstraint { outlives : vec ! [ ty into ( ) ] , dtorck_types : vec ! [ ] , overflows : vec ! [ ] , } ) , // Types that can't be resolved. Pass them forward. ty :: Projection ( .. ) | ty :: Opaque ( .. ) | ty :: Param ( .. ) => Ok ( DtorckConstraint { outlives : vec ! [ ] , dtorck_types : vec ! [ ty ] , overflows : vec ! [ ] , } ) , ty :: Infer ( .. ) | ty :: Error => { // By the time this code runs, all type variables ought to // be fully resolved. Err ( NoSolution ) } } ; debug ! ( " " ty result ) ; result }
Return a set of constraints that needs to be satisfied in
order for `ty` to be valid for destruction.
Return a set of constraints that needs to be satisfied in order for ` ty ` to be valid for destruction .
tcx
TyCtxt<'a, 'gcx, 'tcx>
span
Span
for_ty
Ty<'tcx>
depth
usize
ty
Ty<'tcx>
tcx
TyCtxt<'a, 'gcx, 'tcx>
span
Span
for_ty
Ty<'tcx>
depth
usize
ty
Ty<'tcx>