Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ struct Canonicalizer<'cx, 'tcx> {
/// Set to `None` to disable the resolution of inference variables.
infcx: Option<&'cx InferCtxt<'tcx>>,
tcx: TyCtxt<'tcx>,
variables: SmallVec<[CanonicalVarKind<'tcx>; 8]>,
var_kinds: SmallVec<[CanonicalVarKind<'tcx>; 8]>,
query_state: &'cx mut OriginalQueryValues<'tcx>,
// Note that indices is only used once `var_values` is big enough to be
// heap-allocated.
Expand Down Expand Up @@ -507,7 +507,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
{
let base = Canonical {
max_universe: ty::UniverseIndex::ROOT,
variables: List::empty(),
var_kinds: List::empty(),
value: (),
};
Canonicalizer::canonicalize_with_base(
Expand Down Expand Up @@ -548,7 +548,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
tcx,
canonicalize_mode: canonicalize_region_mode,
needs_canonical_flags,
variables: SmallVec::from_slice(base.variables),
var_kinds: SmallVec::from_slice(base.var_kinds),
query_state,
indices: FxHashMap::default(),
sub_root_lookup_table: Default::default(),
Expand All @@ -569,16 +569,16 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
// anymore.
debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());

let canonical_variables =
tcx.mk_canonical_var_kinds(&canonicalizer.universe_canonicalized_variables());
let canonical_var_kinds =
tcx.mk_canonical_var_kinds(&canonicalizer.universe_canonicalized_var_kinds());

let max_universe = canonical_variables
let max_universe = canonical_var_kinds
.iter()
.map(|cvar| cvar.universe())
.max()
.unwrap_or(ty::UniverseIndex::ROOT);

Canonical { max_universe, variables: canonical_variables, value: (base.value, out_value) }
Canonical { max_universe, var_kinds: canonical_var_kinds, value: (base.value, out_value) }
}

/// Creates a canonical variable replacing `kind` from the input,
Expand All @@ -590,7 +590,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
var_kind: CanonicalVarKind<'tcx>,
value: GenericArg<'tcx>,
) -> BoundVar {
let Canonicalizer { variables, query_state, indices, .. } = self;
let Canonicalizer { var_kinds, query_state, indices, .. } = self;

let var_values = &mut query_state.var_values;

Expand All @@ -607,7 +607,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
}
}

// This code is hot. `variables` and `var_values` are usually small
// This code is hot. `var_kinds` and `var_values` are usually small
// (fewer than 8 elements ~95% of the time). They are SmallVec's to
// avoid allocations in those cases. We also don't use `indices` to
// determine if a kind has been seen before until the limit of 8 has
Expand All @@ -620,10 +620,10 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
BoundVar::new(idx)
} else {
// `kind` isn't present in `var_values`. Append it. Likewise
// for `var_kind` and `variables`.
variables.push(var_kind);
// for `var_kind` and `var_kinds`.
var_kinds.push(var_kind);
var_values.push(value);
assert_eq!(variables.len(), var_values.len());
assert_eq!(var_kinds.len(), var_values.len());

// If `var_values` has become big enough to be heap-allocated,
// fill up `indices` to facilitate subsequent lookups.
Expand All @@ -641,27 +641,27 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
} else {
// `var_values` is large. Do a hashmap search via `indices`.
*indices.entry(value).or_insert_with(|| {
variables.push(var_kind);
var_kinds.push(var_kind);
var_values.push(value);
assert_eq!(variables.len(), var_values.len());
BoundVar::new(variables.len() - 1)
assert_eq!(var_kinds.len(), var_values.len());
BoundVar::new(var_kinds.len() - 1)
})
}
}

fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
let root_vid = self.infcx.unwrap().sub_unification_table_root_var(vid);
let idx =
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.var_kinds.len());
ty::BoundVar::from(idx)
}

/// Replaces the universe indexes used in `var_values` with their index in
/// `query_state.universe_map`. This minimizes the maximum universe used in
/// the canonicalized value.
fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarKind<'tcx>; 8]> {
fn universe_canonicalized_var_kinds(self) -> SmallVec<[CanonicalVarKind<'tcx>; 8]> {
if self.query_state.universe_map.len() == 1 {
return self.variables;
return self.var_kinds;
}

let reverse_universe_map: FxHashMap<ty::UniverseIndex, ty::UniverseIndex> = self
Expand All @@ -672,7 +672,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
.map(|(idx, universe)| (*universe, ty::UniverseIndex::from_usize(idx)))
.collect();

self.variables
self.var_kinds
.iter()
.map(|&kind| match kind {
CanonicalVarKind::Int | CanonicalVarKind::Float => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/canonical/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<'tcx, V> Canonical<'tcx, V> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
assert_eq!(self.variables.len(), var_values.len());
assert_eq!(self.var_kinds.len(), var_values.len());
let value = projection_fn(&self.value);
instantiate_value(tcx, var_values, value)
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl<'tcx> InferCtxt<'tcx> {
.collect();

let var_values =
CanonicalVarValues::instantiate(self.tcx, &canonical.variables, |var_values, info| {
CanonicalVarValues::instantiate(self.tcx, &canonical.var_kinds, |var_values, info| {
self.instantiate_canonical_var(span, info, &var_values, |ui| universes[ui])
});
let result = canonical.instantiate(self.tcx, &var_values);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl<'tcx> InferCtxt<'tcx> {
// result, then we can type the corresponding value from the
// input. See the example above.
let mut opt_values: IndexVec<BoundVar, Option<GenericArg<'tcx>>> =
IndexVec::from_elem_n(None, query_response.variables.len());
IndexVec::from_elem_n(None, query_response.var_kinds.len());

for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
{
Expand All @@ -442,7 +442,7 @@ impl<'tcx> InferCtxt<'tcx> {
// more involved. They are also a lot rarer than region variables.
if let ty::Bound(index_kind, b) = *result_value.kind()
&& !matches!(
query_response.variables[b.var.as_usize()],
query_response.var_kinds[b.var.as_usize()],
CanonicalVarKind::Ty { .. }
)
{
Expand Down Expand Up @@ -472,8 +472,8 @@ impl<'tcx> InferCtxt<'tcx> {
// given variable in the loop above, use that. Otherwise, use
// a fresh inference variable.
let tcx = self.tcx;
let variables = query_response.variables;
let var_values = CanonicalVarValues::instantiate(tcx, variables, |var_values, kind| {
let var_kinds = query_response.var_kinds;
let var_values = CanonicalVarValues::instantiate(tcx, var_kinds, |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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ impl<'tcx> CanonicalParamEnvCache<'tcx> {
) {
return Canonical {
max_universe: ty::UniverseIndex::ROOT,
variables: List::empty(),
var_kinds: List::empty(),
value: key,
};
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,18 +586,26 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
self,
folder: &mut F,
) -> Result<Self, F::Error> {
// This method looks different to `Ty::try_super_fold_with` and `Const::super_fold_with`.
// Why is that? `PredicateKind` provides little scope for optimized folding, unlike
// `TyKind` and `ConstKind` (which have common variants that don't require recursive
// `fold_with` calls on their fields). So we just derive the `TypeFoldable` impl for
// `PredicateKind` and call it here because the derived code is as fast as hand-written
// code would be.
let new = self.kind().try_fold_with(folder)?;
Ok(folder.cx().reuse_or_mk_predicate(self, new))
}

fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
// See comment in `Predicate::try_super_fold_with`.
let new = self.kind().fold_with(folder);
folder.cx().reuse_or_mk_predicate(self, new)
}
}

impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
// See comment in `Predicate::try_super_fold_with`.
self.kind().visit_with(visitor)
}
}
Expand Down
Loading
Loading