Skip to content

Commit 4404592

Browse files
committed
Implement associated type projection and normalization.
1 parent f95bb55 commit 4404592

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2478
-1516
lines changed

src/librustc/metadata/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,3 +256,6 @@ pub const tag_predicate_space: uint = 0xa9;
256256
pub const tag_predicate_data: uint = 0xb0;
257257

258258
pub const tag_unsafety: uint = 0xb1;
259+
260+
pub const tag_associated_type_names: uint = 0xb2;
261+
pub const tag_associated_type_name: uint = 0xb3;

src/librustc/metadata/decoder.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,17 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
369369
}
370370
}
371371

372+
fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
373+
let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
374+
let mut names = Vec::new();
375+
reader::tagged_docs(names_doc, tag_associated_type_name, |name_doc| {
376+
let name = token::intern(name_doc.as_str_slice());
377+
names.push(name);
378+
true
379+
});
380+
names
381+
}
382+
372383
pub fn get_trait_def<'tcx>(cdata: Cmd,
373384
item_id: ast::NodeId,
374385
tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
@@ -377,12 +388,14 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
377388
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
378389
let bounds = trait_def_bounds(item_doc, tcx, cdata);
379390
let unsafety = parse_unsafety(item_doc);
391+
let associated_type_names = parse_associated_type_names(item_doc);
380392

381393
ty::TraitDef {
382394
unsafety: unsafety,
383395
generics: generics,
384396
bounds: bounds,
385-
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
397+
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)),
398+
associated_type_names: associated_type_names,
386399
}
387400
}
388401

src/librustc/metadata/encoder.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
13161316
encode_item_variances(rbml_w, ecx, item.id);
13171317
let trait_def = ty::lookup_trait_def(tcx, def_id);
13181318
encode_unsafety(rbml_w, trait_def.unsafety);
1319+
encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
13191320
encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
13201321
encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
13211322
encode_name(rbml_w, item.ident.name);
@@ -1689,6 +1690,14 @@ fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
16891690
rbml_w.wr_tagged_u8(tag_unsafety, byte);
16901691
}
16911692

1693+
fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
1694+
rbml_w.start_tag(tag_associated_type_names);
1695+
for &name in names.iter() {
1696+
rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get());
1697+
}
1698+
rbml_w.end_tag();
1699+
}
1700+
16921701
fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
16931702
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
16941703
// Pull the cnums and name,vers,hash out of cstore

src/librustc/metadata/tydecode.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,12 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
504504
return ty::mk_unboxed_closure(st.tcx, did,
505505
st.tcx.mk_region(region), st.tcx.mk_substs(substs));
506506
}
507+
'P' => {
508+
assert_eq!(next(st), '[');
509+
let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
510+
let name = token::str_to_ident(parse_str(st, ']').as_slice()).name;
511+
return ty::mk_projection(tcx, trait_ref, name);
512+
}
507513
'e' => {
508514
return tcx.types.err;
509515
}
@@ -683,17 +689,32 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
683689
-> ty::Predicate<'tcx>
684690
{
685691
match next(st) {
686-
't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
692+
't' => ty::Binder(Rc::new(parse_trait_ref(st, conv))).as_predicate(),
687693
'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
688694
parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
689695
'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
690696
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
691697
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
692698
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
699+
'p' => ty::Binder(parse_projection_predicate(st, conv)).as_predicate(),
693700
c => panic!("Encountered invalid character in metadata: {}", c)
694701
}
695702
}
696703

704+
fn parse_projection_predicate<'a,'tcx>(
705+
st: &mut PState<'a, 'tcx>,
706+
conv: conv_did)
707+
-> ty::ProjectionPredicate<'tcx>
708+
{
709+
ty::ProjectionPredicate {
710+
projection_ty: ty::ProjectionTy {
711+
trait_ref: Rc::new(parse_trait_ref(st, |x,y| conv(x,y))),
712+
item_name: token::str_to_ident(parse_str(st, '|').as_slice()).name,
713+
},
714+
ty: parse_ty(st, |x,y| conv(x,y)),
715+
}
716+
}
717+
697718
pub fn parse_type_param_def_data<'tcx>(data: &[u8], start: uint,
698719
crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
699720
conv: conv_did) -> ty::TypeParameterDef<'tcx>
@@ -710,10 +731,6 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
710731
assert_eq!(next(st), '|');
711732
let index = parse_u32(st);
712733
assert_eq!(next(st), '|');
713-
let associated_with = parse_opt(st, |st| {
714-
parse_def(st, NominalType, |x,y| conv(x,y))
715-
});
716-
assert_eq!(next(st), '|');
717734
let bounds = parse_bounds(st, |x,y| conv(x,y));
718735
let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
719736

@@ -722,7 +739,6 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
722739
def_id: def_id,
723740
space: space,
724741
index: index,
725-
associated_with: associated_with,
726742
bounds: bounds,
727743
default: default
728744
}
@@ -768,7 +784,8 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
768784
let mut param_bounds = ty::ParamBounds {
769785
region_bounds: Vec::new(),
770786
builtin_bounds: builtin_bounds,
771-
trait_bounds: Vec::new()
787+
trait_bounds: Vec::new(),
788+
projection_bounds: Vec::new(),
772789
};
773790
loop {
774791
match next(st) {
@@ -778,7 +795,11 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
778795
}
779796
'I' => {
780797
param_bounds.trait_bounds.push(
781-
Rc::new(ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)))));
798+
ty::Binder(Rc::new(parse_trait_ref(st, |x,y| conv(x,y)))));
799+
}
800+
'P' => {
801+
param_bounds.projection_bounds.push(
802+
ty::Binder(parse_projection_predicate(st, |x,y| conv(x,y))));
782803
}
783804
'.' => {
784805
return param_bounds;

src/librustc/metadata/tyencode.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
149149
enc_substs(w, cx, substs);
150150
mywrite!(w, "]");
151151
}
152+
ty::ty_projection(ref data) => {
153+
mywrite!(w, "P[");
154+
enc_trait_ref(w, cx, &data.trait_ref);
155+
mywrite!(w, "{}]", token::get_name(data.item_name));
156+
}
152157
ty::ty_err => {
153158
mywrite!(w, "e");
154159
}
@@ -403,7 +408,12 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
403408

404409
for tp in bs.trait_bounds.iter() {
405410
mywrite!(w, "I");
406-
enc_trait_ref(w, cx, &tp.0);
411+
enc_trait_ref(w, cx, &*tp.0);
412+
}
413+
414+
for tp in bs.projection_bounds.iter() {
415+
mywrite!(w, "P");
416+
enc_projection_predicate(w, cx, &tp.0);
407417
}
408418

409419
mywrite!(w, ".");
@@ -414,8 +424,6 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc
414424
mywrite!(w, "{}:{}|{}|{}|",
415425
token::get_name(v.name), (cx.ds)(v.def_id),
416426
v.space.to_uint(), v.index);
417-
enc_opt(w, v.associated_with, |w, did| mywrite!(w, "{}", (cx.ds)(did)));
418-
mywrite!(w, "|");
419427
enc_bounds(w, cx, &v.bounds);
420428
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
421429
}
@@ -427,7 +435,7 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
427435
match *p {
428436
ty::Predicate::Trait(ref trait_ref) => {
429437
mywrite!(w, "t");
430-
enc_trait_ref(w, cx, &trait_ref.0);
438+
enc_trait_ref(w, cx, &*trait_ref.0.trait_ref);
431439
}
432440
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
433441
mywrite!(w, "e");
@@ -444,5 +452,17 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
444452
enc_ty(w, cx, a);
445453
enc_region(w, cx, b);
446454
}
455+
ty::Predicate::Projection(ty::Binder(ref data)) => {
456+
mywrite!(w, "p");
457+
enc_projection_predicate(w, cx, data)
458+
}
447459
}
448460
}
461+
462+
fn enc_projection_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
463+
cx: &ctxt<'a, 'tcx>,
464+
data: &ty::ProjectionPredicate<'tcx>) {
465+
enc_trait_ref(w, cx, &*data.projection_ty.trait_ref);
466+
mywrite!(w, "{}|", token::get_name(data.projection_ty.item_name));
467+
enc_ty(w, cx, data.ty);
468+
}

src/librustc/middle/astencode.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
12841284
rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
12851285
rbml_w.id(id);
12861286
rbml_w.tag(c::tag_table_val, |rbml_w| {
1287-
rbml_w.emit_trait_ref(ecx, &trait_ref.0);
1287+
rbml_w.emit_trait_ref(ecx, &*trait_ref.0);
12881288
})
12891289
})
12901290
}
@@ -1364,7 +1364,7 @@ trait rbml_decoder_decoder_helpers<'tcx> {
13641364
fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
13651365
-> Rc<ty::TraitRef<'tcx>>;
13661366
fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
1367-
-> Rc<ty::PolyTraitRef<'tcx>>;
1367+
-> ty::PolyTraitRef<'tcx>;
13681368
fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
13691369
-> ty::TypeParameterDef<'tcx>;
13701370
fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1558,8 +1558,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
15581558
}
15591559

15601560
fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
1561-
-> Rc<ty::PolyTraitRef<'tcx>> {
1562-
Rc::new(ty::Binder(self.read_opaque(|this, doc| {
1561+
-> ty::PolyTraitRef<'tcx> {
1562+
ty::Binder(Rc::new(self.read_opaque(|this, doc| {
15631563
let ty = tydecode::parse_trait_ref_data(
15641564
doc.data,
15651565
dcx.cdata.cnum,
@@ -1786,7 +1786,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
17861786
Ok(this.read_poly_trait_ref(dcx))
17871787
}));
17881788
Ok(ty::TyTrait {
1789-
principal: (*principal).clone(),
1789+
principal: ty::Binder((*principal.0).clone()),
17901790
bounds: try!(this.read_struct_field("bounds", 1, |this| {
17911791
Ok(this.read_existential_bounds(dcx))
17921792
})),

src/librustc/middle/fast_reject.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
5858
ty::ty_vec(..) => Some(VecSimplifiedType),
5959
ty::ty_ptr(_) => Some(PtrSimplifiedType),
6060
ty::ty_trait(ref trait_info) => {
61-
Some(TraitSimplifiedType(trait_info.principal.def_id()))
61+
Some(TraitSimplifiedType(trait_info.principal_def_id()))
6262
}
6363
ty::ty_struct(def_id, _) => {
6464
Some(StructSimplifiedType(def_id))
@@ -86,6 +86,9 @@ pub fn simplify_type(tcx: &ty::ctxt,
8686
ty::ty_bare_fn(_, ref f) => {
8787
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
8888
}
89+
ty::ty_projection(_) => {
90+
None
91+
}
8992
ty::ty_param(_) => {
9093
if can_simplify_params {
9194
Some(ParameterSimplifiedType)

src/librustc/middle/infer/combine.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use middle::ty_fold;
5151
use middle::ty_fold::{TypeFoldable};
5252
use util::ppaux::Repr;
5353

54+
use std::rc::Rc;
5455
use syntax::ast::{Onceness, Unsafety};
5556
use syntax::ast;
5657
use syntax::abi;
@@ -358,6 +359,18 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
358359
fn combine<C:Combine<'tcx>>(combiner: &C, a: &Self, b: &Self) -> cres<'tcx, Self>;
359360
}
360361

362+
impl<'tcx,T> Combineable<'tcx> for Rc<T>
363+
where T : Combineable<'tcx>
364+
{
365+
fn combine<C:Combine<'tcx>>(combiner: &C,
366+
a: &Rc<T>,
367+
b: &Rc<T>)
368+
-> cres<'tcx, Rc<T>>
369+
{
370+
Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b))))
371+
}
372+
}
373+
361374
impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
362375
fn combine<C:Combine<'tcx>>(combiner: &C,
363376
a: &ty::TraitRef<'tcx>,
@@ -581,6 +594,15 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
581594
})
582595
}
583596

597+
(&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
598+
if a_data.item_name == b_data.item_name {
599+
let trait_ref = try!(this.trait_refs(&a_data.trait_ref, &b_data.trait_ref));
600+
Ok(ty::mk_projection(tcx, trait_ref, a_data.item_name))
601+
} else {
602+
Err(ty::terr_sorts(expected_found(this, a, b)))
603+
}
604+
}
605+
584606
_ => Err(ty::terr_sorts(expected_found(this, a, b)))
585607
};
586608

src/librustc/middle/infer/error_reporting.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
14371437
format!(" for {}in generic type",
14381438
bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
14391439
}
1440+
infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
1441+
format!(" for {}in trait containing associated type `{}`",
1442+
bound_region_to_string(self.tcx, "lifetime parameter ", true, br),
1443+
token::get_name(type_name))
1444+
}
14401445
infer::EarlyBoundRegion(_, name) => {
14411446
format!(" for lifetime parameter `{}`",
14421447
token::get_name(name).get())
@@ -1661,13 +1666,16 @@ impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
16611666
}
16621667
}
16631668

1664-
impl<'tcx> Resolvable<'tcx> for Rc<ty::PolyTraitRef<'tcx>> {
1665-
fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
1666-
-> Rc<ty::PolyTraitRef<'tcx>> {
1667-
Rc::new(infcx.resolve_type_vars_if_possible(&**self))
1669+
impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
1670+
fn resolve<'a>(&self,
1671+
infcx: &InferCtxt<'a, 'tcx>)
1672+
-> ty::PolyTraitRef<'tcx>
1673+
{
1674+
infcx.resolve_type_vars_if_possible(self)
16681675
}
1676+
16691677
fn contains_error(&self) -> bool {
1670-
ty::trait_ref_contains_error(&self.0)
1678+
ty::trait_ref_contains_error(&*self.0)
16711679
}
16721680
}
16731681

src/librustc/middle/infer/freshen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
157157
ty::ty_struct(..) |
158158
ty::ty_unboxed_closure(..) |
159159
ty::ty_tup(..) |
160+
ty::ty_projection(..) |
160161
ty::ty_param(..) => {
161162
ty_fold::super_fold_ty(self, t)
162163
}

0 commit comments

Comments
 (0)