]> git.lizzy.rs Git - rust.git/commitdiff
remove the subtyping relations from TypeVariable
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 16 Mar 2017 13:05:39 +0000 (09:05 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 12 Apr 2017 00:32:46 +0000 (20:32 -0400)
src/librustc/infer/combine.rs
src/librustc/infer/equate.rs
src/librustc/infer/sub.rs
src/librustc/infer/type_variable.rs
src/librustc/lib.rs
src/test/compile-fail/issue-7813.rs

index 9430421f91014bc72f9ac46a9794a56b07eb81cd..825f279e78e4b0968fd0b865d247504edcbac5bd 100644 (file)
@@ -38,7 +38,6 @@
 use super::sub::Sub;
 use super::InferCtxt;
 use super::{MiscVariable, TypeTrace};
-use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};
 
 use ty::{IntType, UintType};
 use ty::{self, Ty, TyCtxt};
@@ -59,6 +58,11 @@ pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
     pub obligations: PredicateObligations<'tcx>,
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum RelationDir {
+    SubtypeOf, SupertypeOf, EqTo
+}
+
 impl<'infcx, 'gcx, 'tcx> InferCtxt<'infcx, 'gcx, 'tcx> {
     pub fn super_combine_tys<R>(&self,
                                 relation: &mut R,
@@ -177,6 +181,8 @@ pub fn instantiate(&mut self,
                        a_is_expected: bool)
                        -> RelateResult<'tcx, ()>
     {
+        use self::RelationDir::*;
+
         // We use SmallVector here instead of Vec because this code is hot and
         // it's rare that the stack length exceeds 1.
         let mut stack = SmallVector::new();
@@ -224,7 +230,7 @@ pub fn instantiate(&mut self,
                     // Generalize type if necessary.
                     let generalized_ty = match dir {
                         EqTo => self.generalize(a_ty, b_vid, false),
-                        BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
+                        SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
                     }?;
                     debug!("instantiate(a_ty={:?}, dir={:?}, \
                                         b_vid={:?}, generalized_ty={:?})",
@@ -232,8 +238,7 @@ pub fn instantiate(&mut self,
                            generalized_ty);
                     self.infcx.type_variables
                         .borrow_mut()
-                        .instantiate_and_push(
-                            b_vid, generalized_ty, &mut stack);
+                        .instantiate(b_vid, generalized_ty);
                     generalized_ty
                 }
             };
@@ -246,7 +251,6 @@ pub fn instantiate(&mut self,
             // to associate causes/spans with each of the relations in
             // the stack to get this right.
             match dir {
-                BiTo => Ok(a_ty),
                 EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
                 SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
                 SupertypeOf => self.sub(a_is_expected).relate_with_variance(
index bf247acec5a2d31112c5a787ac2b7772ab029318..f620965ced84590e5c1b32d769374248dc66342f 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::CombineFields;
+use super::combine::{CombineFields, RelationDir};
 use super::{Subtype};
-use super::type_variable::{EqTo};
 
 use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
@@ -58,17 +57,17 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
         match (&a.sty, &b.sty) {
             (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
-                infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
+                infcx.type_variables.borrow_mut().equate(a_id, b_id);
                 Ok(a)
             }
 
             (&ty::TyInfer(TyVar(a_id)), _) => {
-                self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
+                self.fields.instantiate(b, RelationDir::EqTo, a_id, self.a_is_expected)?;
                 Ok(a)
             }
 
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, RelationDir::EqTo, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
index 1a94f12973de8a26d22de9e0fd8c062f4535d423..f1de9b043e36ff71794b8e9de576b06cb89a3a67 100644 (file)
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use super::SubregionOrigin;
-use super::combine::CombineFields;
-use super::type_variable::{SubtypeOf, SupertypeOf};
+use super::combine::{CombineFields, RelationDir};
 
 use traits::Obligation;
 use ty::{self, Ty, TyCtxt};
@@ -104,11 +103,11 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
             }
             (&ty::TyInfer(TyVar(a_id)), _) => {
                 self.fields
-                    .instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
+                    .instantiate(b, RelationDir::SupertypeOf, a_id, !self.a_is_expected)?;
                 Ok(a)
             }
             (_, &ty::TyInfer(TyVar(b_id))) => {
-                self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
+                self.fields.instantiate(a, RelationDir::SubtypeOf, b_id, self.a_is_expected)?;
                 Ok(a)
             }
 
index 67f37e5f9272e85c058beb616995a89dbd92b227..298b2a97d5f3641c4657129740421c491269a6b1 100644 (file)
@@ -8,11 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::RelationDir::*;
 use self::TypeVariableValue::*;
-use self::UndoEntry::*;
 use hir::def_id::{DefId};
-use syntax::util::small_vector::SmallVector;
 use syntax::ast;
 use syntax_pos::Span;
 use ty::{self, Ty};
@@ -55,7 +52,6 @@ struct TypeVariableData<'tcx> {
 enum TypeVariableValue<'tcx> {
     Known(Ty<'tcx>),
     Bounded {
-        relations: Vec<Relation>,
         default: Option<Default<'tcx>>
     }
 }
@@ -76,33 +72,13 @@ pub struct Snapshot {
     eq_snapshot: ut::Snapshot<ty::TyVid>,
 }
 
-enum UndoEntry<'tcx> {
-    // The type of the var was specified.
-    SpecifyVar(ty::TyVid, Vec<Relation>, Option<Default<'tcx>>),
-    Relate(ty::TyVid, ty::TyVid),
-    RelateRange(ty::TyVid, usize),
+struct Instantiate<'tcx> {
+    vid: ty::TyVid,
+    default: Option<Default<'tcx>>,
 }
 
 struct Delegate<'tcx>(PhantomData<&'tcx ()>);
 
-type Relation = (RelationDir, ty::TyVid);
-
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub enum RelationDir {
-    SubtypeOf, SupertypeOf, EqTo, BiTo
-}
-
-impl RelationDir {
-    fn opposite(self) -> RelationDir {
-        match self {
-            SubtypeOf => SupertypeOf,
-            SupertypeOf => SubtypeOf,
-            EqTo => EqTo,
-            BiTo => BiTo,
-        }
-    }
-}
-
 impl<'tcx> TypeVariableTable<'tcx> {
     pub fn new() -> TypeVariableTable<'tcx> {
         TypeVariableTable {
@@ -111,10 +87,6 @@ pub fn new() -> TypeVariableTable<'tcx> {
         }
     }
 
-    fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
-        relations(self.values.get_mut(a.index as usize))
-    }
-
     pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
         match &self.values.get(vid.index as usize).value {
             &Known(_) => None,
@@ -130,68 +102,37 @@ pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
         &self.values.get(vid.index as usize).origin
     }
 
-    /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
+    /// Records that `a == b`, depending on `dir`.
     ///
     /// Precondition: neither `a` nor `b` are known.
-    pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
-        let a = self.root_var(a);
-        let b = self.root_var(b);
-        if a != b {
-            if dir == EqTo {
-                // a and b must be equal which we mark in the unification table
-                let root = self.eq_relations.union(a, b);
-                // In addition to being equal, all relations from the variable which is no longer
-                // the root must be added to the root so they are not forgotten as the other
-                // variable should no longer be referenced (other than to get the root)
-                let other = if a == root { b } else { a };
-                let count = {
-                    let (relations, root_relations) = if other.index < root.index {
-                        let (pre, post) = self.values.split_at_mut(root.index as usize);
-                        (relations(&mut pre[other.index as usize]), relations(&mut post[0]))
-                    } else {
-                        let (pre, post) = self.values.split_at_mut(other.index as usize);
-                        (relations(&mut post[0]), relations(&mut pre[root.index as usize]))
-                    };
-                    root_relations.extend_from_slice(relations);
-                    relations.len()
-                };
-                self.values.record(RelateRange(root, count));
-            } else {
-                self.relations(a).push((dir, b));
-                self.relations(b).push((dir.opposite(), a));
-                self.values.record(Relate(a, b));
-            }
-        }
+    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());
+        self.eq_relations.union(a, b);
     }
 
-    /// Instantiates `vid` with the type `ty` and then pushes an entry onto `stack` for each of the
-    /// relations of `vid` to other variables. The relations will have the form `(ty, dir, vid1)`
-    /// where `vid1` is some other variable id.
+    /// Instantiates `vid` with the type `ty`.
     ///
     /// Precondition: `vid` must be a root in the unification table
-    pub fn instantiate_and_push(
-        &mut self,
-        vid: ty::TyVid,
-        ty: Ty<'tcx>,
-        stack: &mut SmallVector<(Ty<'tcx>, RelationDir, ty::TyVid)>)
-    {
+    /// and has not previously been instantiated.
+    pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) {
         debug_assert!(self.root_var(vid) == vid);
-        let old_value = {
-            let value_ptr = &mut self.values.get_mut(vid.index as usize).value;
-            mem::replace(value_ptr, Known(ty))
-        };
+        debug_assert!(self.probe(vid).is_none());
 
-        let (relations, default) = match old_value {
-            Bounded { relations, default } => (relations, default),
-            Known(_) => bug!("Asked to instantiate variable that is \
-                              already instantiated")
+        let old_value = {
+            let vid_data = &mut self.values[vid.index as usize];
+            mem::replace(&mut vid_data.value, TypeVariableValue::Known(ty))
         };
 
-        for &(dir, vid) in &relations {
-            stack.push((ty, dir, vid));
+        match old_value {
+            TypeVariableValue::Bounded { default } => {
+                self.values.record(Instantiate { vid: vid, default: default });
+            }
+            TypeVariableValue::Known(old_ty) => {
+                bug!("instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}",
+                     vid, ty, old_ty)
+            }
         }
-
-        self.values.record(SpecifyVar(vid, relations, default));
     }
 
     pub fn new_var(&mut self,
@@ -201,7 +142,7 @@ pub fn new_var(&mut self,
         debug!("new_var(diverging={:?}, origin={:?})", diverging, origin);
         self.eq_relations.new_key(());
         let index = self.values.push(TypeVariableData {
-            value: Bounded { relations: vec![], default: default },
+            value: Bounded { default: default },
             origin: origin,
             diverging: diverging
         });
@@ -298,7 +239,7 @@ pub fn types_escaping_snapshot(&mut self, s: &Snapshot) -> Vec<Ty<'tcx>> {
                     debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold);
                 }
 
-                sv::UndoLog::Other(SpecifyVar(vid, ..)) => {
+                sv::UndoLog::Other(Instantiate { vid, .. }) => {
                     if vid.index < new_elem_threshold {
                         // quick check to see if this variable was
                         // created since the snapshot started or not.
@@ -334,35 +275,12 @@ pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
 
 impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
     type Value = TypeVariableData<'tcx>;
-    type Undo = UndoEntry<'tcx>;
-
-    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry<'tcx>) {
-        match action {
-            SpecifyVar(vid, relations, default) => {
-                values[vid.index as usize].value = Bounded {
-                    relations: relations,
-                    default: default
-                };
-            }
+    type Undo = Instantiate<'tcx>;
 
-            Relate(a, b) => {
-                relations(&mut (*values)[a.index as usize]).pop();
-                relations(&mut (*values)[b.index as usize]).pop();
-            }
-
-            RelateRange(i, n) => {
-                let relations = relations(&mut (*values)[i.index as usize]);
-                for _ in 0..n {
-                    relations.pop();
-                }
-            }
-        }
-    }
-}
-
-fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
-    match v.value {
-        Known(_) => bug!("var_sub_var: variable is known"),
-        Bounded { ref mut relations, .. } => relations
+    fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: Instantiate<'tcx>) {
+        let Instantiate { vid, default } = action;
+        values[vid.index as usize].value = Bounded {
+            default: default
+        };
     }
 }
index 3b002fd4dfc1a210e8445eb9e2cd8469beac0c68..9176a4c01575f212d84a55633b87d0f026b3c4ca 100644 (file)
@@ -32,6 +32,7 @@
 #![feature(i128_type)]
 #![feature(libc)]
 #![feature(loop_break_value)]
+#![feature(never_type)]
 #![feature(nonzero)]
 #![cfg_attr(stage0, feature(pub_restricted))]
 #![feature(quote)]
index 662b9e894ba3a0d9f51aa93a2f41ac57325ba70b..2551ed0208af3ef4cce431604a84dfdca4eb3fa2 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let v = &[];
-    //~^ NOTE consider giving `it` a type
-    let it = v.iter(); //~ ERROR cannot infer type for `_`
+    let v = &[]; //~ NOTE consider giving `v` a type
+    let it = v.iter(); //~ ERROR type annotations needed
+    //~^ NOTE cannot infer type for `_`
 }