Remove defaults table and attach defaults directly to tyvars
This commit is contained in:
parent
bbdca2c8ad
commit
49eb2c6763
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Foo<T,U=T> { data: PhantomData<(T, U)> }
|
||||
|
||||
fn main() {
|
||||
let foo = Foo { data: PhantomData };
|
||||
}
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user