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
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()
}
}
}
}
+ /// 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;
}
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))
}
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)
}
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 {
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
}
};
let relations = match old_value {
- Bounded(b) => b,
+ Bounded { relations, .. } => relations,
Known(_) => panic!("Asked to instantiate variable that is \
already instantiated")
};
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 }
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)
}
}
}
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()
}
}
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) => {
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
}
}
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};
}
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,
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();
// 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(_)) => {
// 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 {
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)
}
}
}
--- /dev/null
+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();
+}
--- /dev/null
+use std::marker::PhantomData;
+
+struct Foo<T,U=T> { data: PhantomData<(T, U)> }
+
+fn main() {
+ let foo = Foo { data: PhantomData };
+}
--- /dev/null
+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);
+}