optimize CanonicalVarValues::instantiate

This commit is contained in:
lcnr 2025-08-27 09:42:09 +02:00
parent 28a0e77d13
commit f514586408
9 changed files with 63 additions and 56 deletions

View file

@ -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

View file

@ -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