--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Freshening is the process of replacing unknown variables with fresh types. The idea is that
+//! the type, after freshening, contains no inference variables but instead contains either a
+//! value for each variable or fresh "arbitrary" types wherever a variable would have been.
+//!
+//! Freshening is used primarily to get a good type for inserting into a cache. The result
+//! summarizes what the type inferencer knows "so far". The primary place it is used right now is
+//! in the trait matching algorithm, which needs to be able to cache whether an `impl` self type
+//! matches some other type X -- *without* affecting `X`. That means if that if the type `X` is in
+//! fact an unbound type variable, we want the match to be regarded as ambiguous, because depending
+//! on what type that type variable is ultimately assigned, the match may or may not succeed.
+//!
+//! Note that you should be careful not to allow the output of freshening to leak to the user in
+//! error messages or in any other form. Freshening is only really useful as an internal detail.
+//!
+//! __An important detail concerning regions.__ The freshener also replaces *all* regions with
+//! 'static. The reason behind this is that, in general, we do not take region relationships into
+//! account when making type-overloaded decisions. This is important because of the design of the
+//! region inferencer, which is not based on unification but rather on accumulating and then
+//! solving a set of constraints. In contrast, the type inferencer assigns a value to each type
+//! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
+//! inferencer knows "so far".
+
+use middle::ty::{mod, Ty};
+use middle::ty_fold;
+use middle::ty_fold::TypeFoldable;
+use middle::ty_fold::TypeFolder;
+use std::collections::hash_map;
+
+use super::InferCtxt;
+use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
+
+pub struct TypeFreshener<'a, 'tcx:'a> {
+ infcx: &'a InferCtxt<'a, 'tcx>,
+ freshen_count: uint,
+ freshen_map: hash_map::HashMap<ty::InferTy, Ty<'tcx>>,
+}
+
+impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
+ pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeFreshener<'a, 'tcx> {
+ TypeFreshener {
+ infcx: infcx,
+ freshen_count: 0,
+ freshen_map: hash_map::HashMap::new(),
+ }
+ }
+
+ fn freshen<F>(&mut self,
+ opt_ty: Option<Ty<'tcx>>,
+ key: ty::InferTy,
+ freshener: F)
+ -> Ty<'tcx> where
+ F: FnOnce(uint) -> ty::InferTy,
+ {
+ match opt_ty {
+ Some(ty) => { return ty.fold_with(self); }
+ None => { }
+ }
+
+ match self.freshen_map.entry(key) {
+ hash_map::Occupied(entry) => *entry.get(),
+ hash_map::Vacant(entry) => {
+ let index = self.freshen_count;
+ self.freshen_count += 1;
+ let t = ty::mk_infer(self.infcx.tcx, freshener(index));
+ entry.set(t);
+ t
+ }
+ }
+ }
+}
+
+impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
+ fn tcx<'b>(&'b self) -> &'b ty::ctxt<'tcx> {
+ self.infcx.tcx
+ }
+
+ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+ match r {
+ ty::ReEarlyBound(..) |
+ ty::ReLateBound(..) => {
+ // leave bound regions alone
+ r
+ }
+
+ ty::ReStatic |
+ ty::ReFree(_) |
+ ty::ReScope(_) |
+ ty::ReInfer(_) |
+ ty::ReEmpty => {
+ // replace all free regions with 'static
+ ty::ReStatic
+ }
+ }
+ }
+
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ match t.sty {
+ ty::ty_infer(ty::TyVar(v)) => {
+ self.freshen(self.infcx.type_variables.borrow().probe(v),
+ ty::TyVar(v),
+ ty::FreshTy)
+ }
+
+ ty::ty_infer(ty::IntVar(v)) => {
+ self.freshen(self.infcx.probe_var(v),
+ ty::IntVar(v),
+ ty::FreshIntTy)
+ }
+
+ ty::ty_infer(ty::FloatVar(v)) => {
+ self.freshen(self.infcx.probe_var(v),
+ ty::FloatVar(v),
+ ty::FreshIntTy)
+ }
+
+ ty::ty_infer(ty::FreshTy(c)) |
+ ty::ty_infer(ty::FreshIntTy(c)) => {
+ if c >= self.freshen_count {
+ self.tcx().sess.bug(
+ format!("Encountered a freshend type with id {} \
+ but our counter is only at {}",
+ c,
+ self.freshen_count).as_slice());
+ }
+ t
+ }
+
+ ty::ty_open(..) => {
+ self.tcx().sess.bug("Cannot freshen an open existential type");
+ }
+
+ ty::ty_bool |
+ ty::ty_char |
+ ty::ty_int(..) |
+ ty::ty_uint(..) |
+ ty::ty_float(..) |
+ ty::ty_enum(..) |
+ ty::ty_uniq(..) |
+ ty::ty_str |
+ ty::ty_err |
+ ty::ty_vec(..) |
+ ty::ty_ptr(..) |
+ ty::ty_rptr(..) |
+ ty::ty_bare_fn(..) |
+ ty::ty_closure(..) |
+ ty::ty_trait(..) |
+ ty::ty_struct(..) |
+ ty::ty_unboxed_closure(..) |
+ ty::ty_tup(..) |
+ ty::ty_param(..) => {
+ ty_fold::super_fold_ty(self, t)
+ }
+ }
+ }
+}
pub use self::ValuePairs::*;
pub use self::fixup_err::*;
pub use middle::ty::IntVarValue;
-pub use self::skolemize::TypeSkolemizer;
+pub use self::freshen::TypeFreshener;
use middle::subst;
use middle::subst::Substs;
pub mod lub;
pub mod region_inference;
pub mod resolve;
-mod skolemize;
+mod freshen;
pub mod sub;
pub mod type_variable;
pub mod unify;
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
- pub fn skolemize<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
- t.fold_with(&mut self.skolemizer())
+ pub fn freshen<T:TypeFoldable<'tcx>>(&self, t: T) -> T {
+ t.fold_with(&mut self.freshener())
}
pub fn type_var_diverges(&'a self, ty: Ty) -> bool {
}
}
- pub fn skolemizer<'b>(&'b self) -> TypeSkolemizer<'b, 'tcx> {
- skolemize::TypeSkolemizer::new(self)
+ pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
+ freshen::TypeFreshener::new(self)
}
pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Skolemization is the process of replacing unknown variables with fresh types. The idea is that
-//! the type, after skolemization, contains no inference variables but instead contains either a
-//! value for each variable or fresh "arbitrary" types wherever a variable would have been.
-//!
-//! Skolemization is used primarily to get a good type for inserting into a cache. The result
-//! summarizes what the type inferencer knows "so far". The primary place it is used right now is
-//! in the trait matching algorithm, which needs to be able to cache whether an `impl` self type
-//! matches some other type X -- *without* affecting `X`. That means if that if the type `X` is in
-//! fact an unbound type variable, we want the match to be regarded as ambiguous, because depending
-//! on what type that type variable is ultimately assigned, the match may or may not succeed.
-//!
-//! Note that you should be careful not to allow the output of skolemization to leak to the user in
-//! error messages or in any other form. Skolemization is only really useful as an internal detail.
-//!
-//! __An important detail concerning regions.__ The skolemizer also replaces *all* regions with
-//! 'static. The reason behind this is that, in general, we do not take region relationships into
-//! account when making type-overloaded decisions. This is important because of the design of the
-//! region inferencer, which is not based on unification but rather on accumulating and then
-//! solving a set of constraints. In contrast, the type inferencer assigns a value to each type
-//! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
-//! inferencer knows "so far".
-
-use middle::ty::{mod, Ty};
-use middle::ty_fold;
-use middle::ty_fold::TypeFoldable;
-use middle::ty_fold::TypeFolder;
-use std::collections::hash_map;
-
-use super::InferCtxt;
-use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
-
-pub struct TypeSkolemizer<'a, 'tcx:'a> {
- infcx: &'a InferCtxt<'a, 'tcx>,
- skolemization_count: uint,
- skolemization_map: hash_map::HashMap<ty::InferTy, Ty<'tcx>>,
-}
-
-impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> {
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeSkolemizer<'a, 'tcx> {
- TypeSkolemizer {
- infcx: infcx,
- skolemization_count: 0,
- skolemization_map: hash_map::HashMap::new(),
- }
- }
-
- fn skolemize<F>(&mut self,
- opt_ty: Option<Ty<'tcx>>,
- key: ty::InferTy,
- skolemizer: F)
- -> Ty<'tcx> where
- F: FnOnce(uint) -> ty::InferTy,
- {
- match opt_ty {
- Some(ty) => { return ty.fold_with(self); }
- None => { }
- }
-
- match self.skolemization_map.entry(key) {
- hash_map::Occupied(entry) => *entry.get(),
- hash_map::Vacant(entry) => {
- let index = self.skolemization_count;
- self.skolemization_count += 1;
- let t = ty::mk_infer(self.infcx.tcx, skolemizer(index));
- entry.set(t);
- t
- }
- }
- }
-}
-
-impl<'a, 'tcx> TypeFolder<'tcx> for TypeSkolemizer<'a, 'tcx> {
- fn tcx<'b>(&'b self) -> &'b ty::ctxt<'tcx> {
- self.infcx.tcx
- }
-
- fn fold_region(&mut self, r: ty::Region) -> ty::Region {
- match r {
- ty::ReEarlyBound(..) |
- ty::ReLateBound(..) => {
- // leave bound regions alone
- r
- }
-
- ty::ReStatic |
- ty::ReFree(_) |
- ty::ReScope(_) |
- ty::ReInfer(_) |
- ty::ReEmpty => {
- // replace all free regions with 'static
- ty::ReStatic
- }
- }
- }
-
- fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- match t.sty {
- ty::ty_infer(ty::TyVar(v)) => {
- self.skolemize(self.infcx.type_variables.borrow().probe(v),
- ty::TyVar(v),
- ty::SkolemizedTy)
- }
-
- ty::ty_infer(ty::IntVar(v)) => {
- self.skolemize(self.infcx.probe_var(v),
- ty::IntVar(v),
- ty::SkolemizedIntTy)
- }
-
- ty::ty_infer(ty::FloatVar(v)) => {
- self.skolemize(self.infcx.probe_var(v),
- ty::FloatVar(v),
- ty::SkolemizedIntTy)
- }
-
- ty::ty_infer(ty::SkolemizedTy(c)) |
- ty::ty_infer(ty::SkolemizedIntTy(c)) => {
- if c >= self.skolemization_count {
- self.tcx().sess.bug(
- format!("Encountered a skolemized type with id {} \
- but our counter is only at {}",
- c,
- self.skolemization_count).as_slice());
- }
- t
- }
-
- ty::ty_open(..) => {
- self.tcx().sess.bug("Cannot skolemize an open existential type");
- }
-
- ty::ty_bool |
- ty::ty_char |
- ty::ty_int(..) |
- ty::ty_uint(..) |
- ty::ty_float(..) |
- ty::ty_enum(..) |
- ty::ty_uniq(..) |
- ty::ty_str |
- ty::ty_err |
- ty::ty_vec(..) |
- ty::ty_ptr(..) |
- ty::ty_rptr(..) |
- ty::ty_bare_fn(..) |
- ty::ty_closure(..) |
- ty::ty_trait(..) |
- ty::ty_struct(..) |
- ty::ty_unboxed_closure(..) |
- ty::ty_tup(..) |
- ty::ty_param(..) => {
- ty_fold::super_fold_ty(self, t)
- }
- }
- }
-}
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::ty::{mod, Ty, RegionEscape};
use middle::infer;
-use middle::infer::{InferCtxt, TypeSkolemizer};
+use middle::infer::{InferCtxt, TypeFreshener};
use middle::ty_fold::TypeFoldable;
use std::cell::RefCell;
use std::collections::hash_map::HashMap;
param_env: &'cx ty::ParameterEnvironment<'tcx>,
typer: &'cx (Typer<'tcx>+'cx),
- /// Skolemizer used specifically for skolemizing entries on the
+ /// Freshener used specifically for skolemizing entries on the
/// obligation stack. This ensures that all entries on the stack
/// at one time will have the same set of skolemized entries,
/// which is important for checking for trait bounds that
/// recursively require themselves.
- skolemizer: TypeSkolemizer<'cx, 'tcx>,
+ freshener: TypeFreshener<'cx, 'tcx>,
/// If true, indicates that the evaluation should be conservative
/// and consider the possibility of types outside this crate.
obligation: &'prev TraitObligation<'tcx>,
/// Trait ref from `obligation` but skolemized with the
- /// selection-context's skolemizer. Used to check for recursion.
- skol_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+ /// selection-context's freshener. Used to check for recursion.
+ fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
previous: Option<&'prev TraitObligationStack<'prev, 'tcx>>
}
infcx: infcx,
param_env: param_env,
typer: typer,
- skolemizer: infcx.skolemizer(),
+ freshener: infcx.freshener(),
intercrate: false,
}
}
infcx: infcx,
param_env: param_env,
typer: typer,
- skolemizer: infcx.skolemizer(),
+ freshener: infcx.freshener(),
intercrate: true,
}
}
// This suffices to allow chains like `FnMut` implemented in
// terms of `Fn` etc, but we could probably make this more
// precise still.
- let input_types = stack.skol_trait_ref.value.input_types();
- let unbound_input_types = input_types.iter().any(|&t| ty::type_is_skolemized(t));
+ let input_types = stack.fresh_trait_ref.value.input_types();
+ let unbound_input_types = input_types.iter().any(|&t| ty::type_is_fresh(t));
if
unbound_input_types &&
(self.intercrate ||
stack.iter().skip(1).any(
- |prev| stack.skol_trait_ref.value.def_id == prev.skol_trait_ref.value.def_id))
+ |prev| stack.fresh_trait_ref.value.def_id == prev.fresh_trait_ref.value.def_id))
{
debug!("evaluate_stack({}) --> unbound argument, recursion --> ambiguous",
- stack.skol_trait_ref.repr(self.tcx()));
+ stack.fresh_trait_ref.repr(self.tcx()));
return EvaluatedToAmbig;
}
// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` is
// `Send`.
//
- // Note that we do this comparison using the `skol_trait_ref`
+ // Note that we do this comparison using the `fresh_trait_ref`
// fields. Because these have all been skolemized using
- // `self.skolemizer`, we can be sure that (a) this will not
+ // `self.freshener`, we can be sure that (a) this will not
// affect the inferencer state and (b) that if we see two
// skolemized types with the same index, they refer to the
// same unbound type variable.
if
stack.iter()
.skip(1) // skip top-most frame
- .any(|prev| stack.skol_trait_ref == prev.skol_trait_ref)
+ .any(|prev| stack.fresh_trait_ref == prev.fresh_trait_ref)
{
debug!("evaluate_stack({}) --> recursive",
- stack.skol_trait_ref.repr(self.tcx()));
+ stack.fresh_trait_ref.repr(self.tcx()));
return EvaluatedToOk;
}
}
// Check the cache. Note that we skolemize the trait-ref
- // separately rather than using `stack.skol_trait_ref` -- this
+ // separately rather than using `stack.fresh_trait_ref` -- this
// is because we want the unbound variables to be replaced
// with fresh skolemized types starting from index 0.
- let cache_skol_trait_ref =
- self.infcx.skolemize(stack.obligation.trait_ref.clone());
- debug!("candidate_from_obligation(cache_skol_trait_ref={}, obligation={})",
- cache_skol_trait_ref.repr(self.tcx()),
+ let cache_fresh_trait_ref =
+ self.infcx.freshen(stack.obligation.trait_ref.clone());
+ debug!("candidate_from_obligation(cache_fresh_trait_ref={}, obligation={})",
+ cache_fresh_trait_ref.repr(self.tcx()),
stack.repr(self.tcx()));
assert!(!stack.obligation.trait_ref.has_escaping_regions());
- match self.check_candidate_cache(cache_skol_trait_ref.clone()) {
+ match self.check_candidate_cache(cache_fresh_trait_ref.clone()) {
Some(c) => {
- debug!("CACHE HIT: cache_skol_trait_ref={}, candidate={}",
- cache_skol_trait_ref.repr(self.tcx()),
+ debug!("CACHE HIT: cache_fresh_trait_ref={}, candidate={}",
+ cache_fresh_trait_ref.repr(self.tcx()),
c.repr(self.tcx()));
return c;
}
// If no match, compute result and insert into cache.
let candidate = self.candidate_from_obligation_no_cache(stack);
- debug!("CACHE MISS: cache_skol_trait_ref={}, candidate={}",
- cache_skol_trait_ref.repr(self.tcx()), candidate.repr(self.tcx()));
- self.insert_candidate_cache(cache_skol_trait_ref, candidate.clone());
+ debug!("CACHE MISS: cache_fresh_trait_ref={}, candidate={}",
+ cache_fresh_trait_ref.repr(self.tcx()), candidate.repr(self.tcx()));
+ self.insert_candidate_cache(cache_fresh_trait_ref, candidate.clone());
candidate
}
}
fn pick_candidate_cache(&self,
- cache_skol_trait_ref: &Rc<ty::PolyTraitRef<'tcx>>)
+ cache_fresh_trait_ref: &Rc<ty::PolyTraitRef<'tcx>>)
-> &SelectionCache<'tcx>
{
// High-level idea: we have to decide whether to consult the
// If the trait refers to any parameters in scope, then use
// the cache of the param-environment.
if
- cache_skol_trait_ref.value.input_types().iter().any(
+ cache_fresh_trait_ref.value.input_types().iter().any(
|&t| ty::type_has_self(t) || ty::type_has_params(t))
{
return &self.param_env.selection_cache;
// See the discussion in doc.rs for more details.
if
!self.param_env.caller_bounds.is_empty() &&
- cache_skol_trait_ref.value.input_types().iter().any(
+ cache_fresh_trait_ref.value.input_types().iter().any(
|&t| ty::type_has_ty_infer(t))
{
return &self.param_env.selection_cache;
}
fn check_candidate_cache(&mut self,
- cache_skol_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+ cache_fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
-> Option<SelectionResult<'tcx, Candidate<'tcx>>>
{
- let cache = self.pick_candidate_cache(&cache_skol_trait_ref);
+ let cache = self.pick_candidate_cache(&cache_fresh_trait_ref);
let hashmap = cache.hashmap.borrow();
- hashmap.get(&cache_skol_trait_ref).map(|c| (*c).clone())
+ hashmap.get(&cache_fresh_trait_ref).map(|c| (*c).clone())
}
fn insert_candidate_cache(&mut self,
- cache_skol_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+ cache_fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
candidate: SelectionResult<'tcx, Candidate<'tcx>>)
{
- let cache = self.pick_candidate_cache(&cache_skol_trait_ref);
+ let cache = self.pick_candidate_cache(&cache_fresh_trait_ref);
let mut hashmap = cache.hashmap.borrow_mut();
- hashmap.insert(cache_skol_trait_ref, candidate);
+ hashmap.insert(cache_fresh_trait_ref, candidate);
}
fn assemble_candidates<'o>(&mut self,
}
ty::ty_open(_) |
- ty::ty_infer(ty::SkolemizedTy(_)) |
- ty::ty_infer(ty::SkolemizedIntTy(_)) => {
+ ty::ty_infer(ty::FreshTy(_)) |
+ ty::ty_infer(ty::FreshIntTy(_)) => {
self.tcx().sess.bug(
format!(
"asked to assemble builtin bounds of unexpected type: {}",
obligation: &'o TraitObligation<'tcx>)
-> TraitObligationStack<'o, 'tcx>
{
- let skol_trait_ref = obligation.trait_ref.fold_with(&mut self.skolemizer);
+ let fresh_trait_ref = obligation.trait_ref.fold_with(&mut self.freshener);
TraitObligationStack {
obligation: obligation,
- skol_trait_ref: skol_trait_ref,
+ fresh_trait_ref: fresh_trait_ref,
previous: previous_stack.map(|p| p), // FIXME variance
}
}
TyVar(TyVid),
IntVar(IntVid),
FloatVar(FloatVid),
- SkolemizedTy(uint),
+
+ /// A `FreshTy` is one that is generated as a replacement for an
+ /// unbound type variable. This is convenient for caching etc. See
+ /// `middle::infer::freshen` for more details.
+ FreshTy(uint),
// FIXME -- once integral fallback is impl'd, we should remove
// this type. It's only needed to prevent spurious errors for
// integers whose type winds up never being constrained.
- SkolemizedIntTy(uint),
+ FreshIntTy(uint),
}
impl Copy for InferTy {}
TyVar(ref v) => v.fmt(f),
IntVar(ref v) => v.fmt(f),
FloatVar(ref v) => v.fmt(f),
- SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
- SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
+ FreshTy(v) => write!(f, "FreshTy({})", v),
+ FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
}
}
}
}
// Scalar and unique types are sendable, and durable
- ty_infer(ty::SkolemizedIntTy(_)) |
+ ty_infer(ty::FreshIntTy(_)) |
ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty::ty_char => {
TC::None
}
}
-pub fn type_is_skolemized(ty: Ty) -> bool {
+pub fn type_is_fresh(ty: Ty) -> bool {
match ty.sty {
- ty_infer(SkolemizedTy(_)) => true,
- ty_infer(SkolemizedIntTy(_)) => true,
+ ty_infer(FreshTy(_)) => true,
+ ty_infer(FreshIntTy(_)) => true,
_ => false
}
}
ty_infer(TyVar(_)) => "inferred type".to_string(),
ty_infer(IntVar(_)) => "integral variable".to_string(),
ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
- ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
- ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
+ ty_infer(FreshTy(_)) => "skolemized type".to_string(),
+ ty_infer(FreshIntTy(_)) => "skolemized integral type".to_string(),
ty_param(ref p) => {
if p.space == subst::SelfSpace {
"Self".to_string()
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically
// a skolemized type.
- let open_ty = ty::mk_infer(tcx, SkolemizedTy(0));
+ let open_ty = ty::mk_infer(tcx, FreshTy(0));
let opt_trait_ref = opt_principal.map_or(Vec::new(), |principal| {
let substs = principal.substs().with_self_ty(open_ty);
ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
- ty::SkolemizedTy(v) => format!("SkolemizedTy({})", v),
- ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v)
+ ty::FreshTy(v) => format!("FreshTy({})", v),
+ ty::FreshIntTy(v) => format!("FreshIntTy({})", v)
}
}
}
}
- // Use skolemize to simultaneously replace all type variables with
+ // Use freshen to simultaneously replace all type variables with
// their bindings and replace all regions with 'static. This is
// sort of overkill because we do not expect there to be any
- // unbound type variables, hence no skolemized types should ever
- // be inserted.
- let vtable = vtable.fold_with(&mut infcx.skolemizer());
+ // unbound type variables, hence no `TyFresh` types should ever be
+ // inserted.
+ let vtable = vtable.fold_with(&mut infcx.freshener());
info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
ccx.trait_cache().borrow_mut().insert(trait_ref,