From: Niko Matsakis Date: Thu, 16 Mar 2017 13:05:39 +0000 (-0400) Subject: remove the subtyping relations from TypeVariable X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=e58e2b423dabc816ba5d9e2382373622cc07bc8d;p=rust.git remove the subtyping relations from TypeVariable --- diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 9430421f910..825f279e78e 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -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(&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( diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index bf247acec5a..f620965ced8 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -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) } diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 1a94f12973d..f1de9b043e3 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -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) } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 67f37e5f927..298b2a97d5f 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -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, default: Option> } } @@ -76,33 +72,13 @@ pub struct Snapshot { eq_snapshot: ut::Snapshot, } -enum UndoEntry<'tcx> { - // The type of the var was specified. - SpecifyVar(ty::TyVid, Vec, Option>), - Relate(ty::TyVid, ty::TyVid), - RelateRange(ty::TyVid, usize), +struct Instantiate<'tcx> { + vid: ty::TyVid, + default: Option>, } 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 { - relations(self.values.get_mut(a.index as usize)) - } - pub fn default(&self, vid: ty::TyVid) -> Option> { 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> { 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 { impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> { type Value = TypeVariableData<'tcx>; - type Undo = UndoEntry<'tcx>; - - fn reverse(values: &mut Vec>, 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 { - match v.value { - Known(_) => bug!("var_sub_var: variable is known"), - Bounded { ref mut relations, .. } => relations + fn reverse(values: &mut Vec>, action: Instantiate<'tcx>) { + let Instantiate { vid, default } = action; + values[vid.index as usize].value = Bounded { + default: default + }; } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 3b002fd4dfc..9176a4c0157 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -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)] diff --git a/src/test/compile-fail/issue-7813.rs b/src/test/compile-fail/issue-7813.rs index 662b9e894ba..2551ed0208a 100644 --- a/src/test/compile-fail/issue-7813.rs +++ b/src/test/compile-fail/issue-7813.rs @@ -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 `_` }