From: Jared Roesch Date: Thu, 9 Jul 2015 19:15:48 +0000 (-0700) Subject: Remove defaults table and attach defaults directly to tyvars X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=49eb2c6763e68ee462b5808ab558b4fa9f84fcc0;p=rust.git Remove defaults table and attach defaults directly to tyvars --- diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 59ca795e5f7..db6e0ad1d4a 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -95,9 +95,6 @@ pub struct InferCtxt<'a, 'tcx: 'a> { normalize: bool, err_count_on_creation: usize, - - // Default Type Parameter fallbacks - pub defaults: RefCell, 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> { + match ty.sty { + ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid), + _ => None + } + } + pub fn unsolved_variables(&self) -> Vec> { 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>) -> 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> { + 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) } diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index ebecb0898b4..6ba289d3665 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -30,7 +30,17 @@ struct TypeVariableData<'tcx> { enum TypeVariableValue<'tcx> { Known(Ty<'tcx>), - Bounded(Vec), + Bounded { + relations: Vec, + default: Option> + } +} + +// 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 { 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, + &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>) -> 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> { 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> { } pub fn unsolved_variables(&self) -> Vec { - 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>, 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>, action: UndoEntry) { fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec { match v.value { Known(_) => panic!("var_sub_var: variable is known"), - Bounded(ref mut relations) => relations + Bounded { ref mut relations, .. } => relations } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ae2b3448e01..f6a4dbca291 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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>, _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 index 00000000000..402399f14b9 --- /dev/null +++ b/src/test/run-pass/default_type_parameter_default_dependent_associated_type.rs @@ -0,0 +1,23 @@ +use std::marker::PhantomData; + +trait Id { + type This; +} + +impl Id for A { + type This = A; +} + +struct Foo::This> { + data: PhantomData<(X, Y)> +} + +impl Foo { + fn new() -> Foo { + 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 index 00000000000..4f492bed9d4 --- /dev/null +++ b/src/test/run-pass/default_type_parameter_dependent_defaults.rs @@ -0,0 +1,7 @@ +use std::marker::PhantomData; + +struct Foo { 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 index 00000000000..d42e65d90fe --- /dev/null +++ b/src/test/run-pass/default_type_parameter_struct_and_type_alias.rs @@ -0,0 +1,30 @@ +use std::marker::PhantomData; + +trait TypeEq {} +impl TypeEq for A {} + +struct DeterministicHasher; +struct RandomHasher; + + +struct MyHashMap { + data: PhantomData<(K, V, H)> +} + +impl MyHashMap { + fn new() -> MyHashMap { + MyHashMap { data: PhantomData } + } +} + +mod mystd { + use super::{MyHashMap, RandomHasher}; + pub type HashMap = MyHashMap; +} + +fn try_me(hash_map: mystd::HashMap) {} + +fn main() { + let hash_map = mystd::HashMap::new(); + try_me(hash_map); +}