Skip to content
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

Replace CanonicalVar with DebruijnIndex #52984

Merged
merged 2 commits into from
Oct 21, 2018
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
4 changes: 2 additions & 2 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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>>
Expand Down
33 changes: 20 additions & 13 deletions src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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")
}

Expand Down Expand Up @@ -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,
Expand All @@ -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`.
Expand All @@ -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
Expand All @@ -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
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Up @@ -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
Expand Down Expand Up @@ -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)) => {
Expand Down Expand Up @@ -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:
Expand All @@ -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) => {
Expand All @@ -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(),
Expand Down Expand Up @@ -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])
};

Expand Down Expand Up @@ -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)) => {
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/infer/canonical/substitute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}
}
_ => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(_)) => {
Expand Down Expand Up @@ -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(_)) => {
Expand Down Expand Up @@ -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(_))
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl FlagComputation {
ty::FreshTy(_) |
ty::FreshIntTy(_) |
ty::FreshFloatTy(_) |
ty::CanonicalTy(_) => {
ty::BoundTy(_) => {
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
18 changes: 13 additions & 5 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {}
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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(_)) =>
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
},

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/util/ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down