From d57fdcfd291a2b1597637b01ee41bab0a05168a4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Jan 2022 17:31:27 +0000 Subject: [PATCH] Allocate one vec, instead of one per invocation --- .../src/infer/canonical/query_response.rs | 14 +++++------ .../src/traits/query/type_op/mod.rs | 24 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 5b4a9d9dfad45..505b3fd0955ff 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -14,10 +14,10 @@ use crate::infer::canonical::{ }; use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; -use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; +use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin, TypeError}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::TraitEngine; -use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{Obligation, ObligationCause, PredicateObligation, PredicateObligations}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; @@ -219,7 +219,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { original_values: &OriginalQueryValues<'tcx>, query_response: &Canonical<'tcx, QueryResponse<'tcx, R>>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, - ) -> InferResult<'tcx, R> + obligations: &mut PredicateObligations<'tcx> + ) -> Result> where R: Debug + TypeFoldable<'tcx>, { @@ -229,7 +230,6 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Compute `QueryOutlivesConstraint` 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.var_values.iter().enumerate() { // ...with the value `v_r` of that variable from the query. @@ -263,7 +263,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { infcx: self, param_env, cause, - obligations: &mut obligations, + obligations: &mut *obligations, }, ty::Variance::Invariant, ) @@ -277,7 +277,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { infcx: self, param_env, cause, - obligations: &mut obligations, + obligations: &mut *obligations, }, ty::Variance::Invariant, ) @@ -316,7 +316,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { let user_result: R = query_response.substitute_projected(self.tcx, &result_subst, |q_r| q_r.value.clone()); - Ok(InferOk { value: user_result, obligations }) + Ok(user_result) } /// Given the original values and the (canonicalized) result from diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index d662f61e2cf4d..683949b00be36 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -1,7 +1,7 @@ use crate::infer::canonical::{ Canonicalized, CanonicalizedQueryResponse, OriginalQueryValues, QueryRegionConstraints, }; -use crate::infer::{InferCtxt, InferOk}; +use crate::infer::{InferCtxt}; use crate::traits::query::Fallible; use crate::traits::ObligationCause; use rustc_infer::infer::canonical::{Canonical, Certainty}; @@ -81,14 +81,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx { query_key: ParamEnvAnd<'tcx, Self>, infcx: &InferCtxt<'_, 'tcx>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, + obligations: &mut PredicateObligations<'tcx>, ) -> Fallible<( Self::QueryResponse, Option>>, - PredicateObligations<'tcx>, Certainty, )> { if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { - return Ok((result, None, vec![], Certainty::Proven)); + return Ok((result, None, Certainty::Proven)); } // FIXME(#33684) -- We need to use @@ -101,16 +101,17 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx { infcx.canonicalize_query_keep_static(query_key, &mut canonical_var_values); let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?; - let InferOk { value, obligations } = infcx + let value = infcx .instantiate_nll_query_response_and_region_obligations( &ObligationCause::dummy(), old_param_env, &canonical_var_values, canonical_result, output_query_region_constraints, + obligations, )?; - Ok((value, Some(canonical_self), obligations, canonical_result.value.certainty)) + Ok((value, Some(canonical_self), canonical_result.value.certainty)) } } @@ -122,8 +123,9 @@ where fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible> { let mut region_constraints = QueryRegionConstraints::default(); - let (output, canonicalized_query, mut obligations, _) = - Q::fully_perform_into(self, infcx, &mut region_constraints)?; + let mut obligations = Vec::new(); + let (output, canonicalized_query, _) = + Q::fully_perform_into(self, infcx, &mut region_constraints, &mut obligations)?; // Typically, instantiating NLL query results does not // create obligations. However, in some cases there @@ -133,15 +135,15 @@ where while !obligations.is_empty() { trace!("{:#?}", obligations); let mut progress = false; - for obligation in std::mem::take(&mut obligations) { - let obligation = infcx.resolve_vars_if_possible(obligation); + for _ in 0..obligations.len() { + let obligation = infcx.resolve_vars_if_possible(obligations.swap_remove(0)); match ProvePredicate::fully_perform_into( obligation.param_env.and(ProvePredicate::new(obligation.predicate)), infcx, &mut region_constraints, + &mut obligations, ) { - Ok(((), _, new, certainty)) => { - obligations.extend(new); + Ok(((), _, certainty)) => { progress = true; if let Certainty::Ambiguous = certainty { obligations.push(obligation);