Skip to content

Rollup of 6 pull requests #141506

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 24, 2025
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
159 changes: 69 additions & 90 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ use tracing::debug;

use crate::infer::InferCtxt;
use crate::infer::canonical::{
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind,
OriginalQueryValues,
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarKind, OriginalQueryValues,
};

impl<'tcx> InferCtxt<'tcx> {
Expand Down Expand Up @@ -174,10 +173,8 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
match r.kind() {
ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,

ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
r,
),
ty::RePlaceholder(placeholder) => canonicalizer
.canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r),

ty::ReVar(vid) => {
let universe = infcx
Expand All @@ -186,10 +183,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
.unwrap_region_constraints()
.probe_value(vid)
.unwrap_err();
canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) },
r,
)
canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r)
}

_ => {
Expand Down Expand Up @@ -294,7 +288,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<[CanonicalVarInfo<'tcx>; 8]>,
variables: 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 @@ -368,9 +362,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
ui = ty::UniverseIndex::ROOT;
}
self.canonicalize_ty_var(
CanonicalVarInfo {
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
},
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
t,
)
}
Expand All @@ -382,21 +374,15 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) },
t,
)
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
}
}
ty::Infer(ty::FloatVar(vid)) => {
let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid);
if nt != t {
return self.fold_ty(nt);
} else {
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) },
t,
)
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t)
}
}

Expand All @@ -408,10 +394,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
if !self.canonicalize_mode.preserve_universes() {
placeholder.universe = ty::UniverseIndex::ROOT;
}
self.canonicalize_ty_var(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) },
t,
)
self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
}

ty::Bound(debruijn, _) => {
Expand Down Expand Up @@ -483,10 +466,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
// FIXME: perf problem described in #55921.
ui = ty::UniverseIndex::ROOT;
}
return self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) },
ct,
);
return self.canonicalize_const_var(CanonicalVarKind::Const(ui), ct);
}
}
}
Expand All @@ -501,10 +481,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
}
ty::ConstKind::Placeholder(placeholder) => {
return self.canonicalize_const_var(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) },
ct,
);
return self
.canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct);
}
_ => {}
}
Expand Down Expand Up @@ -595,7 +573,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());

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

let max_universe = canonical_variables
.iter()
Expand All @@ -610,18 +588,22 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// or returns an existing variable if `kind` has already been
/// seen. `kind` is expected to be an unbound variable (or
/// potentially a free region).
fn canonical_var(&mut self, info: CanonicalVarInfo<'tcx>, kind: GenericArg<'tcx>) -> BoundVar {
fn canonical_var(
&mut self,
var_kind: CanonicalVarKind<'tcx>,
value: GenericArg<'tcx>,
) -> BoundVar {
let Canonicalizer { variables, query_state, indices, .. } = self;

let var_values = &mut query_state.var_values;

let universe = info.universe();
let universe = var_kind.universe();
if universe != ty::UniverseIndex::ROOT {
assert!(self.canonicalize_mode.preserve_universes());

// Insert universe into the universe map. To preserve the order of the
// universes in the value being canonicalized, we don't update the
// universe in `info` until we have finished canonicalizing.
// universe in `var_kind` until we have finished canonicalizing.
match query_state.universe_map.binary_search(&universe) {
Err(idx) => query_state.universe_map.insert(idx, universe),
Ok(_) => {}
Expand All @@ -636,14 +618,14 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
if !var_values.spilled() {
// `var_values` is stack-allocated. `indices` isn't used yet. Do a
// direct linear search of `var_values`.
if let Some(idx) = var_values.iter().position(|&k| k == kind) {
if let Some(idx) = var_values.iter().position(|&v| v == value) {
// `kind` is already present in `var_values`.
BoundVar::new(idx)
} else {
// `kind` isn't present in `var_values`. Append it. Likewise
// for `info` and `variables`.
variables.push(info);
var_values.push(kind);
// for `var_kind` and `variables`.
variables.push(var_kind);
var_values.push(value);
assert_eq!(variables.len(), var_values.len());

// If `var_values` has become big enough to be heap-allocated,
Expand All @@ -653,17 +635,17 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
*indices = var_values
.iter()
.enumerate()
.map(|(i, &kind)| (kind, BoundVar::new(i)))
.map(|(i, &value)| (value, BoundVar::new(i)))
.collect();
}
// The cv is the index of the appended element.
BoundVar::new(var_values.len() - 1)
}
} else {
// `var_values` is large. Do a hashmap search via `indices`.
*indices.entry(kind).or_insert_with(|| {
variables.push(info);
var_values.push(kind);
*indices.entry(value).or_insert_with(|| {
variables.push(var_kind);
var_values.push(value);
assert_eq!(variables.len(), var_values.len());
BoundVar::new(variables.len() - 1)
})
Expand All @@ -673,7 +655,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// 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<[CanonicalVarInfo<'tcx>; 8]> {
fn universe_canonicalized_variables(self) -> SmallVec<[CanonicalVarKind<'tcx>; 8]> {
if self.query_state.universe_map.len() == 1 {
return self.variables;
}
Expand All @@ -688,37 +670,33 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {

self.variables
.iter()
.map(|v| CanonicalVarInfo {
kind: match v.kind {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
return *v;
}
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
}
CanonicalVarKind::Region(u) => {
CanonicalVarKind::Region(reverse_universe_map[&u])
}
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
CanonicalVarKind::PlaceholderTy(placeholder) => {
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
CanonicalVarKind::PlaceholderRegion(placeholder) => {
CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
CanonicalVarKind::PlaceholderConst(placeholder) => {
CanonicalVarKind::PlaceholderConst(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
},
.map(|&kind| match kind {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
return kind;
}
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
}
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
CanonicalVarKind::PlaceholderTy(placeholder) => {
CanonicalVarKind::PlaceholderTy(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
CanonicalVarKind::PlaceholderRegion(placeholder) => {
CanonicalVarKind::PlaceholderRegion(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
CanonicalVarKind::PlaceholderConst(placeholder) => {
CanonicalVarKind::PlaceholderConst(ty::Placeholder {
universe: reverse_universe_map[&placeholder.universe],
..placeholder
})
}
})
.collect()
}
Expand All @@ -740,20 +718,17 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
&mut self,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
self.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::Region(ty::UniverseIndex::ROOT) },
r,
)
self.canonical_var_for_region(CanonicalVarKind::Region(ty::UniverseIndex::ROOT), r)
}

/// Creates a canonical variable (with the given `info`)
/// representing the region `r`; return a region referencing it.
fn canonical_var_for_region(
&mut self,
info: CanonicalVarInfo<'tcx>,
var_kind: CanonicalVarKind<'tcx>,
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
let var = self.canonical_var(info, r.into());
let var = self.canonical_var(var_kind, r.into());
let br = ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon };
ty::Region::new_bound(self.cx(), self.binder_index, br)
}
Expand All @@ -762,9 +737,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// if `ty_var` is bound to anything; if so, canonicalize
/// *that*. Otherwise, create a new canonical variable for
/// `ty_var`.
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo<'tcx>, ty_var: Ty<'tcx>) -> Ty<'tcx> {
fn canonicalize_ty_var(
&mut self,
var_kind: CanonicalVarKind<'tcx>,
ty_var: Ty<'tcx>,
) -> Ty<'tcx> {
debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var)));
let var = self.canonical_var(info, ty_var.into());
let var = self.canonical_var(var_kind, ty_var.into());
Ty::new_bound(self.tcx, self.binder_index, var.into())
}

Expand All @@ -774,13 +753,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// `const_var`.
fn canonicalize_const_var(
&mut self,
info: CanonicalVarInfo<'tcx>,
const_var: ty::Const<'tcx>,
var_kind: CanonicalVarKind<'tcx>,
ct_var: ty::Const<'tcx>,
) -> ty::Const<'tcx> {
debug_assert!(
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
!self.infcx.is_some_and(|infcx| ct_var != infcx.shallow_resolve_const(ct_var))
);
let var = self.canonical_var(info, const_var.into());
let var = self.canonical_var(var_kind, ct_var.into());
ty::Const::new_bound(self.tcx, self.binder_index, var)
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_infer/src/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ impl<'tcx> InferCtxt<'tcx> {
fn instantiate_canonical_vars(
&self,
span: Span,
variables: &List<CanonicalVarInfo<'tcx>>,
variables: &List<CanonicalVarKind<'tcx>>,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> CanonicalVarValues<'tcx> {
CanonicalVarValues {
var_values: self.tcx.mk_args_from_iter(
variables
.iter()
.map(|info| self.instantiate_canonical_var(span, info, &universe_map)),
.map(|kind| self.instantiate_canonical_var(span, kind, &universe_map)),
),
}
}
Expand All @@ -104,10 +104,10 @@ impl<'tcx> InferCtxt<'tcx> {
pub fn instantiate_canonical_var(
&self,
span: Span,
cv_info: CanonicalVarInfo<'tcx>,
kind: CanonicalVarKind<'tcx>,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> GenericArg<'tcx> {
match cv_info.kind {
match kind {
CanonicalVarKind::Ty(ty_kind) => {
let ty = match ty_kind {
CanonicalTyVarKind::General(ui) => {
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,17 +445,17 @@ impl<'tcx> InferCtxt<'tcx> {
// a fresh inference variable.
let result_args = CanonicalVarValues {
var_values: self.tcx.mk_args_from_iter(
query_response.variables.iter().enumerate().map(|(index, info)| {
if info.universe() != ty::UniverseIndex::ROOT {
query_response.variables.iter().enumerate().map(|(index, var_kind)| {
if var_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, info, |u| {
self.instantiate_canonical_var(cause.span, var_kind, |u| {
universe_map[u.as_usize()]
})
} else if info.is_existential() {
} else if var_kind.is_existential() {
match opt_values[BoundVar::new(index)] {
Some(k) => k,
None => self.instantiate_canonical_var(cause.span, info, |u| {
None => self.instantiate_canonical_var(cause.span, var_kind, |u| {
universe_map[u.as_usize()]
}),
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
pub use rustc_type_ir as ir;
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
pub use rustc_type_ir::CanonicalTyVarKind;
use smallvec::SmallVec;

use crate::mir::ConstraintCategory;
use crate::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};

pub type CanonicalQueryInput<'tcx, V> = ir::CanonicalQueryInput<TyCtxt<'tcx>, V>;
pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
pub type CanonicalVarKind<'tcx> = ir::CanonicalVarKind<TyCtxt<'tcx>>;
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
pub type CanonicalVarKinds<'tcx> = &'tcx List<CanonicalVarKind<'tcx>>;

/// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores
Expand Down
Loading
Loading