Skip to content

Commit d2f8074

Browse files
committed
Add a 4th space for associated types defined in a trait (currently unused)
1 parent 94d142b commit d2f8074

File tree

8 files changed

+85
-69
lines changed

8 files changed

+85
-69
lines changed

src/librustc/middle/astencode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,8 +717,9 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
717717
{
718718
let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
719719
let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
720+
let assocs = self.read_to_vec(|this| Ok(f(this))).unwrap();
720721
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
721-
VecPerParamSpace::new(types, selfs, fns)
722+
VecPerParamSpace::new(types, selfs, assocs, fns)
722723
}
723724

724725
fn read_vtable_res_with_key(&mut self,

src/librustc/middle/subst.rs

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,17 @@ impl Substs {
112112
r: Vec<ty::Region>)
113113
-> Substs
114114
{
115-
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
116-
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
115+
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new(), Vec::new()),
116+
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
117117
}
118118

119119
pub fn new_trait(t: Vec<ty::t>,
120120
r: Vec<ty::Region>,
121121
s: ty::t)
122122
-> Substs
123123
{
124-
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
125-
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
124+
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new(), Vec::new()),
125+
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
126126
}
127127

128128
pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
@@ -226,29 +226,32 @@ impl RegionSubsts {
226226
#[deriving(PartialOrd, Ord, PartialEq, Eq,
227227
Clone, Hash, Encodable, Decodable, Show)]
228228
pub enum ParamSpace {
229-
TypeSpace, // Type parameters attached to a type definition, trait, or impl
230-
SelfSpace, // Self parameter on a trait
231-
FnSpace, // Type parameters attached to a method or fn
229+
TypeSpace, // Type parameters attached to a type definition, trait, or impl
230+
SelfSpace, // Self parameter on a trait
231+
AssocSpace, // Assoc types defined in a trait/impl
232+
FnSpace, // Type parameters attached to a method or fn
232233
}
233234

234235
impl ParamSpace {
235-
pub fn all() -> [ParamSpace, ..3] {
236-
[TypeSpace, SelfSpace, FnSpace]
236+
pub fn all() -> [ParamSpace, ..4] {
237+
[TypeSpace, SelfSpace, AssocSpace, FnSpace]
237238
}
238239

239240
pub fn to_uint(self) -> uint {
240241
match self {
241242
TypeSpace => 0,
242243
SelfSpace => 1,
243-
FnSpace => 2,
244+
AssocSpace => 2,
245+
FnSpace => 3,
244246
}
245247
}
246248

247249
pub fn from_uint(u: uint) -> ParamSpace {
248250
match u {
249251
0 => TypeSpace,
250252
1 => SelfSpace,
251-
2 => FnSpace,
253+
2 => AssocSpace,
254+
3 => FnSpace,
252255
_ => panic!("Invalid ParamSpace: {}", u)
253256
}
254257
}
@@ -268,11 +271,13 @@ pub struct VecPerParamSpace<T> {
268271
// Here is how the representation corresponds to the abstraction
269272
// i.e. the "abstraction function" AF:
270273
//
271-
// AF(self) = (self.content.slice_to(self.type_limit),
272-
// self.content.slice(self.type_limit, self.self_limit),
273-
// self.content.slice_from(self.self_limit))
274+
// AF(self) = (self.content[..self.type_limit],
275+
// self.content[self.type_limit..self.self_limit],
276+
// self.content[self.self_limit..self.assoc_limit],
277+
// self.content[self.assoc_limit..])
274278
type_limit: uint,
275279
self_limit: uint,
280+
assoc_limit: uint,
276281
content: Vec<T>,
277282
}
278283

@@ -292,14 +297,16 @@ impl<T> VecPerParamSpace<T> {
292297
match space {
293298
TypeSpace => (0, self.type_limit),
294299
SelfSpace => (self.type_limit, self.self_limit),
295-
FnSpace => (self.self_limit, self.content.len()),
300+
AssocSpace => (self.self_limit, self.assoc_limit),
301+
FnSpace => (self.assoc_limit, self.content.len()),
296302
}
297303
}
298304

299305
pub fn empty() -> VecPerParamSpace<T> {
300306
VecPerParamSpace {
301307
type_limit: 0,
302308
self_limit: 0,
309+
assoc_limit: 0,
303310
content: Vec::new()
304311
}
305312
}
@@ -310,26 +317,33 @@ impl<T> VecPerParamSpace<T> {
310317

311318
/// `t` is the type space.
312319
/// `s` is the self space.
320+
/// `a` is the assoc space.
313321
/// `f` is the fn space.
314-
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
322+
pub fn new(t: Vec<T>, s: Vec<T>, a: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
315323
let type_limit = t.len();
316-
let self_limit = t.len() + s.len();
324+
let self_limit = type_limit + s.len();
325+
let assoc_limit = self_limit + a.len();
326+
317327
let mut content = t;
318328
content.extend(s.into_iter());
329+
content.extend(a.into_iter());
319330
content.extend(f.into_iter());
331+
320332
VecPerParamSpace {
321333
type_limit: type_limit,
322334
self_limit: self_limit,
335+
assoc_limit: assoc_limit,
323336
content: content,
324337
}
325338
}
326339

327-
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
340+
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint, assoc_limit: uint)
328341
-> VecPerParamSpace<T>
329342
{
330343
VecPerParamSpace {
331344
type_limit: type_limit,
332345
self_limit: self_limit,
346+
assoc_limit: assoc_limit,
333347
content: content,
334348
}
335349
}
@@ -341,9 +355,10 @@ impl<T> VecPerParamSpace<T> {
341355
pub fn push(&mut self, space: ParamSpace, value: T) {
342356
let (_, limit) = self.limits(space);
343357
match space {
344-
TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
345-
SelfSpace => { self.self_limit += 1; }
346-
FnSpace => {}
358+
TypeSpace => { self.type_limit += 1; self.self_limit += 1; self.assoc_limit += 1; }
359+
SelfSpace => { self.self_limit += 1; self.assoc_limit += 1; }
360+
AssocSpace => { self.assoc_limit += 1; }
361+
FnSpace => { }
347362
}
348363
self.content.insert(limit, value);
349364
}
@@ -354,9 +369,10 @@ impl<T> VecPerParamSpace<T> {
354369
None
355370
} else {
356371
match space {
357-
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
358-
SelfSpace => { self.self_limit -= 1; }
359-
FnSpace => {}
372+
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; self.assoc_limit -= 1; }
373+
SelfSpace => { self.self_limit -= 1; self.assoc_limit -= 1; }
374+
AssocSpace => { self.assoc_limit -= 1; }
375+
FnSpace => {}
360376
}
361377
self.content.remove(limit - 1)
362378
}
@@ -442,35 +458,29 @@ impl<T> VecPerParamSpace<T> {
442458
let result = self.iter().map(pred).collect();
443459
VecPerParamSpace::new_internal(result,
444460
self.type_limit,
445-
self.self_limit)
461+
self.self_limit,
462+
self.assoc_limit)
446463
}
447464

448465
pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
449-
let (t, s, f) = self.split();
466+
let (t, s, a, f) = self.split();
450467
VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
451468
s.into_iter().map(|p| pred(p)).collect(),
469+
a.into_iter().map(|p| pred(p)).collect(),
452470
f.into_iter().map(|p| pred(p)).collect())
453471
}
454472

455-
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
456-
// FIXME (#15418): this does two traversals when in principle
457-
// one would suffice. i.e. change to use `move_iter`.
458-
let VecPerParamSpace { type_limit, self_limit, content } = self;
459-
let mut i = 0;
460-
let (prefix, fn_vec) = content.partition(|_| {
461-
let on_left = i < self_limit;
462-
i += 1;
463-
on_left
464-
});
473+
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>, Vec<T>) {
474+
let VecPerParamSpace { type_limit, self_limit, assoc_limit, content } = self;
475+
476+
let mut content_iter = content.into_iter();
465477

466-
let mut i = 0;
467-
let (type_vec, self_vec) = prefix.partition(|_| {
468-
let on_left = i < type_limit;
469-
i += 1;
470-
on_left
471-
});
478+
let types = content_iter.by_ref().take(type_limit).collect();
479+
let selfs = content_iter.by_ref().take(self_limit - type_limit).collect();
480+
let assocs = content_iter.by_ref().take(assoc_limit - self_limit).collect();
481+
let fns = content_iter.collect();
472482

473-
(type_vec, self_vec, fn_vec)
483+
(types, selfs, assocs, fns)
474484
}
475485

476486
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
@@ -616,12 +626,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
616626
this.tcx().sess.span_bug(
617627
span,
618628
format!("Type parameter `{}` ({}/{}/{}) out of range \
619-
when substituting (root type={})",
629+
when substituting (root type={}) substs={}",
620630
p.repr(this.tcx()),
621631
source_ty.repr(this.tcx()),
622632
space,
623633
index,
624-
this.root_ty.repr(this.tcx())).as_slice());
634+
this.root_ty.repr(this.tcx()),
635+
this.substs.repr(this.tcx())).as_slice());
625636
}
626637
}
627638
}

src/librustc/middle/traits/select.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1607,7 +1607,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16071607
Ok(o) => o,
16081608
Err(ErrorReported) => Vec::new()
16091609
};
1610-
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
1610+
let obligations = VecPerParamSpace::new(obligations, Vec::new(),
1611+
Vec::new(), Vec::new());
16111612
VtableBuiltinData { nested: obligations }
16121613
}
16131614

src/librustc/middle/trans/meth.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ pub fn trans_static_method_callee(bcx: Block,
205205
// type parameters that belong to the trait but also some that
206206
// belong to the method:
207207
let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
208-
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.split();
208+
let (rcvr_type, rcvr_self, rcvr_assoc, rcvr_method) = rcvr_substs.types.split();
209209

210210
// Lookup the precise impl being called. To do that, we need to
211211
// create a trait reference identifying the self type and other
@@ -232,6 +232,7 @@ pub fn trans_static_method_callee(bcx: Block,
232232
let trait_substs =
233233
Substs::erased(VecPerParamSpace::new(rcvr_type,
234234
rcvr_self,
235+
rcvr_assoc,
235236
Vec::new()));
236237
debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
237238
let trait_ref = Rc::new(ty::TraitRef { def_id: trait_id,
@@ -265,10 +266,11 @@ pub fn trans_static_method_callee(bcx: Block,
265266
// that with the `rcvr_method` from before, which tells us
266267
// the type parameters from the *method*, to yield
267268
// `callee_substs=[[T=int],[],[U=String]]`.
268-
let (impl_type, impl_self, _) = impl_substs.types.split();
269+
let (impl_type, impl_self, impl_assoc, _) = impl_substs.types.split();
269270
let callee_substs =
270271
Substs::erased(VecPerParamSpace::new(impl_type,
271272
impl_self,
273+
impl_assoc,
272274
rcvr_method));
273275

274276
let mth_id = method_with_name(ccx, impl_did, mname);
@@ -397,12 +399,12 @@ fn combine_impl_and_methods_tps(bcx: Block,
397399

398400
// Break apart the type parameters from the node and type
399401
// parameters from the receiver.
400-
let (_, _, node_method) = node_substs.types.split();
401-
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.clone().split();
402+
let (_, _, _, node_method) = node_substs.types.split();
403+
let (rcvr_type, rcvr_self, rcvr_assoc, rcvr_method) = rcvr_substs.types.clone().split();
402404
assert!(rcvr_method.is_empty());
403405
subst::Substs {
404406
regions: subst::ErasedRegions,
405-
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
407+
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, rcvr_assoc, node_method)
406408
}
407409
}
408410

src/librustc/util/ppaux.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -666,10 +666,11 @@ impl Repr for subst::Substs {
666666

667667
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
668668
fn repr(&self, tcx: &ctxt) -> String {
669-
format!("[{};{};{}]",
670-
self.get_slice(subst::TypeSpace).repr(tcx),
671-
self.get_slice(subst::SelfSpace).repr(tcx),
672-
self.get_slice(subst::FnSpace).repr(tcx))
669+
format!("[{};{};{};{}]",
670+
self.get_slice(subst::TypeSpace).repr(tcx),
671+
self.get_slice(subst::SelfSpace).repr(tcx),
672+
self.get_slice(subst::AssocSpace).repr(tcx),
673+
self.get_slice(subst::FnSpace).repr(tcx))
673674
}
674675
}
675676

src/test/compile-fail/variance-regions-direct.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
// Regions that just appear in normal spots are contravariant:
1515

1616
#[rustc_variance]
17-
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
17+
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]]
1818
x: &'a int,
1919
y: &'b [int],
2020
c: &'c str
@@ -23,7 +23,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
2323
// Those same annotations in function arguments become covariant:
2424

2525
#[rustc_variance]
26-
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
26+
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]]
2727
x: extern "Rust" fn(&'a int),
2828
y: extern "Rust" fn(&'b [int]),
2929
c: extern "Rust" fn(&'c str),
@@ -32,15 +32,15 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
3232
// Mutability induces invariance:
3333

3434
#[rustc_variance]
35-
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
35+
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]]
3636
x: &'a mut &'b int,
3737
}
3838

3939
// Mutability induces invariance, even when in a
4040
// contravariant context:
4141

4242
#[rustc_variance]
43-
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
43+
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]]
4444
x: extern "Rust" fn(&'a mut &'b int),
4545
}
4646

@@ -50,21 +50,21 @@ struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
5050
// argument list occurs in an invariant context.
5151

5252
#[rustc_variance]
53-
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
53+
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[];[]]
5454
x: &'a mut extern "Rust" fn(&'b int),
5555
}
5656

5757
// No uses at all is bivariant:
5858

5959
#[rustc_variance]
60-
struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
60+
struct Test7<'a> { //~ ERROR regions=[[*];[];[];[]]
6161
x: int
6262
}
6363

6464
// Try enums too.
6565

6666
#[rustc_variance]
67-
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
67+
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
6868
Test8A(extern "Rust" fn(&'a int)),
6969
Test8B(&'b [int]),
7070
Test8C(&'b mut &'c str),

0 commit comments

Comments
 (0)