]> git.lizzy.rs Git - rust.git/commitdiff
Remove defaults table and attach defaults directly to tyvars
authorJared Roesch <roeschinc@gmail.com>
Thu, 9 Jul 2015 19:15:48 +0000 (12:15 -0700)
committerJared Roesch <jroesch@MacBook.home>
Sun, 26 Jul 2015 02:57:58 +0000 (19:57 -0700)
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/type_variable.rs
src/librustc_typeck/check/mod.rs
src/test/run-pass/default_type_parameter_default_dependent_associated_type.rs [new file with mode: 0644]
src/test/run-pass/default_type_parameter_dependent_defaults.rs [new file with mode: 0644]
src/test/run-pass/default_type_parameter_struct_and_type_alias.rs [new file with mode: 0644]

index 59ca795e5f7511eba978e0af45106c98d1456630..db6e0ad1d4a83bc7b05c55072dc82e6352cc292d 100644 (file)
@@ -95,9 +95,6 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
     normalize: bool,
 
     err_count_on_creation: usize,
-
-    // Default Type Parameter fallbacks
-    pub defaults: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
 }
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -353,8 +350,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
         parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
         fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
         normalize: false,
-        err_count_on_creation: tcx.sess.err_count(),
-        defaults: RefCell::new(FnvHashMap()),
+        err_count_on_creation: tcx.sess.err_count()
     }
 }
 
@@ -657,27 +653,44 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
         }
     }
 
+    /// Returns a type variable's default fallback if any exists. A default
+    /// must be attached to the variable when created, if it is created
+    /// without a default, this will return None.
+    ///
+    /// See `new_ty_var_with_default` to create a type variable with a default.
+    /// See `type_variable::Default` for details about what a default entails.
+    pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
+        match ty.sty {
+            ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
+            _ => None
+        }
+    }
+
     pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
         let mut variables = Vec::new();
 
         let unbound_ty_vars = self.type_variables
                                   .borrow()
                                   .unsolved_variables()
-                                  .into_iter().map(|t| self.tcx.mk_var(t));
+                                  .into_iter()
+                                  .map(|t| self.tcx.mk_var(t));
 
         let unbound_int_vars = self.int_unification_table
                                    .borrow_mut()
                                    .unsolved_variables()
-                                   .into_iter().map(|v| self.tcx.mk_int_var(v));
+                                   .into_iter()
+                                   .map(|v| self.tcx.mk_int_var(v));
 
         let unbound_float_vars = self.float_unification_table
                                      .borrow_mut()
                                      .unsolved_variables()
-                                     .into_iter().map(|v| self.tcx.mk_float_var(v));
+                                     .into_iter()
+                                     .map(|v| self.tcx.mk_float_var(v));
 
         variables.extend(unbound_ty_vars);
         variables.extend(unbound_int_vars);
         variables.extend(unbound_float_vars);
+        
         return variables;
     }
 
@@ -984,13 +997,22 @@ pub fn region_outlives_predicate(&self,
     pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {
         self.type_variables
             .borrow_mut()
-            .new_var(diverging)
+            .new_var(diverging, None)
     }
 
     pub fn next_ty_var(&self) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(false))
     }
 
+    pub fn next_ty_var_with_default(&self,
+                                    default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
+        let ty_var_id = self.type_variables
+                            .borrow_mut()
+                            .new_var(false, default);
+
+        self.tcx.mk_var(ty_var_id)
+    }
+
     pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(true))
     }
@@ -1027,14 +1049,18 @@ pub fn region_vars_for_defs(&self,
     pub fn type_vars_for_defs(&self,
                               defs: &[ty::TypeParameterDef<'tcx>])
                               -> Vec<ty::Ty<'tcx>> {
+        let mut substs = Substs::empty();
         let mut vars = Vec::with_capacity(defs.len());
 
         for def in defs.iter() {
-            let ty_var = self.next_ty_var();
-            match def.default {
-                None => {},
-                Some(default) => { self.defaults.borrow_mut().insert(ty_var, default); }
-            }
+            let default = def.default.map(|default| {
+                type_variable::Default {
+                    ty: default
+                }
+            });
+            //.subst(self.tcx, &substs)
+            let ty_var = self.next_ty_var_with_default(default);
+            substs.types.push(subst::ParamSpace::SelfSpace, ty_var);
             vars.push(ty_var)
         }
 
index ebecb0898b4df4b55bbb6a40b269f0bda4ce21a5..6ba289d3665aa7d870145117a72128839591462b 100644 (file)
@@ -30,7 +30,17 @@ struct TypeVariableData<'tcx> {
 
 enum TypeVariableValue<'tcx> {
     Known(Ty<'tcx>),
-    Bounded(Vec<Relation>),
+    Bounded {
+        relations: Vec<Relation>,
+        default: Option<Default<'tcx>>
+    }
+}
+
+// We will use this to store the required information to recapitulate what happened when
+// an error occurs.
+#[derive(Clone)]
+pub struct Default<'tcx> {
+    pub ty: Ty<'tcx>
 }
 
 pub struct Snapshot {
@@ -72,6 +82,13 @@ 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,
+            &Bounded { ref default, .. } => default.clone()
+        }
+    }
+
     pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
         self.values.get(vid.index as usize).diverging
     }
@@ -102,7 +119,7 @@ pub fn instantiate_and_push(
         };
 
         let relations = match old_value {
-            Bounded(b) => b,
+            Bounded { relations, .. } => relations,
             Known(_) => panic!("Asked to instantiate variable that is \
                                already instantiated")
         };
@@ -114,9 +131,11 @@ pub fn instantiate_and_push(
         self.values.record(SpecifyVar(vid, relations));
     }
 
-    pub fn new_var(&mut self, diverging: bool) -> ty::TyVid {
+    pub fn new_var(&mut self,
+                   diverging: bool,
+                   default: Option<Default<'tcx>>) -> ty::TyVid {
         let index = self.values.push(TypeVariableData {
-            value: Bounded(vec![]),
+            value: Bounded { relations: vec![], default: default },
             diverging: diverging
         });
         ty::TyVid { index: index as u32 }
@@ -124,7 +143,7 @@ pub fn new_var(&mut self, diverging: bool) -> ty::TyVid {
 
     pub fn probe(&self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
         match self.values.get(vid.index as usize).value {
-            Bounded(..) => None,
+            Bounded { .. } => None,
             Known(t) => Some(t)
         }
     }
@@ -197,12 +216,14 @@ pub fn types_escaping_snapshot(&self, s: &Snapshot) -> Vec<Ty<'tcx>> {
     }
 
     pub fn unsolved_variables(&self) -> Vec<ty::TyVid> {
-        self.values.iter().enumerate().filter_map(|(i, value)|
-            match &value.value {
+        self.values
+            .iter()
+            .enumerate()
+            .filter_map(|(i, value)| match &value.value {
                 &TypeVariableValue::Known(_) => None,
-                &TypeVariableValue::Bounded(_) => Some(ty::TyVid { index: i as u32 })
-            }
-        ).collect()
+                &TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 })
+            })
+            .collect()
     }
 }
 
@@ -213,7 +234,7 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
     fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
         match action {
             SpecifyVar(vid, relations) => {
-                values[vid.index as usize].value = Bounded(relations);
+                values[vid.index as usize].value = Bounded { relations: relations, default: None };
             }
 
             Relate(a, b) => {
@@ -227,6 +248,6 @@ fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
 fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
     match v.value {
         Known(_) => panic!("var_sub_var: variable is known"),
-        Bounded(ref mut relations) => relations
+        Bounded { ref mut relations, .. } => relations
     }
 }
index ae2b3448e01d383e6dfba29b2c01519a581ed6e8..f6a4dbca291bb759f3aa416b6477a0a39eee98e0 100644 (file)
@@ -87,6 +87,7 @@
 use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
 use middle::def;
 use middle::infer;
+use middle::infer::type_variable;
 use middle::pat_util::{self, pat_id_map};
 use middle::privacy::{AllPublic, LastMod};
 use middle::region::{self, CodeExtent};
@@ -1139,12 +1140,8 @@ fn trait_defines_associated_type_named(&self,
     }
 
     fn ty_infer(&self, default: Option<Ty<'tcx>>, _span: Span) -> Ty<'tcx> {
-        let ty_var = self.infcx().next_ty_var();
-        match default {
-            Some(default) => { self.infcx().defaults.borrow_mut().insert(ty_var, default); }
-            None => {}
-        }
-        ty_var
+        let default = default.map(|t| type_variable::Default { ty: t });
+        self.infcx().next_ty_var_with_default(default)
     }
 
     fn projected_ty_from_poly_trait_ref(&self,
@@ -1697,7 +1694,7 @@ fn check_casts(&self) {
     fn select_all_obligations_and_apply_defaults(&self) {
         use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
 
-        debug!("select_all_obligations_and_apply_defaults: defaults={:?}", self.infcx().defaults);
+        // debug!("select_all_obligations_and_apply_defaults: defaults={:?}", self.infcx().defaults);
 
         for _ in (0..self.tcx().sess.recursion_limit.get()) {
             self.select_obligations_where_possible();
@@ -1725,11 +1722,11 @@ fn select_all_obligations_and_apply_defaults(&self) {
 
             // Collect the set of variables that need fallback applied
             for ty in &unsolved_variables {
-                if self.inh.infcx.defaults.borrow().contains_key(ty) {
+                if let Some(_) = self.inh.infcx.default(ty) {
                     let resolved = self.infcx().resolve_type_vars_if_possible(ty);
 
-                    debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
-                            ty, self.inh.infcx.defaults.borrow().get(ty));
+                    // debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
+                    //         ty, self.inh.infcx.defaults.borrow().get(ty));
 
                     match resolved.sty {
                         ty::TyInfer(ty::TyVar(_)) => {
@@ -1754,7 +1751,6 @@ fn select_all_obligations_and_apply_defaults(&self) {
 
             // Go through the unbound variables and unify them with the proper fallbacks
             for ty in &unbound_tyvars {
-                // let resolved = self.infcx().resolve_type_vars_if_possible(ty);
                 if self.infcx().type_var_diverges(ty) {
                     demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
                 } else {
@@ -1766,17 +1762,16 @@ fn select_all_obligations_and_apply_defaults(&self) {
                             demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
                         }
                         Neither => {
-                            let default_map = self.inh.infcx.defaults.borrow();
-                            if let Some(default) = default_map.get(ty) {
+                            if let Some(default) = self.inh.infcx.default(ty) {
                                 match infer::mk_eqty(self.infcx(), false,
                                                      infer::Misc(codemap::DUMMY_SP),
-                                                     ty, default) {
+                                                     ty, default.ty) {
                                     Ok(()) => { /* ok */ }
                                     Err(_) => {
                                         self.infcx().report_conflicting_default_types(
                                             codemap::DUMMY_SP,
                                             ty,
-                                            default)
+                                            default.ty)
                                     }
                                 }
                             }
diff --git a/src/test/run-pass/default_type_parameter_default_dependent_associated_type.rs b/src/test/run-pass/default_type_parameter_default_dependent_associated_type.rs
new file mode 100644 (file)
index 0000000..402399f
--- /dev/null
@@ -0,0 +1,23 @@
+use std::marker::PhantomData;
+
+trait Id {
+    type This;
+}
+
+impl<A> Id for A {
+    type This = A;
+}
+
+struct Foo<X: Default = usize, Y = <X as Id>::This> {
+    data: PhantomData<(X, Y)>
+}
+
+impl<X: Default, Y> Foo<X, Y> {
+    fn new() -> Foo<X, Y> {
+        Foo { data: PhantomData }
+    }
+}
+
+fn main() {
+    let foo = Foo::new();
+}
diff --git a/src/test/run-pass/default_type_parameter_dependent_defaults.rs b/src/test/run-pass/default_type_parameter_dependent_defaults.rs
new file mode 100644 (file)
index 0000000..4f492be
--- /dev/null
@@ -0,0 +1,7 @@
+use std::marker::PhantomData;
+
+struct Foo<T,U=T> { data: PhantomData<(T, U)> }
+
+fn main() {
+    let foo = Foo { data: PhantomData };
+}
diff --git a/src/test/run-pass/default_type_parameter_struct_and_type_alias.rs b/src/test/run-pass/default_type_parameter_struct_and_type_alias.rs
new file mode 100644 (file)
index 0000000..d42e65d
--- /dev/null
@@ -0,0 +1,30 @@
+use std::marker::PhantomData;
+
+trait TypeEq<A> {}
+impl<A> TypeEq<A> for A {}
+
+struct DeterministicHasher;
+struct RandomHasher;
+
+
+struct MyHashMap<K, V, H=DeterministicHasher> {
+    data: PhantomData<(K, V, H)>
+}
+
+impl<K, V, H> MyHashMap<K, V, H> {
+    fn new() -> MyHashMap<K, V, H> {
+        MyHashMap { data: PhantomData }
+    }
+}
+
+mod mystd {
+    use super::{MyHashMap, RandomHasher};
+    pub type HashMap<K, V, H=RandomHasher> = MyHashMap<K, V, H>;
+}
+
+fn try_me<H>(hash_map: mystd::HashMap<i32, i32, H>) {}
+
+fn main() {
+    let hash_map = mystd::HashMap::new();
+    try_me(hash_map);
+}