Remove defaults table and attach defaults directly to tyvars

This commit is contained in:
Jared Roesch 2015-07-09 12:15:48 -07:00 committed by Jared Roesch
parent bbdca2c8ad
commit 49eb2c6763
6 changed files with 143 additions and 41 deletions

View 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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
/// 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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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)
}

View 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 @@ impl<'tcx> TypeVariableTable<'tcx> {
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 @@ impl<'tcx> TypeVariableTable<'tcx> {
};
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 @@ impl<'tcx> TypeVariableTable<'tcx> {
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 @@ impl<'tcx> TypeVariableTable<'tcx> {
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 @@ impl<'tcx> TypeVariableTable<'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 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
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
}
}

View File

@ -87,6 +87,7 @@ use fmt_macros::{Parser, Piece, Position};
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 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
}
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
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)
}
}
}

View File

@ -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();
}

View File

@ -0,0 +1,7 @@
use std::marker::PhantomData;
struct Foo<T,U=T> { data: PhantomData<(T, U)> }
fn main() {
let foo = Foo { data: PhantomData };
}

View File

@ -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);
}