Skip to content

Replace CanonicalVar with DebruijnIndex #52984

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 2 commits into from
Oct 21, 2018
Merged
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
4 changes: 2 additions & 2 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionVid {
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::CanonicalVar {
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundTyIndex {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
@@ -915,7 +915,7 @@ impl_stable_hash_for!(enum ty::InferTy {
FreshTy(a),
FreshIntTy(a),
FreshFloatTy(a),
CanonicalTy(a),
BoundTy(a),
});

impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
33 changes: 20 additions & 13 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ use infer::InferCtxt;
use std::sync::atomic::Ordering;
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::Kind;
use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt, TypeFlags};
use ty::{self, BoundTy, BoundTyIndex, Lift, List, Ty, TyCtxt, TypeFlags};

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
@@ -225,7 +225,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
query_state: &'cx mut OriginalQueryValues<'tcx>,
// Note that indices is only used once `var_values` is big enough to be
// heap-allocated.
indices: FxHashMap<Kind<'tcx>, CanonicalVar>,
indices: FxHashMap<Kind<'tcx>, BoundTyIndex>,
canonicalize_region_mode: &'cx dyn CanonicalizeRegionMode,
needs_canonical_flags: TypeFlags,
}
@@ -283,7 +283,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
bug!("encountered a fresh type during canonicalization")
}

ty::Infer(ty::CanonicalTy(_)) => {
ty::Infer(ty::BoundTy(_)) => {
bug!("encountered a canonical type during canonicalization")
}

@@ -393,7 +393,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, '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, kind: Kind<'tcx>) -> CanonicalVar {
fn canonical_var(&mut self, info: CanonicalVarInfo, kind: Kind<'tcx>) -> BoundTy {
let Canonicalizer {
variables,
query_state,
@@ -408,12 +408,12 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
// 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
// been exceeded, to also avoid allocations for `indices`.
if !var_values.spilled() {
let var = 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) {
// `kind` is already present in `var_values`.
CanonicalVar::new(idx)
BoundTyIndex::new(idx)
} else {
// `kind` isn't present in `var_values`. Append it. Likewise
// for `info` and `variables`.
@@ -428,29 +428,35 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
*indices = var_values
.iter()
.enumerate()
.map(|(i, &kind)| (kind, CanonicalVar::new(i)))
.map(|(i, &kind)| (kind, BoundTyIndex::new(i)))
.collect();
}
// The cv is the index of the appended element.
CanonicalVar::new(var_values.len() - 1)
BoundTyIndex::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);
assert_eq!(variables.len(), var_values.len());
CanonicalVar::new(variables.len() - 1)
BoundTyIndex::new(variables.len() - 1)
})
};

BoundTy {
level: ty::INNERMOST,
var,
}
}

fn canonical_var_for_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Region,
};
let cvar = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(cvar))
let b = self.canonical_var(info, r.into());
debug_assert_eq!(ty::INNERMOST, b.level);
self.tcx().mk_region(ty::ReCanonical(b.var))
}

/// Given a type variable `ty_var` of the given kind, first check
@@ -466,8 +472,9 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
let info = CanonicalVarInfo {
kind: CanonicalVarKind::Ty(ty_kind),
};
let cvar = self.canonical_var(info, ty_var.into());
self.tcx().mk_infer(ty::InferTy::CanonicalTy(cvar))
let b = self.canonical_var(info, ty_var.into());
debug_assert_eq!(ty::INNERMOST, b.level);
self.tcx().mk_infer(ty::InferTy::BoundTy(b))
}
}
}
10 changes: 5 additions & 5 deletions src/librustc/infer/canonical/mod.rs
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ use std::ops::Index;
use syntax::source_map::Span;
use ty::fold::TypeFoldable;
use ty::subst::Kind;
use ty::{self, CanonicalVar, Lift, Region, List, TyCtxt};
use ty::{self, BoundTyIndex, Lift, Region, List, TyCtxt};

mod canonicalizer;

@@ -72,7 +72,7 @@ impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
/// canonicalized query response.
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
pub struct CanonicalVarValues<'tcx> {
pub var_values: IndexVec<CanonicalVar, Kind<'tcx>>,
pub var_values: IndexVec<BoundTyIndex, Kind<'tcx>>,
}

/// When we canonicalize a value to form a query, we wind up replacing
@@ -264,7 +264,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
span: Span,
variables: &List<CanonicalVarInfo>,
) -> CanonicalVarValues<'tcx> {
let var_values: IndexVec<CanonicalVar, Kind<'tcx>> = variables
let var_values: IndexVec<BoundTyIndex, Kind<'tcx>> = variables
.iter()
.map(|info| self.fresh_inference_var_for_canonical_var(span, *info))
.collect();
@@ -367,10 +367,10 @@ BraceStructLiftImpl! {
} where R: Lift<'tcx>
}

impl<'tcx> Index<CanonicalVar> for CanonicalVarValues<'tcx> {
impl<'tcx> Index<BoundTyIndex> for CanonicalVarValues<'tcx> {
type Output = Kind<'tcx>;

fn index(&self, value: CanonicalVar) -> &Kind<'tcx> {
fn index(&self, value: BoundTyIndex) -> &Kind<'tcx> {
&self.var_values[value]
}
}
18 changes: 9 additions & 9 deletions src/librustc/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ use traits::{FulfillmentContext, TraitEngine};
use traits::{Obligation, ObligationCause, PredicateObligation};
use ty::fold::TypeFoldable;
use ty::subst::{Kind, UnpackedKind};
use ty::{self, CanonicalVar, Lift, Ty, TyCtxt};
use ty::{self, BoundTyIndex, Lift, Ty, TyCtxt};

impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> {
/// The "main method" for a canonicalized trait query. Given the
@@ -273,7 +273,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
for (index, original_value) in original_values.var_values.iter().enumerate() {
// ...with the value `v_r` of that variable from the query.
let result_value = query_response.substitute_projected(self.tcx, &result_subst, |v| {
&v.var_values[CanonicalVar::new(index)]
&v.var_values[BoundTyIndex::new(index)]
});
match (original_value.unpack(), result_value.unpack()) {
(UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
@@ -408,7 +408,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// is directly equal to one of the canonical variables in the
// result, then we can type the corresponding value from the
// input. See the example above.
let mut opt_values: IndexVec<CanonicalVar, Option<Kind<'tcx>>> =
let mut opt_values: IndexVec<BoundTyIndex, Option<Kind<'tcx>>> =
IndexVec::from_elem_n(None, query_response.variables.len());

// In terms of our example above, we are iterating over pairs like:
@@ -417,9 +417,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
match result_value.unpack() {
UnpackedKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above...
if let ty::Infer(ty::InferTy::CanonicalTy(index)) = result_value.sty {
if let ty::Infer(ty::InferTy::BoundTy(b)) = result_value.sty {
// in which case we would set `canonical_vars[0]` to `Some(?U)`.
opt_values[index] = Some(*original_value);
opt_values[b.var] = Some(*original_value);
}
}
UnpackedKind::Lifetime(result_value) => {
@@ -440,7 +440,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
.variables
.iter()
.enumerate()
.map(|(index, info)| opt_values[CanonicalVar::new(index)].unwrap_or_else(||
.map(|(index, info)| opt_values[BoundTyIndex::new(index)].unwrap_or_else(||
self.fresh_inference_var_for_canonical_var(cause.span, *info)
))
.collect(),
@@ -470,7 +470,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// canonical variable; this is taken from
// `query_response.var_values` after applying the substitution
// `result_subst`.
let substituted_query_response = |index: CanonicalVar| -> Kind<'tcx> {
let substituted_query_response = |index: BoundTyIndex| -> Kind<'tcx> {
query_response.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
};

@@ -526,12 +526,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
variables1: &OriginalQueryValues<'tcx>,
variables2: impl Fn(CanonicalVar) -> Kind<'tcx>,
variables2: impl Fn(BoundTyIndex) -> Kind<'tcx>,
) -> InferResult<'tcx, ()> {
self.commit_if_ok(|_| {
let mut obligations = vec![];
for (index, value1) in variables1.var_values.iter().enumerate() {
let value2 = variables2(CanonicalVar::new(index));
let value2 = variables2(BoundTyIndex::new(index));

match (value1.unpack(), value2.unpack()) {
(UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
7 changes: 4 additions & 3 deletions src/librustc/infer/canonical/substitute.rs
Original file line number Diff line number Diff line change
@@ -85,10 +85,11 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g

fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.sty {
ty::Infer(ty::InferTy::CanonicalTy(c)) => {
match self.var_values.var_values[c].unpack() {
ty::Infer(ty::InferTy::BoundTy(b)) => {
debug_assert_eq!(ty::INNERMOST, b.level);
match self.var_values.var_values[b.var].unpack() {
UnpackedKind::Type(ty) => ty,
r => bug!("{:?} is a type but value is {:?}", c, r),
r => bug!("{:?} is a type but value is {:?}", b, r),
}
}
_ => {
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
@@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
t
}

ty::Infer(ty::CanonicalTy(..)) =>
ty::Infer(ty::BoundTy(..)) =>
bug!("encountered canonical ty during freshening"),

ty::Generator(..) |
6 changes: 3 additions & 3 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
@@ -2421,7 +2421,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::Infer(ty::TyVar(_)) => Ambiguous,

ty::UnnormalizedProjection(..)
| ty::Infer(ty::CanonicalTy(_))
| ty::Infer(ty::BoundTy(_))
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2506,7 +2506,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}

ty::UnnormalizedProjection(..)
| ty::Infer(ty::CanonicalTy(_))
| ty::Infer(ty::BoundTy(_))
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
| ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2549,7 +2549,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
| ty::Param(..)
| ty::Foreign(..)
| ty::Projection(..)
| ty::Infer(ty::CanonicalTy(_))
| ty::Infer(ty::BoundTy(_))
| ty::Infer(ty::TyVar(_))
| ty::Infer(ty::FreshTy(_))
| ty::Infer(ty::FreshIntTy(_))
2 changes: 1 addition & 1 deletion src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
@@ -217,7 +217,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::Infer(ty::TyVar(_)) => "inferred type".into(),
ty::Infer(ty::IntVar(_)) => "integral variable".into(),
ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
ty::Infer(ty::CanonicalTy(_)) |
ty::Infer(ty::BoundTy(_)) |
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
2 changes: 1 addition & 1 deletion src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
@@ -122,7 +122,7 @@ impl FlagComputation {
ty::FreshTy(_) |
ty::FreshIntTy(_) |
ty::FreshFloatTy(_) |
ty::CanonicalTy(_) => {
ty::BoundTy(_) => {
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
}

2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,

use hir;

pub use self::sty::{Binder, CanonicalVar, DebruijnIndex, INNERMOST};
pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
pub use self::sty::{FnSig, GenSig, PolyFnSig, PolyGenSig};
pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
18 changes: 13 additions & 5 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -1165,7 +1165,7 @@ pub enum RegionKind {
ReClosureBound(RegionVid),

/// Canonicalized region, used only when preparing a trait query.
ReCanonical(CanonicalVar),
ReCanonical(BoundTyIndex),
}

impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@@ -1217,14 +1217,22 @@ pub enum InferTy {
FreshIntTy(u32),
FreshFloatTy(u32),

/// Canonicalized type variable, used only when preparing a trait query.
CanonicalTy(CanonicalVar),
/// Bound type variable, used only when preparing a trait query.
BoundTy(BoundTy),
}

newtype_index! {
pub struct CanonicalVar { .. }
pub struct BoundTyIndex { .. }
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct BoundTy {
pub level: DebruijnIndex,
pub var: BoundTyIndex,
}

impl_stable_hash_for!(struct BoundTy { level, var });

/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ExistentialProjection<'tcx> {
@@ -1919,7 +1927,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {

ty::Infer(ty::TyVar(_)) => false,

ty::Infer(ty::CanonicalTy(_)) |
ty::Infer(ty::BoundTy(_)) |
ty::Infer(ty::FreshTy(_)) |
ty::Infer(ty::FreshIntTy(_)) |
ty::Infer(ty::FreshFloatTy(_)) =>
6 changes: 3 additions & 3 deletions src/librustc/ty/subst.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@

use hir::def_id::DefId;
use infer::canonical::Canonical;
use ty::{self, CanonicalVar, Lift, List, Ty, TyCtxt};
use ty::{self, BoundTyIndex, Lift, List, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};

use serialize::{self, Encodable, Encoder, Decodable, Decoder};
@@ -553,10 +553,10 @@ impl CanonicalUserSubsts<'tcx> {
return false;
}

self.value.substs.iter().zip(CanonicalVar::new(0)..).all(|(kind, cvar)| {
self.value.substs.iter().zip(BoundTyIndex::new(0)..).all(|(kind, cvar)| {
match kind.unpack() {
UnpackedKind::Type(ty) => match ty.sty {
ty::Infer(ty::CanonicalTy(cvar1)) => cvar == cvar1,
ty::Infer(ty::BoundTy(ref b)) => cvar == b.var,
_ => false,
},

4 changes: 2 additions & 2 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
@@ -984,7 +984,7 @@ define_print! {
ty::TyVar(_) => write!(f, "_"),
ty::IntVar(_) => write!(f, "{}", "{integer}"),
ty::FloatVar(_) => write!(f, "{}", "{float}"),
ty::CanonicalTy(_) => write!(f, "_"),
ty::BoundTy(_) => write!(f, "_"),
ty::FreshTy(v) => write!(f, "FreshTy({})", v),
ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
@@ -996,7 +996,7 @@ define_print! {
ty::TyVar(ref v) => write!(f, "{:?}", v),
ty::IntVar(ref v) => write!(f, "{:?}", v),
ty::FloatVar(ref v) => write!(f, "{:?}", v),
ty::CanonicalTy(v) => write!(f, "?{:?}", v.index()),
ty::BoundTy(v) => write!(f, "?{:?}", v.var.index()),
ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)