have probe() return TypeVariableValue

This commit is contained in:
Niko Matsakis 2017-07-16 10:18:55 -04:00 committed by Sean Griffin
parent ccd92c2a4e
commit 69fe43c97e
5 changed files with 46 additions and 35 deletions

View File

@ -34,10 +34,10 @@
use super::equate::Equate;
use super::glb::Glb;
use super::{InferCtxt, MiscVariable, TypeTrace};
use super::lub::Lub;
use super::sub::Sub;
use super::InferCtxt;
use super::{MiscVariable, TypeTrace};
use super::type_variable::TypeVariableValue;
use hir::def_id::DefId;
use ty::{IntType, UintType};
@ -194,7 +194,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
use self::RelationDir::*;
// Get the actual variable that b_vid has been inferred to
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_none());
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_unknown());
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
@ -403,11 +403,11 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
return Err(TypeError::CyclicTy(self.root_ty));
} else {
match variables.probe(vid) {
Some(u) => {
TypeVariableValue::Known { value: u } => {
drop(variables);
self.relate(&u, &u)
}
None => {
TypeVariableValue::Unknown { .. } => {
match self.ambient_variance {
// Invariant: no need to make a fresh type variable.
ty::Invariant => return Ok(t),

View File

@ -133,7 +133,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
match t.sty {
ty::TyInfer(ty::TyVar(v)) => {
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v);
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
self.freshen(
opt_ty,
ty::TyVar(v),

View File

@ -131,7 +131,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
// variables to their binding anyhow, we know
// that it is unbound, so we can just return
// it.
debug_assert!(self.infcx.type_variables.borrow_mut().probe(vid).is_none());
debug_assert!(self.infcx.type_variables.borrow_mut()
.probe(vid)
.is_unknown());
ty
}

View File

@ -1259,9 +1259,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// so this recursion should always be of very limited
// depth.
self.type_variables.borrow_mut()
.probe(v)
.map(|t| self.shallow_resolve(t))
.unwrap_or(typ)
.probe(v)
.known()
.map(|t| self.shallow_resolve(t))
.unwrap_or(typ)
}
ty::TyInfer(ty::IntVar(v)) => {

View File

@ -78,12 +78,28 @@ struct TypeVariableData {
diverging: bool
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum TypeVariableValue<'tcx> {
#[derive(Copy, Clone, Debug)]
pub enum TypeVariableValue<'tcx> {
Known { value: Ty<'tcx> },
Unknown,
}
impl<'tcx> TypeVariableValue<'tcx> {
pub fn known(&self) -> Option<Ty<'tcx>> {
match *self {
TypeVariableValue::Unknown { .. } => None,
TypeVariableValue::Known { value } => Some(value),
}
}
pub fn is_unknown(&self) -> bool {
match *self {
TypeVariableValue::Unknown { .. } => true,
TypeVariableValue::Known { .. } => false,
}
}
}
pub struct Snapshot<'tcx> {
/// number of variables at the time of the snapshot
num_vars: usize,
@ -124,8 +140,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
///
/// Precondition: neither `a` nor `b` are known.
pub fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
debug_assert!(self.probe(a).is_none());
debug_assert!(self.probe(b).is_none());
debug_assert!(self.probe(a).is_unknown());
debug_assert!(self.probe(b).is_unknown());
self.eq_relations.union(a, b);
self.sub_relations.union(a, b);
}
@ -134,8 +150,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
///
/// Precondition: neither `a` nor `b` are known.
pub fn sub(&mut self, a: ty::TyVid, b: ty::TyVid) {
debug_assert!(self.probe(a).is_none());
debug_assert!(self.probe(b).is_none());
debug_assert!(self.probe(a).is_unknown());
debug_assert!(self.probe(b).is_unknown());
self.sub_relations.union(a, b);
}
@ -144,8 +160,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
/// Precondition: `vid` must not have been previously instantiated.
pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
let vid = self.root_var(vid);
debug_assert!(self.probe(vid).is_none());
debug_assert!(self.eq_relations.probe_value(vid) == TypeVariableValue::Unknown,
debug_assert!(self.probe(vid).is_unknown());
debug_assert!(self.eq_relations.probe_value(vid).is_unknown(),
"instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
vid, ty, self.eq_relations.probe_value(vid));
self.eq_relations.union_value(vid, TypeVariableValue::Known { value: ty });
@ -211,12 +227,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
/// Retrieves the type to which `vid` has been instantiated, if
/// any.
pub fn probe(&mut self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
let vid = self.root_var(vid);
match self.eq_relations.probe_value(vid) {
TypeVariableValue::Unknown => None,
TypeVariableValue::Known { value } => Some(value)
}
pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
self.eq_relations.probe_value(vid)
}
/// If `t` is a type-inference variable, and it has been
@ -226,8 +238,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
match t.sty {
ty::TyInfer(ty::TyVar(v)) => {
match self.probe(v) {
None => t,
Some(u) => u
TypeVariableValue::Unknown { .. } => t,
TypeVariableValue::Known { value } => value,
}
}
_ => t,
@ -313,12 +325,9 @@ impl<'tcx> TypeVariableTable<'tcx> {
// use the less efficient algorithm for now.
let mut escaping_types = Vec::with_capacity(snapshot.num_vars);
escaping_types.extend(
(0..snapshot.num_vars) // for all variables that pre-exist the snapshot...
(0..snapshot.num_vars) // for all variables that pre-exist the snapshot, collect..
.map(|i| ty::TyVid { index: i as u32 })
.filter_map(|vid| match self.eq_relations.probe_value(vid) {
TypeVariableValue::Unknown => None,
TypeVariableValue::Known { value } => Some(value),
})); // ...collect what types they've been instantiated with.
.filter_map(|vid| self.probe(vid).known())); // ..types they are instantiated with.
debug!("types_escaping_snapshot = {:?}", escaping_types);
escaping_types
}
@ -329,10 +338,9 @@ impl<'tcx> TypeVariableTable<'tcx> {
(0..self.var_data.len())
.filter_map(|i| {
let vid = ty::TyVid { index: i as u32 };
if self.probe(vid).is_some() {
None
} else {
Some(vid)
match self.probe(vid) {
TypeVariableValue::Unknown { .. } => Some(vid),
TypeVariableValue::Known { .. } => None,
}
})
.collect()