]> git.lizzy.rs Git - rust.git/commitdiff
Rename the code that replaces unbound variables to "freshen" rather than "skolemize...
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 12 Dec 2014 11:13:42 +0000 (06:13 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 19 Dec 2014 08:29:30 +0000 (03:29 -0500)
src/librustc/middle/infer/freshen.rs [new file with mode: 0644]
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/skolemize.rs [deleted file]
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/util/ppaux.rs
src/librustc_trans/trans/common.rs

diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs
new file mode 100644 (file)
index 0000000..ebff854
--- /dev/null
@@ -0,0 +1,165 @@
+// 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)
+            }
+        }
+    }
+}
index 80508a8f16f1f98dce56bcce0e4f735c03007a39..c58b99e0ae2b71906eccb4a45ee8cef89c55f488 100644 (file)
@@ -19,7 +19,7 @@
 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;
@@ -57,7 +57,7 @@
 pub mod lub;
 pub mod region_inference;
 pub mod resolve;
-mod skolemize;
+mod freshen;
 pub mod sub;
 pub mod type_variable;
 pub mod unify;
@@ -505,8 +505,8 @@ pub struct CombinedSnapshot {
 }
 
 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 {
@@ -516,8 +516,8 @@ 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>)
diff --git a/src/librustc/middle/infer/skolemize.rs b/src/librustc/middle/infer/skolemize.rs
deleted file mode 100644 (file)
index 8336131..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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)
-            }
-        }
-    }
-}
index 86435267be002cec5e33d9beac79ed1cef11570c..ce59f5285dbc7b94ad08938c561459f1648b601d 100644 (file)
@@ -30,7 +30,7 @@
 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;
@@ -44,12 +44,12 @@ pub struct SelectionContext<'cx, 'tcx:'cx> {
     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.
@@ -73,8 +73,8 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
     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>>
 }
@@ -172,7 +172,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>,
             infcx: infcx,
             param_env: param_env,
             typer: typer,
-            skolemizer: infcx.skolemizer(),
+            freshener: infcx.freshener(),
             intercrate: false,
         }
     }
@@ -185,7 +185,7 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
             infcx: infcx,
             param_env: param_env,
             typer: typer,
-            skolemizer: infcx.skolemizer(),
+            freshener: infcx.freshener(),
             intercrate: true,
         }
     }
@@ -347,16 +347,16 @@ fn evaluate_stack<'o>(&mut self,
         // 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;
         }
 
@@ -373,19 +373,19 @@ fn evaluate_stack<'o>(&mut self,
         // `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;
         }
 
@@ -445,20 +445,20 @@ fn candidate_from_obligation<'o>(&mut self,
         }
 
         // 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;
             }
@@ -467,9 +467,9 @@ fn candidate_from_obligation<'o>(&mut self,
 
         // 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
     }
 
@@ -569,7 +569,7 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
     }
 
     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
@@ -591,7 +591,7 @@ fn pick_candidate_cache(&self,
         // 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;
@@ -604,7 +604,7 @@ fn pick_candidate_cache(&self,
         // 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;
@@ -615,21 +615,21 @@ fn pick_candidate_cache(&self,
     }
 
     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,
@@ -1269,8 +1269,8 @@ fn builtin_bound(&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: {}",
@@ -1831,11 +1831,11 @@ fn push_stack<'o,'s:'o>(&mut self,
                             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
         }
     }
index ee4097b4d0a9c32aab9cae37dafdcf8577f84234..a25e4087905dde5bd3e162890f750d87545d9086 100644 (file)
@@ -1538,12 +1538,16 @@ pub enum InferTy {
     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 {}
@@ -1610,8 +1614,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             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),
         }
     }
 }
@@ -2986,7 +2990,7 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
             }
 
             // 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
@@ -3592,10 +3596,10 @@ pub fn type_is_integral(ty: Ty) -> bool {
     }
 }
 
-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
     }
 }
@@ -4428,8 +4432,8 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         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()
@@ -5594,7 +5598,7 @@ pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
     // 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);
index afa7ce1867554fcabf0342b50542bbf52bf2ca89..6c00aa546f3874164bd971f95db58f8a86e451d7 100644 (file)
@@ -374,8 +374,8 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
             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)
         }
     }
 
index ab18a05a2511fecdd821d753cd93663219fb18ca..a8e88eca0e19f1f49216bf8d44d71d9628377fb2 100644 (file)
@@ -848,12 +848,12 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     }
 
-    // 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,