pub fn instantiate_nll_query_result_and_region_obligations<R>(
        &self,
        cause: &ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        original_values: &SmallCanonicalVarValues<'tcx>,
        query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
    ) -> InferResult<'tcx, R>
    where
        R: Debug + TypeFoldable<'tcx>,
    {
        // In an NLL query, there should be no type variables in the
        // query, only region variables.
        debug_assert!(query_result.variables.iter().all(|v| match v.kind {
            CanonicalVarKind::Ty(_) => false,
            CanonicalVarKind::Region => true,
        }));

        let result_subst =
            self.query_result_substitution_guess(cause, original_values, query_result);

        // Compute `QueryRegionConstraint` values that unify each of
        // the original values `v_o` that was canonicalized into a
        // variable...
        let mut obligations = vec![];

        for (index, original_value) in original_values.iter().enumerate() {
            // ...with the value `v_r` of that variable from the query.
            let result_value = query_result.substitute_projected(self.tcx, &result_subst, |v| {
                &v.var_values[CanonicalVar::new(index)]
            });
            match (original_value.unpack(), result_value.unpack()) {
                (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
                    // no action needed
                }

                (UnpackedKind::Lifetime(v_o), UnpackedKind::Lifetime(v_r)) => {
                    // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
                    if v_o != v_r {
                        output_query_region_constraints
                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
                        output_query_region_constraints
                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
                    }
                }

                (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
                    let ok = self.at(cause, param_env).eq(v1, v2)?;
                    obligations.extend(ok.into_obligations());
                }

                _ => {
                    bug!(
                        "kind mismatch, cannot unify {:?} and {:?}",
                        original_value,
                        result_value
                    );
                }
            }
        }

        // ...also include the other query region constraints from the query.
        output_query_region_constraints.reserve(query_result.value.region_constraints.len());
        for r_c in query_result.value.region_constraints.iter() {
            let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
            let k1 = substitute_value(self.tcx, &result_subst, &k1);
            let r2 = substitute_value(self.tcx, &result_subst, &r2);
            if k1 != r2.into() {
                output_query_region_constraints
                    .push(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)));
            }
        }

        let user_result: R =
            query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);

        Ok(InferOk {
            value: user_result,
            obligations,
        })
    }
/// An alternative to
/// `instantiate_query_result_and_region_obligations` that is more
/// efficient for NLL. NLL is a bit more advanced in the
/// "transition to chalk" than the rest of the compiler. During
/// the NLL type check, all of the "processing" of types and
/// things happens in queries -- the NLL checker itself is only
/// interested in the region obligations (`'a: 'b` or `T: 'b`)
/// that come out of these queries, which it wants to convert into
/// MIR-based constraints and solve. Therefore, it is most
/// convenient for the NLL Type Checker to **directly consume**
/// the `QueryRegionConstraint` values that arise from doing a
/// query. This is contrast to other parts of the compiler, which
/// would prefer for those `QueryRegionConstraint` to be converted
/// into the older infcx-style constraints (e.g., calls to
/// `sub_regions` or `register_region_obligation`).
///
/// Therefore, `instantiate_nll_query_result_and_region_obligations` performs the same
/// basic operations as `instantiate_query_result_and_region_obligations` but
/// it returns its result differently:
///
/// - It creates a substitution `S` that maps from the original
///   query variables to the values computed in the query
///   result. If any errors arise, they are propagated back as an
///   `Err` result.
/// - In the case of a successful substitution, we will append
///   `QueryRegionConstraint` values onto the
///   `output_query_region_constraints` vector for the solver to
///   use (if an error arises, some values may also be pushed, but
///   they should be ignored).
/// - It **can happen** (though it rarely does currently) that
///   equating types and things will give rise to subobligations
///   that must be processed.  In this case, those subobligations
///   are propagated back in the return value.
/// - Finally, the query result (of type `R`) is propagated back,
///   after applying the substitution `S`.
An alternative to
`instantiate_query_result_and_region_obligations` that is more
efficient for NLL. NLL is a bit more advanced in the
"transition to chalk" than the rest of the compiler. During
the NLL type check, all of the "processing" of types and
things happens in queries -- the NLL checker itself is only
interested in the region obligations (`'a: 'b` or `T: 'b`)
that come out of these queries, which it wants to convert into
MIR-based constraints and solve. Therefore, it is most
convenient for the NLL Type Checker to **directly consume
the `QueryRegionConstraint` values that arise from doing a
query. This is contrast to other parts of the compiler, which
would prefer for those `QueryRegionConstraint` to be converted
into the older infcx-style constraints .

Therefore, `instantiate_nll_query_result_and_region_obligations` performs the same
basic operations as `instantiate_query_result_and_region_obligations` but
it returns its result differently.

It creates a substitution `S` that maps from the original
query variables to the values computed in the query
result. If any errors arise, they are propagated back as an
`Err` result.
In the case of a successful substitution, we will append
`QueryRegionConstraint` values onto the
`output_query_region_constraints` vector for the solver to
use (if an error arises, some values may also be pushed, but
they should be ignored).
It **can happen** (though it rarely does currently) that
equating types and things will give rise to subobligations
that must be processed.  In this case, those subobligations
are propagated back in the return value.
Finally, the query result (of type `R`) is propagated back,
after applying the substitution `S`.
An alternative to ` instantiate_query_result_and_region_obligations ` that is more efficient for NLL . NLL is a bit more advanced in the " transition to chalk " than the rest of the compiler . During the NLL type check all of the " processing " of types and things happens in queries -- the NLL checker itself is only interested in the region obligations ( ` ' a : ' b ` or ` T : ' b ` ) that come out of these queries which it wants to convert into MIR - based constraints and solve . Therefore it is most convenient for the NLL Type Checker to ** directly consume the ` QueryRegionConstraint ` values that arise from doing a query . This is contrast to other parts of the compiler which would prefer for those ` QueryRegionConstraint ` to be converted into the older infcx - style constraints . Therefore ` instantiate_nll_query_result_and_region_obligations ` performs the same basic operations as ` instantiate_query_result_and_region_obligations ` but it returns its result differently . It creates a substitution ` S ` that maps from the original query variables to the values computed in the query result . If any errors arise they are propagated back as an ` Err ` result . In the case of a successful substitution we will append ` QueryRegionConstraint ` values onto the ` output_query_region_constraints ` vector for the solver to use ( if an error arises some values may also be pushed but they should be ignored ) . It ** can happen ** ( though it rarely does currently ) that equating types and things will give rise to subobligations that must be processed . In this case those subobligations are propagated back in the return value . Finally the query result ( of type ` R ` ) is propagated back after applying the substitution ` S ` .
pub fn instantiate_nll_query_result_and_region_obligations<R>(
        &self,
        cause: &ObligationCause<'tcx>,
        param_env: ty::ParamEnv<'tcx>,
        original_values: &SmallCanonicalVarValues<'tcx>,
        query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
    ) -> InferResult<'tcx, R>
    where
        R: Debug + TypeFoldable<'tcx>,
    {
        // In an NLL query, there should be no type variables in the
        // query, only region variables.
        debug_assert!(query_result.variables.iter().all(|v| match v.kind {
            CanonicalVarKind::Ty(_) => false,
            CanonicalVarKind::Region => true,
        }));
        let result_subst =
            self.query_result_substitution_guess(cause, original_values, query_result);
        // Compute `QueryRegionConstraint` values that unify each of
        // the original values `v_o` that was canonicalized into a
        // variable...
        let mut obligations = vec![];
        for (index, original_value) in original_values.iter().enumerate() {
            // ...with the value `v_r` of that variable from the query.
            let result_value = query_result.substitute_projected(self.tcx, &result_subst, |v| {
                &v.var_values[CanonicalVar::new(index)]
            });
            match (original_value.unpack(), result_value.unpack()) {
                (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
                    // no action needed
                }
                (UnpackedKind::Lifetime(v_o), UnpackedKind::Lifetime(v_r)) => {
                    // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
                    if v_o != v_r {
                        output_query_region_constraints
                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
                        output_query_region_constraints
                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
                    }
                }
                (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
                    let ok = self.at(cause, param_env).eq(v1, v2)?;
                    obligations.extend(ok.into_obligations());
                }
                _ => {
                    bug!(
                        "kind mismatch, cannot unify {:?} and {:?}",
                        original_value,
                        result_value
                    );
                }
            }
        }
        // ...also include the other query region constraints from the query.
        output_query_region_constraints.reserve(query_result.value.region_constraints.len());
        for r_c in query_result.value.region_constraints.iter() {
            let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
            let k1 = substitute_value(self.tcx, &result_subst, &k1);
            let r2 = substitute_value(self.tcx, &result_subst, &r2);
            if k1 != r2.into() {
                output_query_region_constraints
                    .push(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)));
            }
        }
        let user_result: R =
            query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
        Ok(InferOk {
            value: user_result,
            obligations,
        })
    }
pub fn instantiate_nll_query_result_and_region_obligations < R > ( & self , cause : & ObligationCause < ' tcx > , param_env : ty :: ParamEnv < ' tcx > , original_values : & SmallCanonicalVarValues < ' tcx > , query_result : & Canonical < ' tcx , QueryResult < ' tcx , R > > , output_query_region_constraints : & mut Vec < QueryRegionConstraint < ' tcx > > , ) -> InferResult < ' tcx , R > where R : Debug + TypeFoldable < ' tcx > , { // In an NLL query, there should be no type variables in the // query, only region variables. debug_assert ! ( query_result variables iter ( ) all ( v match v kind { CanonicalVarKind Ty ( ) false CanonicalVarKind Region true } ) ) ; let result_subst = self . query_result_substitution_guess ( cause , original_values , query_result ) ; // Compute `QueryRegionConstraint` values that unify each of // the original values `v_o` that was canonicalized into a // variable... let mut obligations = vec ! [ ] ; for ( index , original_value ) in original_values . iter ( ) . enumerate ( ) { // ...with the value `v_r` of that variable from the query. let result_value = query_result . substitute_projected ( self . tcx , & result_subst , | v | { & v . var_values [ CanonicalVar :: new ( index ) ] } ) ; match ( original_value . unpack ( ) , result_value . unpack ( ) ) { ( UnpackedKind :: Lifetime ( ty :: ReErased ) , UnpackedKind :: Lifetime ( ty :: ReErased ) ) => { // no action needed } ( UnpackedKind :: Lifetime ( v_o ) , UnpackedKind :: Lifetime ( v_r ) ) => { // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`. if v_o != v_r { output_query_region_constraints . push ( ty :: Binder :: dummy ( ty :: OutlivesPredicate ( v_o . into ( ) , v_r ) ) ) ; output_query_region_constraints . push ( ty :: Binder :: dummy ( ty :: OutlivesPredicate ( v_r . into ( ) , v_o ) ) ) ; } } ( UnpackedKind :: Type ( v1 ) , UnpackedKind :: Type ( v2 ) ) => { let ok = self . at ( cause , param_env ) . eq ( v1 , v2 ) ? ; obligations . extend ( ok . into_obligations ( ) ) ; } _ => { bug ! ( " " original_value result_value ) ; } } } // ...also include the other query region constraints from the query. output_query_region_constraints . reserve ( query_result . value . region_constraints . len ( ) ) ; for r_c in query_result . value . region_constraints . iter ( ) { let & ty :: OutlivesPredicate ( k1 , r2 ) = r_c . skip_binder ( ) ; // reconstructed below let k1 = substitute_value ( self . tcx , & result_subst , & k1 ) ; let r2 = substitute_value ( self . tcx , & result_subst , & r2 ) ; if k1 != r2 . into ( ) { output_query_region_constraints . push ( ty :: Binder :: bind ( ty :: OutlivesPredicate ( k1 , r2 ) ) ) ; } } let user_result : R = query_result . substitute_projected ( self . tcx , & result_subst , | q_r | & q_r . value ) ; Ok ( InferOk { value : user_result , obligations , } ) }
An alternative to
`instantiate_query_result_and_region_obligations` that is more
efficient for NLL.
An alternative to ` instantiate_query_result_and_region_obligations ` that is more efficient for NLL .
&self
cause
&ObligationCause<'tcx>
param_env
ty::ParamEnv<'tcx>
original_values
&SmallCanonicalVarValues<'tcx>
query_result
&Canonical<'tcx, QueryResult<'tcx, R>>
output_query_region_constraints
&mut Vec<QueryRegionConstraint<'tcx>>