Skip to content

Commit d9b1983

Browse files
committed
Remove defaults table and attach defaults directly to tyvars
1 parent 2bec590 commit d9b1983

File tree

6 files changed

+143
-41
lines changed

6 files changed

+143
-41
lines changed

src/librustc/middle/infer/mod.rs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,6 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
9595
normalize: bool,
9696

9797
err_count_on_creation: usize,
98-
99-
// Default Type Parameter fallbacks
100-
pub defaults: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
10198
}
10299

103100
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -356,8 +353,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
356353
parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
357354
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
358355
normalize: false,
359-
err_count_on_creation: tcx.sess.err_count(),
360-
defaults: RefCell::new(FnvHashMap()),
356+
err_count_on_creation: tcx.sess.err_count()
361357
}
362358
}
363359

@@ -660,27 +656,44 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
660656
}
661657
}
662658

659+
/// Returns a type variable's default fallback if any exists. A default
660+
/// must be attached to the variable when created, if it is created
661+
/// without a default, this will return None.
662+
///
663+
/// See `new_ty_var_with_default` to create a type variable with a default.
664+
/// See `type_variable::Default` for details about what a default entails.
665+
pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
666+
match ty.sty {
667+
ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
668+
_ => None
669+
}
670+
}
671+
663672
pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
664673
let mut variables = Vec::new();
665674

666675
let unbound_ty_vars = self.type_variables
667676
.borrow()
668677
.unsolved_variables()
669-
.into_iter().map(|t| self.tcx.mk_var(t));
678+
.into_iter()
679+
.map(|t| self.tcx.mk_var(t));
670680

671681
let unbound_int_vars = self.int_unification_table
672682
.borrow_mut()
673683
.unsolved_variables()
674-
.into_iter().map(|v| self.tcx.mk_int_var(v));
684+
.into_iter()
685+
.map(|v| self.tcx.mk_int_var(v));
675686

676687
let unbound_float_vars = self.float_unification_table
677688
.borrow_mut()
678689
.unsolved_variables()
679-
.into_iter().map(|v| self.tcx.mk_float_var(v));
690+
.into_iter()
691+
.map(|v| self.tcx.mk_float_var(v));
680692

681693
variables.extend(unbound_ty_vars);
682694
variables.extend(unbound_int_vars);
683695
variables.extend(unbound_float_vars);
696+
684697
return variables;
685698
}
686699

@@ -985,13 +998,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
985998
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {
986999
self.type_variables
9871000
.borrow_mut()
988-
.new_var(diverging)
1001+
.new_var(diverging, None)
9891002
}
9901003

9911004
pub fn next_ty_var(&self) -> Ty<'tcx> {
9921005
self.tcx.mk_var(self.next_ty_var_id(false))
9931006
}
9941007

1008+
pub fn next_ty_var_with_default(&self,
1009+
default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
1010+
let ty_var_id = self.type_variables
1011+
.borrow_mut()
1012+
.new_var(false, default);
1013+
1014+
self.tcx.mk_var(ty_var_id)
1015+
}
1016+
9951017
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
9961018
self.tcx.mk_var(self.next_ty_var_id(true))
9971019
}
@@ -1028,14 +1050,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10281050
pub fn type_vars_for_defs(&self,
10291051
defs: &[ty::TypeParameterDef<'tcx>])
10301052
-> Vec<ty::Ty<'tcx>> {
1053+
let mut substs = Substs::empty();
10311054
let mut vars = Vec::with_capacity(defs.len());
10321055

10331056
for def in defs.iter() {
1034-
let ty_var = self.next_ty_var();
1035-
match def.default {
1036-
None => {},
1037-
Some(default) => { self.defaults.borrow_mut().insert(ty_var, default); }
1038-
}
1057+
let default = def.default.map(|default| {
1058+
type_variable::Default {
1059+
ty: default
1060+
}
1061+
});
1062+
//.subst(self.tcx, &substs)
1063+
let ty_var = self.next_ty_var_with_default(default);
1064+
substs.types.push(subst::ParamSpace::SelfSpace, ty_var);
10391065
vars.push(ty_var)
10401066
}
10411067

src/librustc/middle/infer/type_variable.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,17 @@ struct TypeVariableData<'tcx> {
3030

3131
enum TypeVariableValue<'tcx> {
3232
Known(Ty<'tcx>),
33-
Bounded(Vec<Relation>),
33+
Bounded {
34+
relations: Vec<Relation>,
35+
default: Option<Default<'tcx>>
36+
}
37+
}
38+
39+
// We will use this to store the required information to recapitulate what happened when
40+
// an error occurs.
41+
#[derive(Clone)]
42+
pub struct Default<'tcx> {
43+
pub ty: Ty<'tcx>
3444
}
3545

3646
pub struct Snapshot {
@@ -72,6 +82,13 @@ impl<'tcx> TypeVariableTable<'tcx> {
7282
relations(self.values.get_mut(a.index as usize))
7383
}
7484

85+
pub fn default(&self, vid: ty::TyVid) -> Option<Default<'tcx>> {
86+
match &self.values.get(vid.index as usize).value {
87+
&Known(_) => None,
88+
&Bounded { ref default, .. } => default.clone()
89+
}
90+
}
91+
7592
pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
7693
self.values.get(vid.index as usize).diverging
7794
}
@@ -102,7 +119,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
102119
};
103120

104121
let relations = match old_value {
105-
Bounded(b) => b,
122+
Bounded { relations, .. } => relations,
106123
Known(_) => panic!("Asked to instantiate variable that is \
107124
already instantiated")
108125
};
@@ -114,17 +131,19 @@ impl<'tcx> TypeVariableTable<'tcx> {
114131
self.values.record(SpecifyVar(vid, relations));
115132
}
116133

117-
pub fn new_var(&mut self, diverging: bool) -> ty::TyVid {
134+
pub fn new_var(&mut self,
135+
diverging: bool,
136+
default: Option<Default<'tcx>>) -> ty::TyVid {
118137
let index = self.values.push(TypeVariableData {
119-
value: Bounded(vec![]),
138+
value: Bounded { relations: vec![], default: default },
120139
diverging: diverging
121140
});
122141
ty::TyVid { index: index as u32 }
123142
}
124143

125144
pub fn probe(&self, vid: ty::TyVid) -> Option<Ty<'tcx>> {
126145
match self.values.get(vid.index as usize).value {
127-
Bounded(..) => None,
146+
Bounded { .. } => None,
128147
Known(t) => Some(t)
129148
}
130149
}
@@ -197,12 +216,14 @@ impl<'tcx> TypeVariableTable<'tcx> {
197216
}
198217

199218
pub fn unsolved_variables(&self) -> Vec<ty::TyVid> {
200-
self.values.iter().enumerate().filter_map(|(i, value)|
201-
match &value.value {
219+
self.values
220+
.iter()
221+
.enumerate()
222+
.filter_map(|(i, value)| match &value.value {
202223
&TypeVariableValue::Known(_) => None,
203-
&TypeVariableValue::Bounded(_) => Some(ty::TyVid { index: i as u32 })
204-
}
205-
).collect()
224+
&TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 })
225+
})
226+
.collect()
206227
}
207228
}
208229

@@ -213,7 +234,7 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
213234
fn reverse(values: &mut Vec<TypeVariableData<'tcx>>, action: UndoEntry) {
214235
match action {
215236
SpecifyVar(vid, relations) => {
216-
values[vid.index as usize].value = Bounded(relations);
237+
values[vid.index as usize].value = Bounded { relations: relations, default: None };
217238
}
218239

219240
Relate(a, b) => {
@@ -227,6 +248,6 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
227248
fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
228249
match v.value {
229250
Known(_) => panic!("var_sub_var: variable is known"),
230-
Bounded(ref mut relations) => relations
251+
Bounded { ref mut relations, .. } => relations
231252
}
232253
}

src/librustc_typeck/check/mod.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ use fmt_macros::{Parser, Piece, Position};
8787
use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
8888
use middle::def;
8989
use middle::infer;
90+
use middle::infer::type_variable;
9091
use middle::pat_util::{self, pat_id_map};
9192
use middle::privacy::{AllPublic, LastMod};
9293
use middle::region::{self, CodeExtent};
@@ -1133,12 +1134,8 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
11331134
}
11341135

11351136
fn ty_infer(&self, default: Option<Ty<'tcx>>, _span: Span) -> Ty<'tcx> {
1136-
let ty_var = self.infcx().next_ty_var();
1137-
match default {
1138-
Some(default) => { self.infcx().defaults.borrow_mut().insert(ty_var, default); }
1139-
None => {}
1140-
}
1141-
ty_var
1137+
let default = default.map(|t| type_variable::Default { ty: t });
1138+
self.infcx().next_ty_var_with_default(default)
11421139
}
11431140

11441141
fn projected_ty_from_poly_trait_ref(&self,
@@ -1691,7 +1688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16911688
fn select_all_obligations_and_apply_defaults(&self) {
16921689
use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
16931690

1694-
debug!("select_all_obligations_and_apply_defaults: defaults={:?}", self.infcx().defaults);
1691+
// debug!("select_all_obligations_and_apply_defaults: defaults={:?}", self.infcx().defaults);
16951692

16961693
for _ in (0..self.tcx().sess.recursion_limit.get()) {
16971694
self.select_obligations_where_possible();
@@ -1719,11 +1716,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17191716

17201717
// Collect the set of variables that need fallback applied
17211718
for ty in &unsolved_variables {
1722-
if self.inh.infcx.defaults.borrow().contains_key(ty) {
1719+
if let Some(_) = self.inh.infcx.default(ty) {
17231720
let resolved = self.infcx().resolve_type_vars_if_possible(ty);
17241721

1725-
debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
1726-
ty, self.inh.infcx.defaults.borrow().get(ty));
1722+
// debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}",
1723+
// ty, self.inh.infcx.defaults.borrow().get(ty));
17271724

17281725
match resolved.sty {
17291726
ty::TyInfer(ty::TyVar(_)) => {
@@ -1748,7 +1745,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17481745

17491746
// Go through the unbound variables and unify them with the proper fallbacks
17501747
for ty in &unbound_tyvars {
1751-
// let resolved = self.infcx().resolve_type_vars_if_possible(ty);
17521748
if self.infcx().type_var_diverges(ty) {
17531749
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
17541750
} else {
@@ -1760,17 +1756,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17601756
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
17611757
}
17621758
Neither => {
1763-
let default_map = self.inh.infcx.defaults.borrow();
1764-
if let Some(default) = default_map.get(ty) {
1759+
if let Some(default) = self.inh.infcx.default(ty) {
17651760
match infer::mk_eqty(self.infcx(), false,
17661761
infer::Misc(codemap::DUMMY_SP),
1767-
ty, default) {
1762+
ty, default.ty) {
17681763
Ok(()) => { /* ok */ }
17691764
Err(_) => {
17701765
self.infcx().report_conflicting_default_types(
17711766
codemap::DUMMY_SP,
17721767
ty,
1773-
default)
1768+
default.ty)
17741769
}
17751770
}
17761771
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use std::marker::PhantomData;
2+
3+
trait Id {
4+
type This;
5+
}
6+
7+
impl<A> Id for A {
8+
type This = A;
9+
}
10+
11+
struct Foo<X: Default = usize, Y = <X as Id>::This> {
12+
data: PhantomData<(X, Y)>
13+
}
14+
15+
impl<X: Default, Y> Foo<X, Y> {
16+
fn new() -> Foo<X, Y> {
17+
Foo { data: PhantomData }
18+
}
19+
}
20+
21+
fn main() {
22+
let foo = Foo::new();
23+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use std::marker::PhantomData;
2+
3+
struct Foo<T,U=T> { data: PhantomData<(T, U)> }
4+
5+
fn main() {
6+
let foo = Foo { data: PhantomData };
7+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::marker::PhantomData;
2+
3+
trait TypeEq<A> {}
4+
impl<A> TypeEq<A> for A {}
5+
6+
struct DeterministicHasher;
7+
struct RandomHasher;
8+
9+
10+
struct MyHashMap<K, V, H=DeterministicHasher> {
11+
data: PhantomData<(K, V, H)>
12+
}
13+
14+
impl<K, V, H> MyHashMap<K, V, H> {
15+
fn new() -> MyHashMap<K, V, H> {
16+
MyHashMap { data: PhantomData }
17+
}
18+
}
19+
20+
mod mystd {
21+
use super::{MyHashMap, RandomHasher};
22+
pub type HashMap<K, V, H=RandomHasher> = MyHashMap<K, V, H>;
23+
}
24+
25+
fn try_me<H>(hash_map: mystd::HashMap<i32, i32, H>) {}
26+
27+
fn main() {
28+
let hash_map = mystd::HashMap::new();
29+
try_me(hash_map);
30+
}

0 commit comments

Comments
 (0)