about summary refs log tree commit diff
path: root/compiler/rustc_infer
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2025-08-27 09:42:09 +0200
committerlcnr <rust@lcnr.de>2025-09-08 14:17:56 +0200
commitf51458640840cb94c32f1e55431b1c855ca22e88 (patch)
tree96f0a77ec3555f183d2f49eb4689a9751d1332bc /compiler/rustc_infer
parent28a0e77d1318210540fa1a561b9a8af08e2ffe40 (diff)
downloadrust-f51458640840cb94c32f1e55431b1c855ca22e88.tar.gz
rust-f51458640840cb94c32f1e55431b1c855ca22e88.zip
optimize `CanonicalVarValues::instantiate`
Diffstat (limited to 'compiler/rustc_infer')
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs31
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs24
2 files changed, 18 insertions, 37 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 4e1ea52af4c..517331c3245 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -24,7 +24,7 @@
 pub use instantiate::CanonicalExt;
 use rustc_index::IndexVec;
 pub use rustc_middle::infer::canonical::*;
-use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 
 use crate::infer::{InferCtxt, RegionVariableOrigin};
@@ -67,29 +67,12 @@ impl<'tcx> InferCtxt<'tcx> {
             .chain((1..=canonical.max_universe.as_u32()).map(|_| self.create_next_universe()))
             .collect();
 
-        let canonical_inference_vars =
-            self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]);
-        let result = canonical.instantiate(self.tcx, &canonical_inference_vars);
-        (result, canonical_inference_vars)
-    }
-
-    /// Given the "infos" about the canonical variables from some
-    /// canonical, creates fresh variables with the same
-    /// characteristics (see `instantiate_canonical_var` for
-    /// details). You can then use `instantiate` to instantiate the
-    /// canonical variable with these inference variables.
-    fn instantiate_canonical_vars(
-        &self,
-        span: Span,
-        variables: &List<CanonicalVarKind<'tcx>>,
-        universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
-    ) -> CanonicalVarValues<'tcx> {
-        let mut var_values = Vec::with_capacity(variables.len());
-        for info in variables.iter() {
-            let value = self.instantiate_canonical_var(span, info, &var_values, &universe_map);
-            var_values.push(value);
-        }
-        CanonicalVarValues { var_values: self.tcx.mk_args(&var_values) }
+        let var_values =
+            CanonicalVarValues::instantiate(self.tcx, &canonical.variables, |var_values, info| {
+                self.instantiate_canonical_var(span, info, &var_values, |ui| universes[ui])
+            });
+        let result = canonical.instantiate(self.tcx, &var_values);
+        (result, var_values)
     }
 
     /// Given the "info" about a canonical variable, creates a fresh
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 22c9c4edccc..5d1b4be9e57 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -453,16 +453,17 @@ impl<'tcx> InferCtxt<'tcx> {
         // Create result arguments: if we found a value for a
         // given variable in the loop above, use that. Otherwise, use
         // a fresh inference variable.
-        let mut var_values = Vec::with_capacity(query_response.variables.len());
-        for (index, kind) in query_response.variables.iter().enumerate() {
-            let value = if kind.universe() != ty::UniverseIndex::ROOT {
+        let tcx = self.tcx;
+        let variables = query_response.variables;
+        let var_values = CanonicalVarValues::instantiate(tcx, variables, |var_values, kind| {
+            if kind.universe() != ty::UniverseIndex::ROOT {
                 // A variable from inside a binder of the query. While ideally these shouldn't
                 // exist at all, we have to deal with them for now.
                 self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
                     universe_map[u.as_usize()]
                 })
             } else if kind.is_existential() {
-                match opt_values[BoundVar::new(index)] {
+                match opt_values[BoundVar::new(var_values.len())] {
                     Some(k) => k,
                     None => self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
                         universe_map[u.as_usize()]
@@ -471,20 +472,17 @@ impl<'tcx> InferCtxt<'tcx> {
             } else {
                 // For placeholders which were already part of the input, we simply map this
                 // universal bound variable back the placeholder of the input.
-                opt_values[BoundVar::new(index)]
+                opt_values[BoundVar::new(var_values.len())]
                     .expect("expected placeholder to be unified with itself during response")
-            };
-            var_values.push(value);
-        }
-
-        let result_args = CanonicalVarValues { var_values: self.tcx.mk_args(&var_values) };
+            }
+        });
 
         let mut obligations = PredicateObligations::new();
 
         // Carry all newly resolved opaque types to the caller's scope
         for &(a, b) in &query_response.value.opaque_types {
-            let a = instantiate_value(self.tcx, &result_args, a);
-            let b = instantiate_value(self.tcx, &result_args, b);
+            let a = instantiate_value(self.tcx, &var_values, a);
+            let b = instantiate_value(self.tcx, &var_values, b);
             debug!(?a, ?b, "constrain opaque type");
             // We use equate here instead of, for example, just registering the
             // opaque type's hidden value directly, because the hidden type may have been an inference
@@ -501,7 +499,7 @@ impl<'tcx> InferCtxt<'tcx> {
             );
         }
 
-        Ok(InferOk { value: result_args, obligations })
+        Ok(InferOk { value: var_values, obligations })
     }
 
     /// Given a "guess" at the values for the canonical variables in