1
Fork 0

Refactor so that references to traits are not represented using a type with a

bare function store (which is not in fact a kind of value) but rather
ty::TraitRef.  Removes many uses of fail!() and other telltale signs of
type-semantic mismatch.

cc #4183 (not a fix, but related)
This commit is contained in:
Niko Matsakis 2013-03-27 06:16:28 -04:00
parent 3333b0f117
commit d28f734412
46 changed files with 1069 additions and 860 deletions

View file

@ -46,7 +46,8 @@ use ops::Add;
use kinds::Copy; use kinds::Copy;
use util; use util;
use num::Zero; use num::Zero;
use iter::{BaseIter, MutableIter}; use iter::{BaseIter, MutableIter, ExtendedIter};
use iter;
#[cfg(test)] use ptr; #[cfg(test)] use ptr;
#[cfg(test)] use str; #[cfg(test)] use str;
@ -118,6 +119,31 @@ impl<T> MutableIter<T> for Option<T> {
} }
} }
impl<A> ExtendedIter<A> for Option<A> {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
iter::flat_map_to_vec(self, op)
}
}
pub impl<T> Option<T> { pub impl<T> Option<T> {
/// Returns true if the option equals `none` /// Returns true if the option equals `none`
fn is_none(&const self) -> bool { fn is_none(&const self) -> bool {

View file

@ -443,9 +443,9 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
} }
fn visit_trait(&self) -> bool { fn visit_trait(&self) -> bool {
self.align_to::<TyVisitor>(); self.align_to::<@TyVisitor>();
if ! self.inner.visit_trait() { return false; } if ! self.inner.visit_trait() { return false; }
self.bump_past::<TyVisitor>(); self.bump_past::<@TyVisitor>();
true true
} }

View file

@ -298,7 +298,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
@ProgRes(repr) as @Program @ProgRes(repr) as @Program
} }
fn read_all(rd: io::Reader) -> ~str { fn read_all(rd: @io::Reader) -> ~str {
let buf = io::with_bytes_writer(|wr| { let buf = io::with_bytes_writer(|wr| {
let mut bytes = [0, ..4096]; let mut bytes = [0, ..4096];
while !rd.eof() { while !rd.eof() {

View file

@ -74,7 +74,9 @@ pub static tag_crate_dep_vers: uint = 0x2cu;
pub static tag_mod_impl: uint = 0x30u; pub static tag_mod_impl: uint = 0x30u;
pub static tag_item_trait_method: uint = 0x31u; pub static tag_item_trait_method: uint = 0x31u;
pub static tag_impl_trait: uint = 0x32u;
pub static tag_item_trait_ref: uint = 0x32u;
pub static tag_item_super_trait_ref: uint = 0x33u;
// discriminator value for variants // discriminator value for variants
pub static tag_disr_val: uint = 0x34u; pub static tag_disr_val: uint = 0x34u;

View file

@ -139,7 +139,7 @@ pub fn get_provided_trait_methods(tcx: ty::ctxt,
decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx) decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
} }
pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { pub fn get_supertraits(tcx: ty::ctxt, def: ast::def_id) -> ~[@ty::TraitRef] {
let cstore = tcx.cstore; let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate); let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_supertraits(cdata, def.node, tcx) decoder::get_supertraits(cdata, def.node, tcx)
@ -180,6 +180,12 @@ pub fn get_type(tcx: ty::ctxt,
decoder::get_type(cdata, def.node, tcx) decoder::get_type(cdata, def.node, tcx)
} }
pub fn get_trait_def(tcx: ty::ctxt, def: ast::def_id) -> ty::TraitDef {
let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_trait_def(cdata, def.node, tcx)
}
pub fn get_region_param(cstore: @mut metadata::cstore::CStore, pub fn get_region_param(cstore: @mut metadata::cstore::CStore,
def: ast::def_id) -> Option<ty::region_variance> { def: ast::def_id) -> Option<ty::region_variance> {
let cdata = cstore::get_crate_data(cstore, def.crate); let cdata = cstore::get_crate_data(cstore, def.crate);
@ -204,8 +210,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
debug!("got field data %?", the_field); debug!("got field data %?", the_field);
let ty = decoder::item_type(def, the_field, tcx, cdata); let ty = decoder::item_type(def, the_field, tcx, cdata);
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
bounds: @~[], generics: ty::Generics {bounds: @~[],
region_param: None, region_param: None},
ty: ty ty: ty
} }
} }
@ -213,7 +219,8 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
// Given a def_id for an impl or class, return the traits it implements, // Given a def_id for an impl or class, return the traits it implements,
// or the empty vector if it's not for an impl or for a class that implements // or the empty vector if it's not for an impl or for a class that implements
// traits // traits
pub fn get_impl_traits(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::t] { pub fn get_impl_traits(tcx: ty::ctxt,
def: ast::def_id) -> ~[@ty::TraitRef] {
let cstore = tcx.cstore; let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate); let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::get_impl_traits(cdata, def.node, tcx) decoder::get_impl_traits(cdata, def.node, tcx)

View file

@ -20,7 +20,7 @@ use metadata::csearch;
use metadata::cstore; use metadata::cstore;
use metadata::decoder; use metadata::decoder;
use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data, use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
parse_bare_fn_ty_data}; parse_bare_fn_ty_data, parse_trait_ref_data};
use middle::{ty, resolve}; use middle::{ty, resolve};
use core::hash::HashUtil; use core::hash::HashUtil;
@ -256,12 +256,14 @@ pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
} }
} }
fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] { fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
let mut results = ~[]; parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
for reader::tagged_docs(item, tag_impl_trait) |ity| { |_, did| translate_def_id(cdata, did))
results.push(doc_type(ity, tcx, cdata)); }
};
results fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
let tp = reader::get_doc(doc, tag_item_trait_ref);
doc_trait_ref(tp, tcx, cdata)
} }
fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd, fn item_ty_param_bounds(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
@ -371,6 +373,21 @@ pub fn lookup_def(cnum: ast::crate_num, data: @~[u8], did_: ast::def_id) ->
return def_like_to_def(item_to_def_like(item, did, cnum)); return def_like_to_def(item_to_def_like(item, did, cnum));
} }
pub fn get_trait_def(cdata: cmd,
item_id: ast::node_id,
tcx: ty::ctxt) -> ty::TraitDef
{
let item_doc = lookup_item(item_id, cdata.data);
let tp_bounds = item_ty_param_bounds(item_doc, tcx, cdata,
tag_items_data_item_ty_param_bounds);
let rp = item_ty_region_param(item_doc);
ty::TraitDef {
generics: ty::Generics {bounds: tp_bounds,
region_param: rp},
trait_ref: @item_trait_ref(item_doc, tcx, cdata)
}
}
pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
@ -382,8 +399,8 @@ pub fn get_type(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
} else { @~[] }; } else { @~[] };
let rp = item_ty_region_param(item); let rp = item_ty_region_param(item);
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
bounds: tp_bounds, generics: ty::Generics {bounds: tp_bounds,
region_param: rp, region_param: rp},
ty: t ty: t
} }
} }
@ -399,9 +416,19 @@ pub fn get_type_param_count(data: @~[u8], id: ast::node_id) -> uint {
item_ty_param_count(lookup_item(id, data)) item_ty_param_count(lookup_item(id, data))
} }
pub fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) pub fn get_impl_traits(cdata: cmd,
-> ~[ty::t] { id: ast::node_id,
item_impl_traits(lookup_item(id, cdata.data), tcx, cdata) tcx: ty::ctxt) -> ~[@ty::TraitRef]
{
let item_doc = lookup_item(id, cdata.data);
let mut results = ~[];
for reader::tagged_docs(item_doc, tag_item_trait_ref) |tp| {
let trait_ref =
@parse_trait_ref_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did));
results.push(trait_ref);
};
results
} }
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id, pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
@ -735,7 +762,10 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
let self_ty = get_self_ty(method_doc); let self_ty = get_self_ty(method_doc);
ty::method { ty::method {
ident: name, ident: name,
tps: bounds, generics: ty::Generics {
bounds: bounds,
region_param: None
},
transformed_self_ty: transformed_self_ty, transformed_self_ty: transformed_self_ty,
fty: fty, fty: fty,
self_ty: self_ty, self_ty: self_ty,
@ -784,7 +814,10 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
let self_ty = get_self_ty(mth); let self_ty = get_self_ty(mth);
let ty_method = ty::method { let ty_method = ty::method {
ident: name, ident: name,
tps: bounds, generics: ty::Generics {
bounds: bounds,
region_param: None
},
transformed_self_ty: transformed_self_ty, transformed_self_ty: transformed_self_ty,
fty: fty, fty: fty,
self_ty: self_ty, self_ty: self_ty,
@ -804,11 +837,11 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
/// Returns the supertraits of the given trait. /// Returns the supertraits of the given trait.
pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) pub fn get_supertraits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-> ~[ty::t] { -> ~[@ty::TraitRef] {
let mut results = ~[]; let mut results = ~[];
let item_doc = lookup_item(id, cdata.data); let item_doc = lookup_item(id, cdata.data);
for reader::tagged_docs(item_doc, tag_impl_trait) |trait_doc| { for reader::tagged_docs(item_doc, tag_item_super_trait_ref) |trait_doc| {
results.push(doc_type(trait_doc, tcx, cdata)); results.push(@doc_trait_ref(trait_doc, tcx, cdata));
} }
return results; return results;
} }
@ -837,8 +870,8 @@ pub fn get_static_methods_if_impl(intr: @ident_interner,
return None; return None;
} }
// If this impl has a trait ref, don't consider it. // If this impl implements a trait, don't consider it.
for reader::tagged_docs(item, tag_impl_trait) |_doc| { for reader::tagged_docs(item, tag_item_trait_ref) |_doc| {
return None; return None;
} }

View file

@ -153,14 +153,23 @@ fn add_to_index(ecx: @EncodeContext, ebml_w: writer::Encoder, path: &[ident],
}); });
} }
fn encode_trait_ref(ebml_w: writer::Encoder, ecx: @EncodeContext, fn encode_trait_ref(ebml_w: writer::Encoder,
t: @trait_ref) { ecx: @EncodeContext,
ebml_w.start_tag(tag_impl_trait); trait_ref: &ty::TraitRef,
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id)); tag: uint)
{
let ty_str_ctxt = @tyencode::ctxt {
diag: ecx.diag,
ds: def_to_str,
tcx: ecx.tcx,
reachable: |a| reachable(ecx, a),
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
ebml_w.start_tag(tag);
tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
ebml_w.end_tag(); ebml_w.end_tag();
} }
// Item info table encoding // Item info table encoding
fn encode_family(ebml_w: writer::Encoder, c: char) { fn encode_family(ebml_w: writer::Encoder, c: char) {
ebml_w.start_tag(tag_items_data_item_family); ebml_w.start_tag(tag_items_data_item_family);
@ -579,7 +588,7 @@ fn encode_method_ty_fields(ecx: @EncodeContext,
{ {
encode_def_id(ebml_w, method_ty.def_id); encode_def_id(ebml_w, method_ty.def_id);
encode_name(ecx, ebml_w, method_ty.ident); encode_name(ecx, ebml_w, method_ty.ident);
encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps, encode_ty_type_param_bounds(ebml_w, ecx, method_ty.generics.bounds,
tag_item_method_tps); tag_item_method_tps);
encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty); encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
encode_method_fty(ecx, ebml_w, &method_ty.fty); encode_method_fty(ecx, ebml_w, &method_ty.fty);
@ -872,8 +881,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id))); ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
ebml_w.end_tag(); ebml_w.end_tag();
} }
for opt_trait.each |associated_trait| { for opt_trait.each |ast_trait_ref| {
encode_trait_ref(ebml_w, ecx, *associated_trait); let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
} }
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag(); ebml_w.end_tag();
@ -894,14 +904,15 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
&m.generics); &m.generics);
} }
} }
item_trait(ref generics, ref traits, ref ms) => { item_trait(ref generics, ref super_traits, ref ms) => {
add_to_index(); add_to_index();
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id)); encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'I'); encode_family(ebml_w, 'I');
encode_region_param(ecx, ebml_w, item); encode_region_param(ecx, ebml_w, item);
encode_type_param_bounds(ebml_w, ecx, &generics.ty_params); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); let trait_def = ty::lookup_trait_def(tcx, local_def(item.id));
encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
encode_name(ecx, ebml_w, item.ident); encode_name(ecx, ebml_w, item.ident);
encode_attributes(ebml_w, item.attrs); encode_attributes(ebml_w, item.attrs);
for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| { for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
@ -910,8 +921,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
ebml_w.end_tag(); ebml_w.end_tag();
} }
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
for traits.each |associated_trait| { for super_traits.each |ast_trait_ref| {
encode_trait_ref(ebml_w, ecx, *associated_trait); let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
} }
ebml_w.end_tag(); ebml_w.end_tag();
@ -940,7 +952,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
method_ty.fty.purity)); method_ty.fty.purity));
let tpt = ty::lookup_item_type(tcx, method_def_id); let tpt = ty::lookup_item_type(tcx, method_def_id);
encode_ty_type_param_bounds(ebml_w, ecx, tpt.bounds, encode_ty_type_param_bounds(ebml_w, ecx, tpt.generics.bounds,
tag_items_data_item_ty_param_bounds); tag_items_data_item_ty_param_bounds);
encode_type(ecx, ebml_w, tpt.ty); encode_type(ecx, ebml_w, tpt.ty);
} }

View file

@ -125,6 +125,12 @@ pub fn parse_bare_fn_ty_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::c
parse_bare_fn_ty(st, conv) parse_bare_fn_ty(st, conv)
} }
pub fn parse_trait_ref_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
conv: conv_did) -> ty::TraitRef {
let st = parse_state_from_data(data, crate_num, pos, tcx);
parse_trait_ref(st, conv)
}
pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, pub fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt,
conv: conv_did) -> ty::arg { conv: conv_did) -> ty::arg {
let st = parse_state_from_data(data, crate_num, pos, tcx); let st = parse_state_from_data(data, crate_num, pos, tcx);
@ -183,7 +189,6 @@ fn parse_trait_store(st: @mut PState) -> ty::TraitStore {
'~' => ty::UniqTraitStore, '~' => ty::UniqTraitStore,
'@' => ty::BoxTraitStore, '@' => ty::BoxTraitStore,
'&' => ty::RegionTraitStore(parse_region(st)), '&' => ty::RegionTraitStore(parse_region(st)),
'.' => ty::BareTraitStore,
c => st.tcx.sess.bug(fmt!("parse_trait_store(): bad input '%c'", c)) c => st.tcx.sess.bug(fmt!("parse_trait_store(): bad input '%c'", c))
} }
} }
@ -265,6 +270,12 @@ fn parse_str(st: @mut PState, term: char) -> ~str {
return result; return result;
} }
fn parse_trait_ref(st: @mut PState, conv: conv_did) -> ty::TraitRef {
let def = parse_def(st, NominalType, conv);
let substs = parse_substs(st, conv);
ty::TraitRef {def_id: def, substs: substs}
}
fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
match next(st) { match next(st) {
'n' => return ty::mk_nil(st.tcx), 'n' => return ty::mk_nil(st.tcx),
@ -551,7 +562,7 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> @~[ty::param_bound] {
'C' => ty::bound_copy, 'C' => ty::bound_copy,
'K' => ty::bound_const, 'K' => ty::bound_const,
'O' => ty::bound_durable, 'O' => ty::bound_durable,
'I' => ty::bound_trait(parse_ty(st, conv)), 'I' => ty::bound_trait(@parse_trait_ref(st, conv)),
'.' => break, '.' => break,
_ => fail!(~"parse_bounds: bad bounds") _ => fail!(~"parse_bounds: bad bounds")
}); });

View file

@ -214,11 +214,16 @@ pub fn enc_vstore(w: @io::Writer, cx: @ctxt, v: ty::vstore) {
} }
} }
pub fn enc_trait_ref(w: @io::Writer, cx: @ctxt, s: &ty::TraitRef) {
w.write_str((cx.ds)(s.def_id));
w.write_char('|');
enc_substs(w, cx, s.substs);
}
pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) { pub fn enc_trait_store(w: @io::Writer, cx: @ctxt, s: ty::TraitStore) {
match s { match s {
ty::UniqTraitStore => w.write_char('~'), ty::UniqTraitStore => w.write_char('~'),
ty::BoxTraitStore => w.write_char('@'), ty::BoxTraitStore => w.write_char('@'),
ty::BareTraitStore => w.write_char('.'),
ty::RegionTraitStore(re) => { ty::RegionTraitStore(re) => {
w.write_char('&'); w.write_char('&');
enc_region(w, cx, re); enc_region(w, cx, re);
@ -416,7 +421,7 @@ pub fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
ty::bound_durable => w.write_char('O'), ty::bound_durable => w.write_char('O'),
ty::bound_trait(tp) => { ty::bound_trait(tp) => {
w.write_char('I'); w.write_char('I');
enc_ty(w, cx, tp); enc_trait_ref(w, cx, tp);
} }
} }
} }

View file

@ -779,16 +779,20 @@ impl ebml_writer_helpers for writer::Encoder {
fn emit_tpbt(&self, ecx: @e::EncodeContext, fn emit_tpbt(&self, ecx: @e::EncodeContext,
tpbt: ty::ty_param_bounds_and_ty) { tpbt: ty::ty_param_bounds_and_ty) {
do self.emit_struct("ty_param_bounds_and_ty", 3) { do self.emit_struct("ty_param_bounds_and_ty", 2) {
do self.emit_field(~"generics", 0) {
do self.emit_struct("Generics", 2) {
do self.emit_field(~"bounds", 0) { do self.emit_field(~"bounds", 0) {
do self.emit_from_vec(*tpbt.bounds) |bs| { do self.emit_from_vec(*tpbt.generics.bounds) |bs| {
self.emit_bounds(ecx, *bs); self.emit_bounds(ecx, *bs);
} }
} }
do self.emit_field(~"region_param", 1u) { do self.emit_field(~"region_param", 1) {
tpbt.region_param.encode(self); tpbt.generics.region_param.encode(self);
} }
do self.emit_field(~"ty", 2u) { }
}
do self.emit_field(~"ty", 1) {
self.emit_ty(ecx, tpbt.ty); self.emit_ty(ecx, tpbt.ty);
} }
} }
@ -1046,15 +1050,19 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext) fn read_ty_param_bounds_and_ty(&self, xcx: @ExtendedDecodeContext)
-> ty::ty_param_bounds_and_ty -> ty::ty_param_bounds_and_ty
{ {
do self.read_struct("ty_param_bounds_and_ty", 3) { do self.read_struct("ty_param_bounds_and_ty", 2) {
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
bounds: self.read_field(~"bounds", 0u, || { generics: do self.read_struct("Generics", 2) {
ty::Generics {
bounds: self.read_field(~"bounds", 0, || {
@self.read_to_vec(|| self.read_bounds(xcx) ) @self.read_to_vec(|| self.read_bounds(xcx) )
}), }),
region_param: self.read_field(~"region_param", 1u, || { region_param: self.read_field(~"region_param", 1, || {
Decodable::decode(self) Decodable::decode(self)
}), })
ty: self.read_field(~"ty", 2u, || { }
},
ty: self.read_field(~"ty", 1, || {
self.read_ty(xcx) self.read_ty(xcx)
}) })
} }

View file

@ -91,7 +91,7 @@ fn check_struct_safe_for_destructor(cx: Context,
span: span, span: span,
struct_did: def_id) { struct_did: def_id) {
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did); let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
if struct_tpt.bounds.len() == 0 { if struct_tpt.generics.bounds.len() == 0 {
let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs { let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
self_r: None, self_r: None,
self_ty: None, self_ty: None,
@ -279,7 +279,7 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt<Context>) {
let bounds = match e.node { let bounds = match e.node {
expr_path(_) => { expr_path(_) => {
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id)); let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&e.id));
ty::lookup_item_type(cx.tcx, did).bounds ty::lookup_item_type(cx.tcx, did).generics.bounds
} }
_ => { _ => {
// Type substitutions should only occur on paths and // Type substitutions should only occur on paths and
@ -340,7 +340,7 @@ fn check_ty(aty: @Ty, cx: Context, v: visit::vt<Context>) {
// FIXME(#5562): removing this copy causes a segfault before stage2 // FIXME(#5562): removing this copy causes a segfault before stage2
let ts = /*bad*/ copy **ts; let ts = /*bad*/ copy **ts;
let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id)); let did = ast_util::def_id_of_def(*cx.tcx.def_map.get(&id));
let bounds = ty::lookup_item_type(cx.tcx, did).bounds; let bounds = ty::lookup_item_type(cx.tcx, did).generics.bounds;
for vec::each2(ts, *bounds) |ty, bound| { for vec::each2(ts, *bounds) |ty, bound| {
check_bounds(cx, aty.id, aty.span, *ty, *bound) check_bounds(cx, aty.id, aty.span, *ty, *bound)
} }

View file

@ -825,8 +825,7 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) {
ast::item_fn(*) | ast::item_fn(*) |
ast::item_ty(*) | ast::item_ty(*) |
ast::item_enum(*) | ast::item_enum(*) |
ast::item_struct(*) | ast::item_struct(*) => check_type(cx, it.id, it.id, it.span,
ast::item_trait(*) => check_type(cx, it.id, it.id, it.span,
ty::node_id_to_type(cx, it.id)), ty::node_id_to_type(cx, it.id)),
_ => () _ => ()
} }

View file

@ -79,6 +79,7 @@ use syntax::opt_vec::OptVec;
use core::option::Some; use core::option::Some;
use core::str::each_split_str; use core::str::each_split_str;
use core::hashmap::{HashMap, HashSet}; use core::hashmap::{HashMap, HashSet};
use core::util;
// Definition mapping // Definition mapping
pub type DefMap = @mut HashMap<node_id,def>; pub type DefMap = @mut HashMap<node_id,def>;
@ -3414,7 +3415,6 @@ pub impl Resolver {
self_type, self_type,
ref methods) => { ref methods) => {
self.resolve_implementation(item.id, self.resolve_implementation(item.id,
item.span,
generics, generics,
implemented_traits, implemented_traits,
self_type, self_type,
@ -3723,13 +3723,30 @@ pub impl Resolver {
for type_parameters.each |type_parameter| { for type_parameters.each |type_parameter| {
for type_parameter.bounds.each |&bound| { for type_parameter.bounds.each |&bound| {
match bound { match bound {
TraitTyParamBound(ty) => self.resolve_type(ty, visitor), TraitTyParamBound(tref) => {
self.resolve_trait_reference(tref, visitor)
}
RegionTyParamBound => {} RegionTyParamBound => {}
} }
} }
} }
} }
fn resolve_trait_reference(@mut self,
trait_reference: &trait_ref,
visitor: ResolveVisitor) {
match self.resolve_path(trait_reference.path, TypeNS, true, visitor) {
None => {
self.session.span_err(trait_reference.path.span,
~"attempt to implement an \
unknown trait");
}
Some(def) => {
self.record_def(trait_reference.ref_id, def);
}
}
}
fn resolve_struct(@mut self, fn resolve_struct(@mut self,
id: node_id, id: node_id,
generics: &Generics, generics: &Generics,
@ -3797,7 +3814,6 @@ pub impl Resolver {
fn resolve_implementation(@mut self, fn resolve_implementation(@mut self,
id: node_id, id: node_id,
span: span,
generics: &Generics, generics: &Generics,
opt_trait_reference: Option<@trait_ref>, opt_trait_reference: Option<@trait_ref>,
self_type: @Ty, self_type: @Ty,
@ -3816,25 +3832,16 @@ pub impl Resolver {
let original_trait_refs; let original_trait_refs;
match opt_trait_reference { match opt_trait_reference {
Some(trait_reference) => { Some(trait_reference) => {
let mut new_trait_refs = ~[]; self.resolve_trait_reference(trait_reference, visitor);
match self.resolve_path(
trait_reference.path, TypeNS, true, visitor) {
None => {
self.session.span_err(span,
~"attempt to implement an \
unknown trait");
}
Some(def) => {
self.record_def(trait_reference.ref_id, def);
// Record the current trait reference.
new_trait_refs.push(def_id_of_def(def));
}
}
// Record the current set of trait references. // Record the current set of trait references.
let mut old = Some(new_trait_refs); let mut new_trait_refs = ~[];
self.current_trait_refs <-> old; for self.def_map.find(&trait_reference.ref_id).each |&def| {
original_trait_refs = Some(old); new_trait_refs.push(def_id_of_def(*def));
}
original_trait_refs = Some(util::replace(
&mut self.current_trait_refs,
Some(new_trait_refs)));
} }
None => { None => {
original_trait_refs = None; original_trait_refs = None;

View file

@ -1062,9 +1062,6 @@ pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
ty::RegionTraitStore(_) => { ty::RegionTraitStore(_) => {
T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())]) T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())])
} }
ty::BareTraitStore => {
cx.sess.bug(~"can't make T_opaque_trait with bare trait store")
}
} }
} }

View file

@ -40,7 +40,6 @@ use core::libc::c_uint;
use core::str; use core::str;
use std::time; use std::time;
use syntax::ast; use syntax::ast;
use syntax::parse::token::special_idents;
pub fn trans_free(cx: block, v: ValueRef) -> block { pub fn trans_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt("trans_free"); let _icx = cx.insn_ctxt("trans_free");
@ -400,11 +399,9 @@ pub fn call_tydesc_glue(++cx: block, v: ValueRef, t: ty::t, field: uint)
pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) { pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
let _icx = bcx.insn_ctxt("make_visit_glue"); let _icx = bcx.insn_ctxt("make_visit_glue");
let mut bcx = bcx; let mut bcx = bcx;
let ty_visitor_name = special_idents::ty_visitor; let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
assert!(bcx.ccx().tcx.intrinsic_defs.contains_key(&ty_visitor_name)); let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty)));
let (trait_id, ty) = *bcx.ccx().tcx.intrinsic_defs.get(&ty_visitor_name); bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), ty)));
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, trait_id);
build_return(bcx); build_return(bcx);
} }
@ -554,8 +551,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
ty::ty_closure(_) => { ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v0, t, drop_ty) closure::make_closure_glue(bcx, v0, t, drop_ty)
} }
ty::ty_trait(_, _, ty::BoxTraitStore) | ty::ty_trait(_, _, ty::BoxTraitStore) => {
ty::ty_trait(_, _, ty::BareTraitStore) => {
let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u])); let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx)) decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx))
} }
@ -621,8 +617,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
ty::ty_closure(_) => { ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v, t, take_ty) closure::make_closure_glue(bcx, v, t, take_ty)
} }
ty::ty_trait(_, _, ty::BoxTraitStore) | ty::ty_trait(_, _, ty::BoxTraitStore) => {
ty::ty_trait(_, _, ty::BareTraitStore) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u])); let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u]));
incr_refcnt_of_boxed(bcx, llbox); incr_refcnt_of_boxed(bcx, llbox);
bcx bcx

View file

@ -87,8 +87,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
ccx.stats.n_inlines += 1; ccx.stats.n_inlines += 1;
ccx.external.insert(fn_id, Some(mth.id)); ccx.external.insert(fn_id, Some(mth.id));
let ty::ty_param_bounds_and_ty { let ty::ty_param_bounds_and_ty {
bounds: impl_bnds, generics: ty::Generics { bounds: impl_bnds, _ },
region_param: _,
ty: _ ty: _
} = ty::lookup_item_type(ccx.tcx, impl_did); } = ty::lookup_item_type(ccx.tcx, impl_did);
if translate && if translate &&

View file

@ -11,7 +11,6 @@
use core::prelude::*; use core::prelude::*;
use back::abi; use back::abi;
use driver;
use lib::llvm::llvm; use lib::llvm::llvm;
use lib::llvm::ValueRef; use lib::llvm::ValueRef;
use lib; use lib;
@ -302,8 +301,8 @@ pub fn trans_static_method_callee(bcx: block,
// found on the type parametesr T1...Tn to find the index of the // found on the type parametesr T1...Tn to find the index of the
// one we are interested in. // one we are interested in.
let bound_index = { let bound_index = {
let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id); let trait_def = ty::lookup_trait_def(bcx.tcx(), trait_id);
ty::count_traits_and_supertraits(bcx.tcx(), *trait_polyty.bounds) ty::count_traits_and_supertraits(bcx.tcx(), *trait_def.generics.bounds)
}; };
let mname = if method_id.crate == ast::local_crate { let mname = if method_id.crate == ast::local_crate {
@ -552,8 +551,10 @@ pub fn combine_impl_and_methods_origins(bcx: block,
// rcvr + method bounds. // rcvr + method bounds.
let ccx = bcx.ccx(), tcx = bcx.tcx(); let ccx = bcx.ccx(), tcx = bcx.tcx();
let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did);
let ty::ty_param_bounds_and_ty {bounds: r_m_bounds, _} let ty::ty_param_bounds_and_ty {
= ty::lookup_item_type(tcx, mth_did); generics: ty::Generics {bounds: r_m_bounds, _},
_
} = ty::lookup_item_type(tcx, mth_did);
let n_r_m_tps = r_m_bounds.len(); // rcvr + method tps let n_r_m_tps = r_m_bounds.len(); // rcvr + method tps
let m_boundss = vec::slice(*r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps); let m_boundss = vec::slice(*r_m_bounds, n_r_m_tps - n_m_tps, n_r_m_tps);
@ -656,7 +657,6 @@ pub fn trans_trait_callee_from_llval(bcx: block,
// payload. // payload.
match store { match store {
ty::BoxTraitStore | ty::BoxTraitStore |
ty::BareTraitStore |
ty::UniqTraitStore => { ty::UniqTraitStore => {
llself = GEPi(bcx, llbox, [0u, abi::box_field_body]); llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
} }
@ -679,7 +679,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
// Pass a pointer to the box. // Pass a pointer to the box.
match store { match store {
ty::BoxTraitStore | ty::BareTraitStore => llself = llbox, ty::BoxTraitStore => llself = llbox,
_ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait") _ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait")
} }
@ -785,19 +785,14 @@ pub fn make_impl_vtable(ccx: @CrateContext,
let tcx = ccx.tcx; let tcx = ccx.tcx;
// XXX: This should support multiple traits. // XXX: This should support multiple traits.
let trt_id = driver::session::expect( let trt_id = ty::impl_trait_refs(tcx, impl_id)[0].def_id;
tcx.sess,
ty::ty_to_def_id(ty::impl_traits(tcx,
impl_id,
ty::BoxTraitStore)[0]),
|| ~"make_impl_vtable: non-trait-type implemented");
let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u; let has_tps = ty::lookup_item_type(ccx.tcx, impl_id).generics.bounds.len() > 0u;
make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| { make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
let im = ty::method(tcx, *method_def_id); let im = ty::method(tcx, *method_def_id);
let fty = ty::subst_tps(tcx, substs, None, let fty = ty::subst_tps(tcx, substs, None,
ty::mk_bare_fn(tcx, copy im.fty)); ty::mk_bare_fn(tcx, copy im.fty));
if im.tps.len() > 0u || ty::type_has_self(fty) { if im.generics.bounds.len() > 0u || ty::type_has_self(fty) {
debug!("(making impl vtable) method has self or type params: %s", debug!("(making impl vtable) method has self or type params: %s",
*tcx.sess.str_of(im.ident)); *tcx.sess.str_of(im.ident));
C_null(T_ptr(T_nil())) C_null(T_ptr(T_nil()))
@ -844,7 +839,7 @@ pub fn trans_trait_cast(bcx: block,
let v_ty = expr_ty(bcx, val); let v_ty = expr_ty(bcx, val);
match store { match store {
ty::RegionTraitStore(_) | ty::BoxTraitStore | ty::BareTraitStore => { ty::RegionTraitStore(_) | ty::BoxTraitStore => {
let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]); let mut llboxdest = GEPi(bcx, lldest, [0u, 1u]);
// Just store the pointer into the pair. // Just store the pointer into the pair.
llboxdest = PointerCast(bcx, llboxdest = PointerCast(bcx,

View file

@ -169,7 +169,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
let psubsts = Some(@param_substs { let psubsts = Some(@param_substs {
tys: substs, tys: substs,
vtables: vtables, vtables: vtables,
bounds: tpt.bounds, bounds: tpt.generics.bounds,
self_ty: impl_ty_opt self_ty: impl_ty_opt
}); });
@ -291,7 +291,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
ty::ty_trait(_, _, ref store) => { ty::ty_trait(_, _, ref store) => {
let sigil = match *store { let sigil = match *store {
ty::UniqTraitStore => ast::OwnedSigil, ty::UniqTraitStore => ast::OwnedSigil,
ty::BoxTraitStore | ty::BareTraitStore => ast::ManagedSigil, ty::BoxTraitStore => ast::ManagedSigil,
ty::RegionTraitStore(_) => ast::BorrowedSigil, ty::RegionTraitStore(_) => ast::BorrowedSigil,
}; };
@ -328,7 +328,7 @@ pub fn make_mono_id(ccx: @CrateContext, item: ast::def_id, substs: &[ty::t],
+param_uses: Option<~[type_use::type_uses]>) -> mono_id { +param_uses: Option<~[type_use::type_uses]>) -> mono_id {
let precise_param_ids = match vtables { let precise_param_ids = match vtables {
Some(vts) => { Some(vts) => {
let bounds = ty::lookup_item_type(ccx.tcx, item).bounds; let bounds = ty::lookup_item_type(ccx.tcx, item).generics.bounds;
let mut i = 0; let mut i = 0;
vec::map2(*bounds, substs, |bounds, subst| { vec::map2(*bounds, substs, |bounds, subst| {
let mut v = ~[]; let mut v = ~[];

View file

@ -25,8 +25,10 @@ use middle;
use util::ppaux::{note_and_explain_region, bound_region_to_str}; use util::ppaux::{note_and_explain_region, bound_region_to_str};
use util::ppaux::{region_to_str, vstore_to_str}; use util::ppaux::{region_to_str, vstore_to_str};
use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str}; use util::ppaux::{trait_store_to_str, ty_to_str, tys_to_str};
use util::ppaux::{trait_ref_to_str};
use util::common::{indenter}; use util::common::{indenter};
use core;
use core::cast; use core::cast;
use core::cmp; use core::cmp;
use core::ops; use core::ops;
@ -44,6 +46,7 @@ use syntax::ast_util;
use syntax::codemap::span; use syntax::codemap::span;
use syntax::codemap; use syntax::codemap;
use syntax::print::pprust; use syntax::print::pprust;
use syntax::parse::token::special_idents;
use syntax::{ast, ast_map}; use syntax::{ast, ast_map};
use syntax::opt_vec::OptVec; use syntax::opt_vec::OptVec;
use syntax::opt_vec; use syntax::opt_vec;
@ -70,7 +73,7 @@ pub type param_bounds = @~[param_bound];
pub struct method { pub struct method {
ident: ast::ident, ident: ast::ident,
tps: @~[param_bounds], generics: ty::Generics,
transformed_self_ty: Option<ty::t>, transformed_self_ty: Option<ty::t>,
fty: BareFnTy, fty: BareFnTy,
self_ty: ast::self_ty_, self_ty: ast::self_ty_,
@ -96,9 +99,8 @@ pub enum vstore {
#[auto_encode] #[auto_encode]
#[auto_decode] #[auto_decode]
#[deriving(Eq)] #[deriving(Eq, IterBytes)]
pub enum TraitStore { pub enum TraitStore {
BareTraitStore, // a plain trait without a sigil
BoxTraitStore, // @Trait BoxTraitStore, // @Trait
UniqTraitStore, // ~Trait UniqTraitStore, // ~Trait
RegionTraitStore(Region), // &Trait RegionTraitStore(Region), // &Trait
@ -225,11 +227,6 @@ pub struct ProvidedMethodSource {
impl_id: ast::def_id impl_id: ast::def_id
} }
pub struct InstantiatedTraitRef {
def_id: ast::def_id,
tpt: ty_param_substs_and_ty
}
pub type ctxt = @ctxt_; pub type ctxt = @ctxt_;
struct ctxt_ { struct ctxt_ {
@ -265,8 +262,12 @@ struct ctxt_ {
// A cache for the trait_methods() routine // A cache for the trait_methods() routine
trait_methods_cache: @mut HashMap<def_id, @~[@method]>, trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
trait_refs: @mut HashMap<node_id, @TraitRef>,
trait_defs: @mut HashMap<def_id, @TraitDef>,
items: ast_map::map, items: ast_map::map,
intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>, intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
freevars: freevars::freevar_map, freevars: freevars::freevar_map,
tcache: type_cache, tcache: type_cache,
rcache: creader_cache, rcache: creader_cache,
@ -286,7 +287,7 @@ struct ctxt_ {
// that implementation implements. // that implementation implements.
provided_methods: ProvidedMethodsMap, provided_methods: ProvidedMethodsMap,
provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>, provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
supertraits: @mut HashMap<ast::def_id, @~[InstantiatedTraitRef]>, supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
// A mapping from the def ID of an enum or struct type to the def ID // A mapping from the def ID of an enum or struct type to the def ID
// of the method that implements its destructor. If the type is not // of the method that implements its destructor. If the type is not
@ -536,6 +537,12 @@ pub enum sty {
ty_unboxed_vec(mt), ty_unboxed_vec(mt),
} }
#[deriving(Eq, IterBytes)]
pub struct TraitRef {
def_id: def_id,
substs: substs
}
#[deriving(Eq)] #[deriving(Eq)]
pub enum IntVarValue { pub enum IntVarValue {
IntType(ast::int_ty), IntType(ast::int_ty),
@ -582,16 +589,17 @@ pub enum type_err {
terr_self_substs, terr_self_substs,
terr_integer_as_char, terr_integer_as_char,
terr_int_mismatch(expected_found<IntVarValue>), terr_int_mismatch(expected_found<IntVarValue>),
terr_float_mismatch(expected_found<ast::float_ty>) terr_float_mismatch(expected_found<ast::float_ty>),
terr_traits(expected_found<ast::def_id>),
} }
#[deriving(Eq)] #[deriving(Eq, IterBytes)]
pub enum param_bound { pub enum param_bound {
bound_copy, bound_copy,
bound_durable, bound_durable,
bound_owned, bound_owned,
bound_const, bound_const,
bound_trait(t), bound_trait(@TraitRef),
} }
#[deriving(Eq)] #[deriving(Eq)]
@ -660,19 +668,6 @@ impl cmp::Eq for InferRegion {
} }
} }
impl to_bytes::IterBytes for param_bound {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
match *self {
bound_copy => 0u8.iter_bytes(lsb0, f),
bound_durable => 1u8.iter_bytes(lsb0, f),
bound_owned => 2u8.iter_bytes(lsb0, f),
bound_const => 3u8.iter_bytes(lsb0, f),
bound_trait(ref t) =>
to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
}
}
}
pub trait Vid { pub trait Vid {
fn to_uint(&self) -> uint; fn to_uint(&self) -> uint;
} }
@ -759,6 +754,13 @@ impl to_bytes::IterBytes for RegionVid {
} }
} }
/// Information about the type/lifetime parametesr associated with an item.
/// Analogous to ast::Generics.
pub struct Generics {
bounds: @~[param_bounds],
region_param: Option<region_variance>,
}
/// A polytype. /// A polytype.
/// ///
/// - `bounds`: The list of bounds for each type parameter. The length of the /// - `bounds`: The list of bounds for each type parameter. The length of the
@ -770,11 +772,16 @@ impl to_bytes::IterBytes for RegionVid {
/// - `ty`: the base type. May have reference to the (unsubstituted) bound /// - `ty`: the base type. May have reference to the (unsubstituted) bound
/// region `&self` or to (unsubstituted) ty_param types /// region `&self` or to (unsubstituted) ty_param types
pub struct ty_param_bounds_and_ty { pub struct ty_param_bounds_and_ty {
bounds: @~[param_bounds], generics: Generics,
region_param: Option<region_variance>,
ty: t ty: t
} }
/// As `ty_param_bounds_and_ty` but for a trait ref.
pub struct TraitDef {
generics: Generics,
trait_ref: @ty::TraitRef,
}
pub struct ty_param_substs_and_ty { pub struct ty_param_substs_and_ty {
substs: ty::substs, substs: ty::substs,
ty: ty::t ty: ty::t
@ -829,6 +836,9 @@ pub fn mk_ctxt(s: session::Session,
region_paramd_items: region_paramd_items, region_paramd_items: region_paramd_items,
node_types: @mut SmallIntMap::new(), node_types: @mut SmallIntMap::new(),
node_type_substs: @mut HashMap::new(), node_type_substs: @mut HashMap::new(),
trait_refs: @mut HashMap::new(),
trait_defs: @mut HashMap::new(),
intrinsic_traits: @mut HashMap::new(),
items: amap, items: amap,
intrinsic_defs: @mut HashMap::new(), intrinsic_defs: @mut HashMap::new(),
freevars: freevars, freevars: freevars,
@ -1412,7 +1422,7 @@ pub fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
bound_durable => ~"'static", bound_durable => ~"'static",
bound_owned => ~"owned", bound_owned => ~"owned",
bound_const => ~"const", bound_const => ~"const",
bound_trait(t) => ::util::ppaux::ty_to_str(cx, t) bound_trait(t) => ::util::ppaux::trait_ref_to_str(cx, t)
} }
} }
@ -1466,13 +1476,26 @@ pub fn subst(cx: ctxt,
} }
} }
pub fn subst_in_trait_ref(cx: ctxt,
substs: &substs,
trait_ref: &ty::TraitRef) -> ty::TraitRef
{
ty::TraitRef {
def_id: trait_ref.def_id,
substs: subst_in_substs(cx, substs, &trait_ref.substs)
}
}
// Performs substitutions on a set of substitutions (result = sup(sub)) to // Performs substitutions on a set of substitutions (result = sup(sub)) to
// yield a new set of substitutions. This is used in trait inheritance. // yield a new set of substitutions. This is used in trait inheritance.
pub fn subst_substs(cx: ctxt, sup: &substs, sub: &substs) -> substs { pub fn subst_in_substs(cx: ctxt,
substs: &substs,
in_substs: &substs) -> substs
{
substs { substs {
self_r: sup.self_r, self_r: in_substs.self_r,
self_ty: sup.self_ty.map(|typ| subst(cx, sub, *typ)), self_ty: in_substs.self_ty.map(|&typ| subst(cx, substs, typ)),
tps: sup.tps.map(|typ| subst(cx, sub, *typ)) tps: in_substs.tps.map(|&typ| subst(cx, substs, typ))
} }
} }
@ -1488,6 +1511,11 @@ pub fn type_is_error(ty: t) -> bool {
(get(ty).flags & (has_ty_err as uint)) != 0 (get(ty).flags & (has_ty_err as uint)) != 0
} }
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
tref.substs.self_ty.any(|&t| type_is_error(t)) ||
tref.substs.tps.any(|&t| type_is_error(t))
}
pub fn type_is_ty_var(ty: t) -> bool { pub fn type_is_ty_var(ty: t) -> bool {
match get(ty).sty { match get(ty).sty {
ty_infer(TyVar(_)) => true, ty_infer(TyVar(_)) => true,
@ -1932,8 +1960,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
TC_OWNED_CLOSURE TC_OWNED_CLOSURE
} }
ty_trait(_, _, BoxTraitStore) | ty_trait(_, _, BoxTraitStore) => {
ty_trait(_, _, BareTraitStore) => {
TC_MANAGED TC_MANAGED
} }
@ -2592,17 +2619,6 @@ impl to_bytes::IterBytes for vstore {
} }
} }
impl to_bytes::IterBytes for TraitStore {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
match *self {
BareTraitStore => 0u8.iter_bytes(lsb0, f),
UniqTraitStore => 1u8.iter_bytes(lsb0, f),
BoxTraitStore => 2u8.iter_bytes(lsb0, f),
RegionTraitStore(ref r) => to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
}
}
}
impl to_bytes::IterBytes for substs { impl to_bytes::IterBytes for substs {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_3(&self.self_r, to_bytes::iter_bytes_3(&self.self_r,
@ -2715,6 +2731,16 @@ impl to_bytes::IterBytes for sty {
} }
} }
pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
match cx.trait_refs.find(&id) {
Some(&t) => t,
None => cx.sess.bug(
fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
ast_map::node_id_to_str(cx.items, id,
cx.sess.parse_sess.interner)))
}
}
pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t { pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
//io::println(fmt!("%?/%?", id, cx.node_types.len())); //io::println(fmt!("%?/%?", id, cx.node_types.len()));
match cx.node_types.find(&(id as uint)) { match cx.node_types.find(&(id as uint)) {
@ -3025,7 +3051,7 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
// n.b.: When we encode impl methods, the bounds // n.b.: When we encode impl methods, the bounds
// that we encode include both the impl bounds // that we encode include both the impl bounds
// and then the method bounds themselves... // and then the method bounds themselves...
ty::lookup_item_type(tcx, did).bounds ty::lookup_item_type(tcx, did).generics.bounds
} }
typeck::method_param(typeck::method_param { typeck::method_param(typeck::method_param {
trait_id: trt_id, trait_id: trt_id,
@ -3036,10 +3062,9 @@ pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
// ...trait methods bounds, in contrast, include only the // ...trait methods bounds, in contrast, include only the
// method bounds, so we must preprend the tps from the // method bounds, so we must preprend the tps from the
// trait itself. This ought to be harmonized. // trait itself. This ought to be harmonized.
let trt_bounds = let trt_bounds = ty::lookup_trait_def(tcx, trt_id).generics.bounds;
ty::lookup_item_type(tcx, trt_id).bounds;
@(vec::append(/*bad*/copy *trt_bounds, @(vec::append(/*bad*/copy *trt_bounds,
*ty::trait_method(tcx, trt_id, n_mth).tps)) *ty::trait_method(tcx, trt_id, n_mth).generics.bounds))
} }
} }
} }
@ -3488,6 +3513,11 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
ty_sort_str(cx, values.expected), ty_sort_str(cx, values.expected),
ty_sort_str(cx, values.found)) ty_sort_str(cx, values.found))
} }
terr_traits(values) => {
fmt!("expected trait %s but found trait %s",
item_path_str(cx, values.expected),
item_path_str(cx, values.found))
}
terr_self_substs => { terr_self_substs => {
~"inconsistent self substitution" // XXX this is more of a bug ~"inconsistent self substitution" // XXX this is more of a bug
} }
@ -3565,11 +3595,11 @@ pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
} }
pub fn trait_supertraits(cx: ctxt, pub fn trait_supertraits(cx: ctxt,
id: ast::def_id) id: ast::def_id) -> @~[@TraitRef]
-> @~[InstantiatedTraitRef] { {
// Check the cache. // Check the cache.
match cx.supertraits.find(&id) { match cx.supertraits.find(&id) {
Some(&instantiated_trait_info) => { return instantiated_trait_info; } Some(&trait_refs) => { return trait_refs; }
None => {} // Continue. None => {} // Continue.
} }
@ -3578,25 +3608,10 @@ pub fn trait_supertraits(cx: ctxt,
assert!(!is_local(id)); assert!(!is_local(id));
// Get the supertraits out of the metadata and create the // Get the supertraits out of the metadata and create the
// InstantiatedTraitRef for each. // TraitRef for each.
let mut result = ~[]; let result = @csearch::get_supertraits(cx, id);
for csearch::get_supertraits(cx, id).each |trait_type| { cx.supertraits.insert(id, result);
match get(*trait_type).sty { return result;
ty_trait(def_id, ref substs, _) => {
result.push(InstantiatedTraitRef {
def_id: def_id,
tpt: ty_param_substs_and_ty {
substs: (/*bad*/copy *substs),
ty: *trait_type
}
});
}
_ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
}
}
// Unwrap and return the result.
return @result;
} }
fn lookup_locally_or_in_crate_store<V:Copy>( fn lookup_locally_or_in_crate_store<V:Copy>(
@ -3659,23 +3674,7 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
|| @csearch::get_trait_method_def_ids(cx.cstore, id)) || @csearch::get_trait_method_def_ids(cx.cstore, id))
} }
/* pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
Could this return a list of (def_id, substs) pairs?
*/
pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] {
fn storeify(cx: ctxt, ty: t, store: TraitStore) -> t {
match ty::get(ty).sty {
ty::ty_trait(did, ref substs, trait_store) => {
if store == trait_store {
ty
} else {
mk_trait(cx, did, (/*bad*/copy *substs), store)
}
}
_ => cx.sess.bug(~"impl_traits: not a trait")
}
}
if id.crate == ast::local_crate { if id.crate == ast::local_crate {
debug!("(impl_traits) searching for trait impl %?", id); debug!("(impl_traits) searching for trait impl %?", id);
match cx.items.find(&id.node) { match cx.items.find(&id.node) {
@ -3683,17 +3682,15 @@ pub fn impl_traits(cx: ctxt, id: ast::def_id, store: TraitStore) -> ~[t] {
node: ast::item_impl(_, opt_trait, _, _), node: ast::item_impl(_, opt_trait, _, _),
_}, _},
_)) => { _)) => {
match opt_trait {
do opt_trait.map_default(~[]) |trait_ref| { Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
~[storeify(cx, node_id_to_type(cx, trait_ref.ref_id), None => ~[]
store)]
} }
} }
_ => ~[] _ => ~[]
} }
} else { } else {
vec::map(csearch::get_impl_traits(cx, id), csearch::get_impl_traits(cx, id)
|x| storeify(cx, *x, store))
} }
} }
@ -3967,6 +3964,23 @@ pub fn lookup_item_type(cx: ctxt,
|| csearch::get_type(cx, did)) || csearch::get_type(cx, did))
} }
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
match cx.trait_defs.find(&did) {
Some(&trait_def) => {
// The item is in this crate. The caller should have added it to the
// type cache already
return trait_def;
}
None => {
assert!(did.crate != ast::local_crate);
let trait_def = @csearch::get_trait_def(cx, did);
cx.trait_defs.insert(did, trait_def);
return trait_def;
}
}
}
// Look up a field ID, whether or not it's local // Look up a field ID, whether or not it's local
// Takes a list of type substs in case the struct is generic // Takes a list of type substs in case the struct is generic
pub fn lookup_field_type(tcx: ctxt, pub fn lookup_field_type(tcx: ctxt,
@ -4250,9 +4264,6 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
t t
}, },
ty_trait(did, ref substs, BareTraitStore) =>
mk_trait(cx, did, copy *substs, BoxTraitStore),
_ => _ =>
t t
}; };
@ -4318,12 +4329,11 @@ pub fn determine_inherited_purity(parent_purity: ast::purity,
// list. // list.
pub fn iter_bound_traits_and_supertraits(tcx: ctxt, pub fn iter_bound_traits_and_supertraits(tcx: ctxt,
bounds: param_bounds, bounds: param_bounds,
f: &fn(t) -> bool) { f: &fn(&TraitRef) -> bool) {
let mut fin = false; let mut fin = false;
for bounds.each |bound| { for bounds.each |bound| {
let bound_trait_ref = match *bound {
let bound_trait_ty = match *bound {
ty::bound_trait(bound_t) => bound_t, ty::bound_trait(bound_t) => bound_t,
ty::bound_copy | ty::bound_owned | ty::bound_copy | ty::bound_owned |
@ -4332,39 +4342,38 @@ pub fn iter_bound_traits_and_supertraits(tcx: ctxt,
} }
}; };
let mut supertrait_map = HashMap::new(); let mut supertrait_set = HashMap::new();
let mut seen_def_ids = ~[]; let mut seen_def_ids = ~[];
let mut i = 0; let mut i = 0;
let trait_ty_id = ty_to_def_id(bound_trait_ty).expect( let trait_ty_id = bound_trait_ref.def_id;
~"iter_trait_ty_supertraits got a non-trait type"); let mut trait_ref = bound_trait_ref;
let mut trait_ty = bound_trait_ty;
debug!("iter_bound_traits_and_supertraits: trait_ty = %s", debug!("iter_bound_traits_and_supertraits: trait_ref = %s",
ty_to_str(tcx, trait_ty)); trait_ref_to_str(tcx, trait_ref));
// Add the given trait ty to the hash map // Add the given trait ty to the hash map
supertrait_map.insert(trait_ty_id, trait_ty); supertrait_set.insert(trait_ty_id, ());
seen_def_ids.push(trait_ty_id); seen_def_ids.push(trait_ty_id);
if f(trait_ty) { if f(trait_ref) {
// Add all the supertraits to the hash map, // Add all the supertraits to the hash map,
// executing <f> on each of them // executing <f> on each of them
while i < supertrait_map.len() && !fin { while i < supertrait_set.len() && !fin {
let init_trait_id = seen_def_ids[i]; let init_trait_id = seen_def_ids[i];
i += 1; i += 1;
// Add supertraits to supertrait_map
let supertraits = trait_supertraits(tcx, init_trait_id); // Add supertraits to supertrait_set
for supertraits.each |supertrait| { let supertrait_refs = trait_supertraits(tcx, init_trait_id);
let super_t = supertrait.tpt.ty; for supertrait_refs.each |&supertrait_ref| {
let d_id = ty_to_def_id(super_t).expect("supertrait \ let d_id = supertrait_ref.def_id;
should be a trait ty"); if !supertrait_set.contains_key(&d_id) {
if !supertrait_map.contains_key(&d_id) { // NOTE Could have same trait multiple times
supertrait_map.insert(d_id, super_t); supertrait_set.insert(d_id, ());
trait_ty = super_t; trait_ref = supertrait_ref;
seen_def_ids.push(d_id); seen_def_ids.push(d_id);
} }
debug!("A super_t = %s", ty_to_str(tcx, trait_ty)); debug!("A super_t = %s", trait_ref_to_str(tcx, trait_ref));
if !f(trait_ty) { if !f(trait_ref) {
fin = true; fin = true;
} }
} }
@ -4401,6 +4410,14 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
} }
} }
pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
let ty_visitor_name = special_idents::ty_visitor;
assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name);
(trait_ref,
mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore))
}
// Local Variables: // Local Variables:
// mode: rust // mode: rust
// fill-column: 78; // fill-column: 78;

View file

@ -14,14 +14,14 @@
* is parameterized by an instance of `AstConv` and a `region_scope`. * is parameterized by an instance of `AstConv` and a `region_scope`.
* *
* The parameterization of `ast_ty_to_ty()` is because it behaves * The parameterization of `ast_ty_to_ty()` is because it behaves
* somewhat differently during the collect and check phases, particularly * somewhat differently during the collect and check phases,
* with respect to looking up the types of top-level items. In the * particularly with respect to looking up the types of top-level
* collect phase, the crate context is used as the `AstConv` instance; * items. In the collect phase, the crate context is used as the
* in this phase, the `get_item_ty()` function triggers a recursive call * `AstConv` instance; in this phase, the `get_item_ty()` function
* to `ty_of_item()` (note that `ast_ty_to_ty()` will detect recursive * triggers a recursive call to `ty_of_item()` (note that
* types and report an error). In the check phase, when the @FnCtxt is * `ast_ty_to_ty()` will detect recursive types and report an error).
* used as the `AstConv`, `get_item_ty()` just looks up the item type in * In the check phase, when the @FnCtxt is used as the `AstConv`,
* `tcx.tcache`. * `get_item_ty()` just looks up the item type in `tcx.tcache`.
* *
* The `region_scope` trait controls how region references are * The `region_scope` trait controls how region references are
* handled. It has two methods which are used to resolve anonymous * handled. It has two methods which are used to resolve anonymous
@ -76,6 +76,7 @@ use util::common::indenter;
pub trait AstConv { pub trait AstConv {
fn tcx(&self) -> ty::ctxt; fn tcx(&self) -> ty::ctxt;
fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty; fn get_item_ty(&self, id: ast::def_id) -> ty::ty_param_bounds_and_ty;
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef;
// what type should we use when a type is omitted? // what type should we use when a type is omitted?
fn ty_infer(&self, span: span) -> ty::t; fn ty_infer(&self, span: span) -> ty::t;
@ -129,62 +130,96 @@ pub fn ast_region_to_region<AC:AstConv,RS:region_scope + Copy + Durable>(
get_region_reporting_err(self.tcx(), span, opt_lifetime, res) get_region_reporting_err(self.tcx(), span, opt_lifetime, res)
} }
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>( fn ast_path_substs<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC, self: &AC,
rscope: &RS, rscope: &RS,
did: ast::def_id, def_id: ast::def_id,
path: @ast::path) decl_generics: &ty::Generics,
-> ty_param_substs_and_ty { path: @ast::path) -> ty::substs
let tcx = self.tcx(); {
let ty::ty_param_bounds_and_ty { /*!
bounds: decl_bounds, *
region_param: decl_rp, * Given a path `path` that refers to an item `I` with the
ty: decl_ty * declared generics `decl_generics`, returns an appropriate
} = self.get_item_ty(did); * set of substitutions for this particular reference to `I`.
*/
debug!("ast_path_to_substs_and_ty: did=%? decl_rp=%?", let tcx = self.tcx();
did, decl_rp);
// If the type is parameterized by the self region, then replace self // If the type is parameterized by the self region, then replace self
// region with the current anon region binding (in other words, // region with the current anon region binding (in other words,
// whatever & would get replaced with). // whatever & would get replaced with).
let self_r = match (decl_rp, path.rp) { let self_r = match (&decl_generics.region_param, &path.rp) {
(None, None) => { (&None, &None) => {
None None
} }
(None, Some(_)) => { (&None, &Some(_)) => {
tcx.sess.span_err( tcx.sess.span_err(
path.span, path.span,
fmt!("no region bound is allowed on `%s`, \ fmt!("no region bound is allowed on `%s`, \
which is not declared as containing region pointers", which is not declared as containing region pointers",
ty::item_path_str(tcx, did))); ty::item_path_str(tcx, def_id)));
None None
} }
(Some(_), None) => { (&Some(_), &None) => {
let res = rscope.anon_region(path.span); let res = rscope.anon_region(path.span);
let r = get_region_reporting_err(self.tcx(), path.span, None, res); let r = get_region_reporting_err(self.tcx(), path.span, None, res);
Some(r) Some(r)
} }
(Some(_), Some(_)) => { (&Some(_), &Some(_)) => {
Some(ast_region_to_region(self, rscope, path.span, path.rp)) Some(ast_region_to_region(self, rscope, path.span, path.rp))
} }
}; };
// Convert the type parameters supplied by the user. // Convert the type parameters supplied by the user.
if !vec::same_length(*decl_bounds, path.types) { if !vec::same_length(*decl_generics.bounds, path.types) {
self.tcx().sess.span_fatal( self.tcx().sess.span_fatal(
path.span, path.span,
fmt!("wrong number of type arguments: expected %u but found %u", fmt!("wrong number of type arguments: expected %u but found %u",
(*decl_bounds).len(), path.types.len())); decl_generics.bounds.len(), path.types.len()));
} }
let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t)); let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t));
let substs = substs {self_r:self_r, self_ty:None, tps:tps}; substs {self_r:self_r, self_ty:None, tps:tps}
let ty = ty::subst(tcx, &substs, decl_ty); }
pub fn ast_path_to_substs_and_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
did: ast::def_id,
path: @ast::path) -> ty_param_substs_and_ty
{
let tcx = self.tcx();
let ty::ty_param_bounds_and_ty {
generics: generics,
ty: decl_ty
} = self.get_item_ty(did);
let substs = ast_path_substs(self, rscope, did, &generics, path);
let ty = ty::subst(tcx, &substs, decl_ty);
ty_param_substs_and_ty { substs: substs, ty: ty } ty_param_substs_and_ty { substs: substs, ty: ty }
} }
pub fn ast_path_to_trait_ref<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC,
rscope: &RS,
trait_def_id: ast::def_id,
path: @ast::path) -> @ty::TraitRef
{
let trait_def =
self.get_trait_def(trait_def_id);
let substs =
ast_path_substs(
self, rscope,
trait_def.trait_ref.def_id, &trait_def.generics,
path);
let trait_ref =
@ty::TraitRef {def_id: trait_def_id,
substs: substs};
return trait_ref;
}
pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>( pub fn ast_path_to_ty<AC:AstConv,RS:region_scope + Copy + Durable>(
self: &AC, self: &AC,
rscope: &RS, rscope: &RS,
@ -243,12 +278,9 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
check_path_args(tcx, path, NO_TPS | NO_REGIONS); check_path_args(tcx, path, NO_TPS | NO_REGIONS);
return ty::mk_estr(tcx, vst); return ty::mk_estr(tcx, vst);
} }
Some(&ast::def_trait(type_def_id)) => { Some(&ast::def_trait(trait_def_id)) => {
let result = ast_path_to_substs_and_ty( let result = ast_path_to_trait_ref(
self, rscope, self, rscope, trait_def_id, path);
type_def_id, path);
match ty::get(result.ty).sty {
ty::ty_trait(trait_def_id, ref substs, _) => {
let trait_store = match vst { let trait_store = match vst {
ty::vstore_box => ty::BoxTraitStore, ty::vstore_box => ty::BoxTraitStore,
ty::vstore_uniq => ty::UniqTraitStore, ty::vstore_uniq => ty::UniqTraitStore,
@ -266,17 +298,9 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
} }
}; };
return ty::mk_trait(tcx, return ty::mk_trait(tcx,
trait_def_id, result.def_id,
/*bad*/copy *substs, copy result.substs,
trait_store); trait_store);
}
_ => {
tcx.sess.span_bug(
a_seq_ty.ty.span,
fmt!("def_trait but not ty_trait"));
}
}
} }
_ => {} _ => {}
} }
@ -376,7 +400,16 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:region_scope + Copy + Durable>(
Some(&d) => d Some(&d) => d
}; };
match a_def { match a_def {
ast::def_trait(did) | ast::def_ty(did) | ast::def_struct(did) => { ast::def_trait(_) => {
let path_str = path_to_str(path, tcx.sess.intr());
tcx.sess.span_err(
ast_ty.span,
fmt!("reference to trait `%s` where a type is expected; \
try `@%s`, `~%s`, or `&%s`",
path_str, path_str, path_str, path_str));
ty::mk_err(tcx)
}
ast::def_ty(did) | ast::def_struct(did) => {
ast_path_to_ty(self, rscope, did, path).ty ast_path_to_ty(self, rscope, did, path).ty
} }
ast::def_prim_ty(nty) => { ast::def_prim_ty(nty) => {

View file

@ -135,7 +135,7 @@ pub fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
ty::enum_variant_with_id(tcx, enm, var); ty::enum_variant_with_id(tcx, enm, var);
let var_tpt = ty::lookup_item_type(tcx, var); let var_tpt = ty::lookup_item_type(tcx, var);
vinfo.args.map(|t| { vinfo.args.map(|t| {
if var_tpt.bounds.len() == expected_substs.tps.len() { if var_tpt.generics.bounds.len() == expected_substs.tps.len() {
ty::subst(tcx, expected_substs, *t) ty::subst(tcx, expected_substs, *t)
} }
else { else {

View file

@ -382,7 +382,7 @@ pub impl<'self> LookupContext<'self> {
let bounds = tcx.ty_param_bounds.get(&param_ty.def_id.node); let bounds = tcx.ty_param_bounds.get(&param_ty.def_id.node);
for bounds.each |bound| { for bounds.each |bound| {
let bound_trait_ty = match *bound { let bound_trait_ref = match *bound {
ty::bound_trait(bound_t) => bound_t, ty::bound_trait(bound_t) => bound_t,
ty::bound_copy | ty::bound_owned | ty::bound_copy | ty::bound_owned |
@ -391,22 +391,10 @@ pub impl<'self> LookupContext<'self> {
} }
}; };
let bound_substs = match ty::get(bound_trait_ty).sty {
ty::ty_trait(_, ref substs, _) => (/*bad*/copy *substs),
_ => {
self.bug(fmt!("add_candidates_from_param: \
non-trait bound %s",
self.ty_to_str(bound_trait_ty)));
}
};
// Loop over the trait and all of its supertraits. // Loop over the trait and all of its supertraits.
let mut worklist = ~[]; let mut worklist = ~[];
let init_trait_ty = bound_trait_ty; let init_trait_ref = bound_trait_ref;
let init_substs = bound_substs;
// Replace any appearance of `self` with the type of the // Replace any appearance of `self` with the type of the
// generic parameter itself. Note that this is the only // generic parameter itself. Note that this is the only
@ -417,29 +405,26 @@ pub impl<'self> LookupContext<'self> {
// to self are not permitted). // to self are not permitted).
let init_substs = substs { let init_substs = substs {
self_ty: Some(rcvr_ty), self_ty: Some(rcvr_ty),
..init_substs ..copy bound_trait_ref.substs
}; };
worklist.push((init_trait_ty, init_substs)); worklist.push((init_trait_ref.def_id, init_substs));
let mut i = 0; let mut i = 0;
while i < worklist.len() { while i < worklist.len() {
let (init_trait_ty, init_substs) = /*bad*/copy worklist[i]; let (init_trait_id, init_substs) = /*bad*/copy worklist[i];
i += 1; i += 1;
let init_trait_id = ty::ty_to_def_id(init_trait_ty).get();
// Add all the supertraits of this trait to the worklist. // Add all the supertraits of this trait to the worklist.
let supertraits = ty::trait_supertraits(tcx, let supertraits = ty::trait_supertraits(tcx, init_trait_id);
init_trait_id); for supertraits.each |supertrait_ref| {
for supertraits.each |supertrait| {
debug!("adding supertrait: %?", debug!("adding supertrait: %?",
supertrait.def_id); supertrait_ref.def_id);
let new_substs = ty::subst_substs( let new_substs = ty::subst_in_substs(
tcx, tcx,
&supertrait.tpt.substs, &init_substs,
&init_substs); &supertrait_ref.substs);
// Again replacing the self type // Again replacing the self type
let new_substs = substs { let new_substs = substs {
@ -447,7 +432,7 @@ pub impl<'self> LookupContext<'self> {
..new_substs ..new_substs
}; };
worklist.push((supertrait.tpt.ty, new_substs)); worklist.push((supertrait_ref.def_id, new_substs));
} }
@ -1116,7 +1101,7 @@ pub impl<'self> LookupContext<'self> {
// If they were not explicitly supplied, just construct fresh // If they were not explicitly supplied, just construct fresh
// type variables. // type variables.
let num_supplied_tps = self.supplied_tps.len(); let num_supplied_tps = self.supplied_tps.len();
let num_method_tps = candidate.method_ty.tps.len(); let num_method_tps = candidate.method_ty.generics.bounds.len();
let m_substs = { let m_substs = {
if num_supplied_tps == 0u { if num_supplied_tps == 0u {
self.fcx.infcx().next_ty_vars(num_method_tps) self.fcx.infcx().next_ty_vars(num_method_tps)
@ -1210,7 +1195,7 @@ pub impl<'self> LookupContext<'self> {
self-type through a boxed trait"); self-type through a boxed trait");
} }
if candidate.method_ty.tps.len() > 0 { if candidate.method_ty.generics.bounds.len() > 0 {
self.tcx().sess.span_err( self.tcx().sess.span_err(
self.expr.span, self.expr.span,
~"cannot call a generic method through a boxed trait"); ~"cannot call a generic method through a boxed trait");

View file

@ -610,7 +610,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
} else { } else {
for m.items.each |item| { for m.items.each |item| {
let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id)); let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
if !tpt.bounds.is_empty() { if !tpt.generics.bounds.is_empty() {
ccx.tcx.sess.span_err( ccx.tcx.sess.span_err(
item.span, item.span,
fmt!("foreign items may not have type parameters")); fmt!("foreign items may not have type parameters"));
@ -629,6 +629,10 @@ impl AstConv for FnCtxt {
ty::lookup_item_type(self.tcx(), id) ty::lookup_item_type(self.tcx(), id)
} }
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef {
ty::lookup_trait_def(self.tcx(), id)
}
fn ty_infer(&self, _span: span) -> ty::t { fn ty_infer(&self, _span: span) -> ty::t {
self.infcx().next_ty_var() self.infcx().next_ty_var()
} }
@ -1064,7 +1068,7 @@ pub fn impl_self_ty(vcx: &VtableContext,
let (n_tps, region_param, raw_ty) = { let (n_tps, region_param, raw_ty) = {
let ity = ty::lookup_item_type(tcx, did); let ity = ty::lookup_item_type(tcx, did);
(vec::len(*ity.bounds), ity.region_param, ity.ty) (ity.generics.bounds.len(), ity.generics.region_param, ity.ty)
}; };
let self_r = if region_param.is_some() { let self_r = if region_param.is_some() {
@ -1888,8 +1892,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
} }
} else { } else {
let item_type = ty::lookup_item_type(tcx, class_id); let item_type = ty::lookup_item_type(tcx, class_id);
type_parameter_count = (*item_type.bounds).len(); type_parameter_count = item_type.generics.bounds.len();
region_parameterized = item_type.region_param; region_parameterized = item_type.generics.region_param;
raw_type = item_type.ty; raw_type = item_type.ty;
} }
@ -1976,8 +1980,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
} }
} else { } else {
let item_type = ty::lookup_item_type(tcx, enum_id); let item_type = ty::lookup_item_type(tcx, enum_id);
type_parameter_count = (*item_type.bounds).len(); type_parameter_count = item_type.generics.bounds.len();
region_parameterized = item_type.region_param; region_parameterized = item_type.generics.region_param;
raw_type = item_type.ty; raw_type = item_type.ty;
} }
@ -3147,8 +3151,10 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt,
ast::def_fn(_, ast::extern_fn) => { ast::def_fn(_, ast::extern_fn) => {
// extern functions are just u8 pointers // extern functions are just u8 pointers
return ty_param_bounds_and_ty { return ty_param_bounds_and_ty {
generics: ty::Generics {
bounds: @~[], bounds: @~[],
region_param: None, region_param: None
},
ty: ty::mk_ptr( ty: ty::mk_ptr(
fcx.ccx.tcx, fcx.ccx.tcx,
ty::mt { ty::mt {
@ -3211,7 +3217,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
region_lb: ty::Region) { region_lb: ty::Region) {
debug!(">>> instantiate_path"); debug!(">>> instantiate_path");
let ty_param_count = vec::len(*tpt.bounds); let ty_param_count = tpt.generics.bounds.len();
let ty_substs_len = vec::len(pth.types); let ty_substs_len = vec::len(pth.types);
debug!("ty_param_count=%? ty_substs_len=%?", debug!("ty_param_count=%? ty_substs_len=%?",
@ -3222,7 +3228,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
// (if any) and otherwise using a fresh region variable // (if any) and otherwise using a fresh region variable
let self_r = match pth.rp { let self_r = match pth.rp {
Some(_) => { // user supplied a lifetime parameter... Some(_) => { // user supplied a lifetime parameter...
match tpt.region_param { match tpt.generics.region_param {
None => { // ...but the type is not lifetime parameterized! None => { // ...but the type is not lifetime parameterized!
fcx.ccx.tcx.sess.span_err fcx.ccx.tcx.sess.span_err
(span, ~"this item is not region-parameterized"); (span, ~"this item is not region-parameterized");
@ -3235,7 +3241,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
} }
None => { // no lifetime parameter supplied, insert default None => { // no lifetime parameter supplied, insert default
fcx.region_var_if_parameterized( fcx.region_var_if_parameterized(
tpt.region_param, span, region_lb) tpt.generics.region_param, span, region_lb)
} }
}; };
@ -3433,28 +3439,13 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
} }
~"visit_tydesc" => { ~"visit_tydesc" => {
let tydesc_name = special_idents::tydesc; let tydesc_name = special_idents::tydesc;
let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor");
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
assert!(ccx.tcx.intrinsic_defs.contains_key(&ty_visitor_name));
let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name); let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
let (_, visitor_trait) = *tcx.intrinsic_defs.get(&ty_visitor_name); let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
let visitor_trait = match ty::get(visitor_trait).sty {
ty::ty_trait(trait_def_id, ref trait_substs, _) => {
ty::mk_trait(tcx,
trait_def_id,
copy *trait_substs,
ty::BoxTraitStore)
}
_ => {
tcx.sess.span_bug(it.span, ~"TyVisitor wasn't a trait?!")
}
};
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty, let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty,
mutbl: ast::m_imm}); mutbl: ast::m_imm});
(0u, ~[arg(ast::by_copy, td_ptr), (0u, ~[arg(ast::by_copy, td_ptr),
arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx)) arg(ast::by_ref, visitor_object_ty)], ty::mk_nil(tcx))
} }
~"frame_address" => { ~"frame_address" => {
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
@ -3700,7 +3691,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
output: output} output: output}
}); });
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id)); let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
let i_n_tps = (*i_ty.bounds).len(); let i_n_tps = i_ty.generics.bounds.len();
if i_n_tps != n_tps { if i_n_tps != n_tps {
tcx.sess.span_err(it.span, fmt!("intrinsic has wrong number \ tcx.sess.span_err(it.span, fmt!("intrinsic has wrong number \
of type parameters: found %u, \ of type parameters: found %u, \

View file

@ -70,7 +70,7 @@ pub impl VtableContext {
fn tcx(&const self) -> ty::ctxt { self.ccx.tcx } fn tcx(&const self) -> ty::ctxt { self.ccx.tcx }
} }
pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool { fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
vec::any(tps, |bs| { vec::any(tps, |bs| {
bs.any(|b| { bs.any(|b| {
match b { &ty::bound_trait(_) => true, _ => false } match b { &ty::bound_trait(_) => true, _ => false }
@ -78,7 +78,7 @@ pub fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
}) })
} }
pub fn lookup_vtables(vcx: &VtableContext, fn lookup_vtables(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
bounds: @~[ty::param_bounds], bounds: @~[ty::param_bounds],
substs: &ty::substs, substs: &ty::substs,
@ -95,30 +95,30 @@ pub fn lookup_vtables(vcx: &VtableContext,
let mut result = ~[], i = 0u; let mut result = ~[], i = 0u;
for substs.tps.each |ty| { for substs.tps.each |ty| {
for ty::iter_bound_traits_and_supertraits( for ty::iter_bound_traits_and_supertraits(
tcx, bounds[i]) |trait_ty| tcx, bounds[i]) |trait_ref|
{ {
debug!("about to subst: %?, %?", debug!("about to subst: %?, %?",
ppaux::ty_to_str(tcx, trait_ty), ppaux::trait_ref_to_str(tcx, trait_ref),
ty::substs_to_str(tcx, substs)); ty::substs_to_str(tcx, substs));
let new_substs = substs { let new_substs = substs {
self_ty: Some(*ty), self_ty: Some(*ty),
../*bad*/copy *substs ../*bad*/copy *substs
}; };
let trait_ty = ty::subst(tcx, &new_substs, trait_ty); let trait_ref = ty::subst_in_trait_ref(tcx, &new_substs, trait_ref);
debug!("after subst: %?", debug!("after subst: %?",
ppaux::ty_to_str(tcx, trait_ty)); vcx.infcx.trait_ref_to_str(&trait_ref));
match lookup_vtable(vcx, location_info, *ty, trait_ty, is_early) { match lookup_vtable(vcx, location_info, *ty, &trait_ref, is_early) {
Some(vtable) => result.push(vtable), Some(vtable) => result.push(vtable),
None => { None => {
vcx.tcx().sess.span_fatal( vcx.tcx().sess.span_fatal(
location_info.span, location_info.span,
fmt!("failed to find an implementation of \ fmt!("failed to find an implementation of \
trait %s for %s", trait %s for %s",
ppaux::ty_to_str(vcx.tcx(), trait_ty), vcx.infcx.trait_ref_to_str(&trait_ref),
ppaux::ty_to_str(vcx.tcx(), *ty))); vcx.infcx.ty_to_str(*ty)));
} }
} }
} }
@ -136,7 +136,7 @@ pub fn lookup_vtables(vcx: &VtableContext,
@result @result
} }
pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
id: ast::def_id, +substs: ty::substs, id: ast::def_id, +substs: ty::substs,
is_early: bool) -> Option<ty::substs> { is_early: bool) -> Option<ty::substs> {
let tcx = vcx.tcx(); let tcx = vcx.tcx();
@ -152,31 +152,58 @@ pub fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo,
} }
} }
pub fn relate_trait_tys(vcx: &VtableContext, location_info: &LocationInfo, fn relate_trait_refs(vcx: &VtableContext,
exp_trait_ty: ty::t, act_trait_ty: ty::t) { location_info: &LocationInfo,
demand_suptype(vcx, location_info.span, exp_trait_ty, act_trait_ty) act_trait_ref: &ty::TraitRef,
exp_trait_ref: &ty::TraitRef)
{
/*!
*
* Checks that an implementation of `act_trait_ref` is suitable
* for use where `exp_trait_ref` is required and reports an
* error otherwise.
*/
match infer::mk_sub_trait_refs(vcx.infcx, false, location_info.span,
act_trait_ref, exp_trait_ref)
{
result::Ok(()) => {} // Ok.
result::Err(ref err) => {
let r_act_trait_ref =
vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(act_trait_ref);
let r_exp_trait_ref =
vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(exp_trait_ref);
if !ty::trait_ref_contains_error(&r_act_trait_ref) &&
!ty::trait_ref_contains_error(&r_exp_trait_ref)
{
let tcx = vcx.tcx();
tcx.sess.span_err(
location_info.span,
fmt!("expected %s, but found %s (%s)",
ppaux::trait_ref_to_str(tcx, &r_exp_trait_ref),
ppaux::trait_ref_to_str(tcx, &r_act_trait_ref),
ty::type_err_to_str(tcx, err)));
}
}
}
} }
// Look up the vtable to use when treating an item of type `t` as if it has // Look up the vtable to use when treating an item of type `t` as if it has
// type `trait_ty` // type `trait_ty`
pub fn lookup_vtable(vcx: &VtableContext, fn lookup_vtable(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
ty: ty::t, ty: ty::t,
trait_ty: ty::t, trait_ref: &ty::TraitRef,
is_early: bool) is_early: bool)
-> Option<vtable_origin> { -> Option<vtable_origin>
debug!("lookup_vtable(ty=%s, trait_ty=%s)", {
vcx.infcx.ty_to_str(ty), vcx.infcx.ty_to_str(trait_ty)); debug!("lookup_vtable(ty=%s, trait_ref=%s)",
vcx.infcx.ty_to_str(ty),
vcx.infcx.trait_ref_to_str(trait_ref));
let _i = indenter(); let _i = indenter();
let tcx = vcx.tcx(); let tcx = vcx.tcx();
let (trait_id, trait_substs, trait_store) = match ty::get(trait_ty).sty {
ty::ty_trait(did, ref substs, store) =>
(did, (/*bad*/copy *substs), store),
_ => tcx.sess.impossible_case(location_info.span,
"lookup_vtable: \
don't know how to handle a non-trait")
};
let ty = match fixup_ty(vcx, location_info, ty, is_early) { let ty = match fixup_ty(vcx, location_info, ty, is_early) {
Some(ty) => ty, Some(ty) => ty,
None => { None => {
@ -194,38 +221,21 @@ pub fn lookup_vtable(vcx: &VtableContext,
let mut n_bound = 0; let mut n_bound = 0;
let bounds = *tcx.ty_param_bounds.get(&did.node); let bounds = *tcx.ty_param_bounds.get(&did.node);
for ty::iter_bound_traits_and_supertraits( for ty::iter_bound_traits_and_supertraits(
tcx, bounds) |ity| { tcx, bounds) |bound_trait_ref|
{
debug!("checking bounds trait %?", debug!("checking bounds trait %?",
vcx.infcx.ty_to_str(ity)); vcx.infcx.trait_ref_to_str(bound_trait_ref));
match ty::get(ity).sty { if bound_trait_ref.def_id == trait_ref.def_id {
ty::ty_trait(idid, ref isubsts, _) => { relate_trait_refs(vcx,
if trait_id == idid { location_info,
debug!("(checking vtable) @0 \ bound_trait_ref,
relating ty to trait \ trait_ref);
ty with did %?",
idid);
// Convert `ity` so that it has the right vstore.
let ity = ty::mk_trait(vcx.tcx(),
idid,
copy *isubsts,
trait_store);
relate_trait_tys(vcx, location_info,
trait_ty, ity);
let vtable = vtable_param(n, n_bound); let vtable = vtable_param(n, n_bound);
debug!("found param vtable: %?", debug!("found param vtable: %?",
vtable); vtable);
return Some(vtable); return Some(vtable);
} }
}
_ => tcx.sess.impossible_case(
location_info.span,
"lookup_vtable: in loop, \
don't know how to handle a \
non-trait ity")
}
n_bound += 1; n_bound += 1;
} }
@ -236,18 +246,19 @@ pub fn lookup_vtable(vcx: &VtableContext,
let mut impls_seen = HashSet::new(); let mut impls_seen = HashSet::new();
match vcx.ccx.coherence_info.extension_methods.find(&trait_id) { match vcx.ccx.coherence_info.extension_methods.find(&trait_ref.def_id) {
None => { None => {
// Nothing found. Continue. // Nothing found. Continue.
} }
Some(implementations) => { Some(implementations) => {
let implementations: &mut ~[@Impl] = *implementations; let implementations: &mut ~[@Impl] = *implementations;
// implementations is the list of all impls in scope for // implementations is the list of all impls in scope for
// trait_ty. (Usually, there's just one.) // trait_ref. (Usually, there's just one.)
for uint::range(0, implementations.len()) |i| { for uint::range(0, implementations.len()) |i| {
let im = implementations[i]; let im = implementations[i];
// im is one specific impl of trait_ty. // im is one specific impl of trait_ref.
// First, ensure we haven't processed this impl yet. // First, ensure we haven't processed this impl yet.
if impls_seen.contains(&im.did) { if impls_seen.contains(&im.did) {
@ -269,22 +280,15 @@ pub fn lookup_vtable(vcx: &VtableContext,
// ~[baz<int>, bar, quux] // ~[baz<int>, bar, quux]
// //
// For each of the traits foo implements, if // For each of the traits foo implements, if
// it's the same trait as trait_ty, we need to // it's the same trait as trait_ref, we need to
// unify it with trait_ty in order to get all // unify it with trait_ref in order to get all
// the ty vars sorted out. // the ty vars sorted out.
for vec::each(ty::impl_traits(tcx, for ty::impl_trait_refs(tcx, im.did).each |&of_trait_ref|
im.did, {
trait_store)) |of_ty| { if of_trait_ref.def_id != trait_ref.def_id { loop; }
match ty::get(*of_ty).sty {
ty::ty_trait(id, _, _) => {
// Not the trait we're looking for
if id != trait_id { loop; }
}
_ => { /* ok */ }
}
// At this point, we know that of_ty is // At this point, we know that of_trait_ref is
// the same trait as trait_ty, but // the same trait as trait_ref, but
// possibly applied to different substs. // possibly applied to different substs.
// //
// Next, we check whether the "for" ty in // Next, we check whether the "for" ty in
@ -318,39 +322,36 @@ pub fn lookup_vtable(vcx: &VtableContext,
vcx.infcx.ty_to_str(for_ty), vcx.infcx.ty_to_str(for_ty),
tys_to_str(vcx.tcx(), substs.tps)); tys_to_str(vcx.tcx(), substs.tps));
// Next, we unify trait_ty -- the type // Next, we unify trait_ref -- the type
// that we want to cast to -- with of_ty // that we want to cast to -- with of_trait_ref
// -- the trait that im implements. At // -- the trait that im implements. At
// this point, we require that they be // this point, we require that they be
// unifiable with each other -- that's // unifiable with each other -- that's
// what relate_trait_tys does. // what relate_trait_refs does.
// //
// For example, in the above example, // For example, in the above example,
// of_ty would be some_trait<T>, so we // of_trait_ref would be some_trait<T>, so we
// would be unifying trait_ty<U> (for some // would be unifying trait_ref<U> (for some
// value of U) with some_trait<T>. This // value of U) with some_trait<T>. This
// would fail if T and U weren't // would fail if T and U weren't
// compatible. // compatible.
debug!("(checking vtable) @2 relating trait \ debug!("(checking vtable) @2 relating trait \
ty %s to of_ty %s", ty %s to of_trait_ref %s",
vcx.infcx.ty_to_str(trait_ty), vcx.infcx.trait_ref_to_str(trait_ref),
vcx.infcx.ty_to_str(*of_ty)); vcx.infcx.trait_ref_to_str(of_trait_ref));
let of_ty = ty::subst(tcx, &substs, *of_ty);
relate_trait_tys(vcx, location_info, trait_ty,
of_ty);
// Recall that trait_ty -- the trait type let of_trait_ref =
ty::subst_in_trait_ref(tcx, &substs, of_trait_ref);
relate_trait_refs(
vcx, location_info,
&of_trait_ref, trait_ref);
// Recall that trait_ref -- the trait type
// we're casting to -- is the trait with // we're casting to -- is the trait with
// id trait_id applied to the substs // id trait_ref.def_id applied to the substs
// trait_substs. Now we extract out the // trait_ref.substs. Now we extract out the
// types themselves from trait_substs. // types themselves from trait_ref.substs.
let trait_tps = /*bad*/copy trait_substs.tps;
debug!("Casting to a trait ty whose substs \
(trait_tps) are %s",
tys_to_str(vcx.tcx(), trait_tps));
// Recall that substs is the impl self // Recall that substs is the impl self
// type's list of substitutions. That is, // type's list of substitutions. That is,
@ -362,7 +363,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
let substs_f = match fixup_substs(vcx, let substs_f = match fixup_substs(vcx,
location_info, location_info,
trait_id, trait_ref.def_id,
substs, substs,
is_early) { is_early) {
Some(ref substs) => (/*bad*/copy *substs), Some(ref substs) => (/*bad*/copy *substs),
@ -377,7 +378,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
they will be unified with the bounds for \ they will be unified with the bounds for \
the target ty, %s", the target ty, %s",
tys_to_str(vcx.tcx(), substs_f.tps), tys_to_str(vcx.tcx(), substs_f.tps),
tys_to_str(vcx.tcx(), trait_tps)); vcx.infcx.trait_ref_to_str(trait_ref));
// Next, we unify the fixed-up // Next, we unify the fixed-up
// substitutions for the impl self ty with // substitutions for the impl self ty with
@ -386,14 +387,13 @@ pub fn lookup_vtable(vcx: &VtableContext,
// to. connect_trait_tps requires these // to. connect_trait_tps requires these
// lists of types to unify pairwise. // lists of types to unify pairwise.
let im_bs = ty::lookup_item_type(tcx, let im_bs =
im.did).bounds; ty::lookup_item_type(tcx, im.did).generics.bounds;
connect_trait_tps(vcx, connect_trait_tps(vcx,
location_info, location_info,
/*bad*/copy substs_f.tps, &substs_f,
trait_tps, trait_ref,
im.did, im.did);
trait_store);
let subres = lookup_vtables( let subres = lookup_vtables(
vcx, location_info, im_bs, &substs_f, vcx, location_info, im_bs, &substs_f,
is_early); is_early);
@ -430,7 +430,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
return None; return None;
} }
pub fn fixup_ty(vcx: &VtableContext, fn fixup_ty(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
ty: ty::t, ty: ty::t,
is_early: bool) -> Option<ty::t> { is_early: bool) -> Option<ty::t> {
@ -450,43 +450,21 @@ pub fn fixup_ty(vcx: &VtableContext,
} }
} }
// Version of demand::suptype() that takes a vtable context instead of a fn connect_trait_tps(vcx: &VtableContext,
// function context.
pub fn demand_suptype(vcx: &VtableContext, sp: span, e: ty::t, a: ty::t) {
// NB: Order of actual, expected is reversed.
match infer::mk_subty(vcx.infcx, false, sp, a, e) {
result::Ok(()) => {} // Ok.
result::Err(ref err) => {
vcx.infcx.report_mismatched_types(sp, e, a, err);
}
}
}
pub fn connect_trait_tps(vcx: &VtableContext,
location_info: &LocationInfo, location_info: &LocationInfo,
impl_tys: ~[ty::t], impl_substs: &ty::substs,
trait_tys: ~[ty::t], trait_ref: &ty::TraitRef,
impl_did: ast::def_id, impl_did: ast::def_id)
store: ty::TraitStore) { {
let tcx = vcx.tcx(); let tcx = vcx.tcx();
// XXX: This should work for multiple traits. // XXX: This should work for multiple traits.
let ity = ty::impl_traits(tcx, impl_did, store)[0]; let impl_trait_ref = ty::impl_trait_refs(tcx, impl_did)[0];
let trait_ty = ty::subst_tps(tcx, impl_tys, None, ity); let impl_trait_ref = ty::subst_in_trait_ref(tcx, impl_substs, impl_trait_ref);
debug!("(connect trait tps) trait type is %?, impl did is %?", relate_trait_refs(vcx, location_info, trait_ref, &impl_trait_ref);
ty::get(trait_ty).sty, impl_did);
match ty::get(trait_ty).sty {
ty::ty_trait(_, ref substs, _) => {
for vec::each2((*substs).tps, trait_tys) |a, b| {
demand_suptype(vcx, location_info.span, *a, *b);
}
}
_ => tcx.sess.impossible_case(location_info.span, "connect_trait_tps: \
don't know how to handle a non-trait ty")
}
} }
pub fn insert_vtables(fcx: @mut FnCtxt, fn insert_vtables(fcx: @mut FnCtxt,
callee_id: ast::node_id, callee_id: ast::node_id,
vtables: vtable_res) { vtables: vtable_res) {
debug!("insert_vtables(callee_id=%d, vtables=%?)", debug!("insert_vtables(callee_id=%d, vtables=%?)",
@ -517,15 +495,15 @@ pub fn early_resolve_expr(ex: @ast::expr,
let item_ty = ty::lookup_item_type(cx.tcx, did); let item_ty = ty::lookup_item_type(cx.tcx, did);
debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def, debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def,
fcx.infcx().ty_to_str(item_ty.ty)); fcx.infcx().ty_to_str(item_ty.ty));
if has_trait_bounds(/*bad*/copy *item_ty.bounds) { if has_trait_bounds(/*bad*/copy *item_ty.generics.bounds) {
for item_ty.bounds.each |bounds| { for item_ty.generics.bounds.each |bounds| {
debug!("early_resolve_expr: looking up vtables for bound \ debug!("early_resolve_expr: looking up vtables for bound \
%s", %s",
ty::param_bounds_to_str(fcx.tcx(), *bounds)); ty::param_bounds_to_str(fcx.tcx(), *bounds));
} }
let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
item_ty.bounds, substs, is_early); item_ty.generics.bounds, substs, is_early);
if !is_early { if !is_early {
insert_vtables(fcx, ex.id, vtbls); insert_vtables(fcx, ex.id, vtbls);
} }
@ -564,7 +542,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
ast::expr_cast(src, _) => { ast::expr_cast(src, _) => {
let target_ty = fcx.expr_ty(ex); let target_ty = fcx.expr_ty(ex);
match ty::get(target_ty).sty { match ty::get(target_ty).sty {
ty::ty_trait(_, _, store) => { ty::ty_trait(target_def_id, ref target_substs, store) => {
// Look up vtables for the type we're casting to, // Look up vtables for the type we're casting to,
// passing in the source and target type. The source // passing in the source and target type. The source
// must be a pointer type suitable to the object sigil, // must be a pointer type suitable to the object sigil,
@ -573,7 +551,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
fcx.expr_ty(src)); fcx.expr_ty(src));
match (&ty::get(ty).sty, store) { match (&ty::get(ty).sty, store) {
(&ty::ty_box(mt), ty::BoxTraitStore) | (&ty::ty_box(mt), ty::BoxTraitStore) |
// XXX: Bare trait store is deprecated.
(&ty::ty_uniq(mt), ty::UniqTraitStore) | (&ty::ty_uniq(mt), ty::UniqTraitStore) |
(&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => { (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => {
let location_info = let location_info =
@ -582,11 +559,15 @@ pub fn early_resolve_expr(ex: @ast::expr,
ccx: fcx.ccx, ccx: fcx.ccx,
infcx: fcx.infcx() infcx: fcx.infcx()
}; };
let target_trait_ref = ty::TraitRef {
def_id: target_def_id,
substs: copy *target_substs
};
let vtable_opt = let vtable_opt =
lookup_vtable(&vcx, lookup_vtable(&vcx,
location_info, location_info,
mt.ty, mt.ty,
target_ty, &target_trait_ref,
is_early); is_early);
match vtable_opt { match vtable_opt {
Some(vtable) => { Some(vtable) => {
@ -622,11 +603,12 @@ pub fn early_resolve_expr(ex: @ast::expr,
} }
} }
(_, ty::BareTraitStore) => { (_, ty::UniqTraitStore) => {
fcx.ccx.tcx.sess.span_err( fcx.ccx.tcx.sess.span_err(
ex.span, ex.span,
~"a sigil (`@`, `~`, or `&`) must be specified \ fmt!("can only cast an ~-pointer \
when casting to a trait"); to a ~-object, not a %s",
ty::ty_sort_str(fcx.tcx(), ty)));
} }
(_, ty::BoxTraitStore) => { (_, ty::BoxTraitStore) => {
@ -637,14 +619,6 @@ pub fn early_resolve_expr(ex: @ast::expr,
ty::ty_sort_str(fcx.tcx(), ty))); ty::ty_sort_str(fcx.tcx(), ty)));
} }
(_, ty::UniqTraitStore) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
fmt!("can only cast an ~-pointer \
to a ~-object, not a %s",
ty::ty_sort_str(fcx.tcx(), ty)));
}
(_, ty::RegionTraitStore(_)) => { (_, ty::RegionTraitStore(_)) => {
fcx.ccx.tcx.sess.span_err( fcx.ccx.tcx.sess.span_err(
ex.span, ex.span,
@ -661,7 +635,7 @@ pub fn early_resolve_expr(ex: @ast::expr,
} }
} }
pub fn resolve_expr(ex: @ast::expr, fn resolve_expr(ex: @ast::expr,
&&fcx: @mut FnCtxt, &&fcx: @mut FnCtxt,
v: visit::vt<@mut FnCtxt>) { v: visit::vt<@mut FnCtxt>) {
early_resolve_expr(ex, fcx, false); early_resolve_expr(ex, fcx, false);

View file

@ -358,7 +358,7 @@ pub impl CoherenceChecker {
@ProvidedMethodInfo { @ProvidedMethodInfo {
method_info: @MethodInfo { method_info: @MethodInfo {
did: new_did, did: new_did,
n_tps: trait_method.tps.len(), n_tps: trait_method.generics.bounds.len(),
ident: trait_method.ident, ident: trait_method.ident,
self_type: trait_method.self_ty self_type: trait_method.self_ty
}, },
@ -542,10 +542,10 @@ pub impl CoherenceChecker {
-> UniversalQuantificationResult { -> UniversalQuantificationResult {
// NDM--this span is bogus. // NDM--this span is bogus.
let self_region = let self_region =
polytype.region_param.map( polytype.generics.region_param.map(
|_r| self.inference_context.next_region_var_nb(dummy_sp())); |_r| self.inference_context.next_region_var_nb(dummy_sp()));
let bounds_count = polytype.bounds.len(); let bounds_count = polytype.generics.bounds.len();
let type_parameters = let type_parameters =
self.inference_context.next_ty_vars(bounds_count); self.inference_context.next_ty_vars(bounds_count);
@ -565,7 +565,7 @@ pub impl CoherenceChecker {
UniversalQuantificationResult { UniversalQuantificationResult {
monotype: monotype, monotype: monotype,
type_variables: type_parameters, type_variables: type_parameters,
bounds: polytype.bounds bounds: polytype.generics.bounds
} }
} }
@ -864,17 +864,8 @@ pub impl CoherenceChecker {
} }
// Record all the trait methods. // Record all the trait methods.
for associated_traits.each |trait_type| { for associated_traits.each |trait_ref| {
match get(*trait_type).sty { self.add_trait_method(trait_ref.def_id, *implementation);
ty_trait(trait_id, _, _) => {
self.add_trait_method(trait_id, *implementation);
}
_ => {
self.crate_context.tcx.sess.bug(~"trait type \
returned is not a \
trait");
}
}
} }
// Add the implementation to the mapping from // Add the implementation to the mapping from
@ -923,7 +914,7 @@ pub impl CoherenceChecker {
@ProvidedMethodInfo { @ProvidedMethodInfo {
method_info: @MethodInfo { method_info: @MethodInfo {
did: new_did, did: new_did,
n_tps: trait_method_info.ty.tps.len(), n_tps: trait_method_info.ty.generics.bounds.len(),
ident: trait_method_info.ty.ident, ident: trait_method_info.ty.ident,
self_type: trait_method_info.ty.self_ty self_type: trait_method_info.ty.self_ty
}, },
@ -954,15 +945,7 @@ pub impl CoherenceChecker {
def_id); def_id);
} }
dl_def(def_trait(def_id)) => { dl_def(def_trait(def_id)) => {
let tcx = self.crate_context.tcx; self.add_default_methods_for_external_trait(def_id);
let polytype = csearch::get_type(tcx, def_id);
match ty::get(polytype.ty).sty {
ty::ty_trait(*) => {
self.add_default_methods_for_external_trait(
def_id);
}
_ => {}
}
} }
dl_def(_) | dl_impl(_) | dl_field => { dl_def(_) | dl_impl(_) | dl_field => {
// Skip this. // Skip this.

View file

@ -33,7 +33,6 @@ are represented as `ty_param()` instances.
use core::prelude::*; use core::prelude::*;
use metadata::csearch; use metadata::csearch;
use middle::ty::InstantiatedTraitRef;
use middle::ty::{substs, ty_param_bounds_and_ty, ty_param_substs_and_ty}; use middle::ty::{substs, ty_param_bounds_and_ty, ty_param_substs_and_ty};
use middle::ty; use middle::ty;
use middle::typeck::astconv::{AstConv, ty_of_arg}; use middle::typeck::astconv::{AstConv, ty_of_arg};
@ -83,12 +82,10 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
match intrinsic_item.node { match intrinsic_item.node {
ast::item_trait(*) => { ast::item_trait(*) => {
let ty = ty::mk_trait(ccx.tcx, let tref = @ty::TraitRef {def_id: def_id,
def_id, substs: substs};
substs, ccx.tcx.intrinsic_traits.insert
ty::BareTraitStore); (intrinsic_item.ident, tref);
ccx.tcx.intrinsic_defs.insert
(intrinsic_item.ident, (def_id, ty));
} }
ast::item_enum(*) => { ast::item_enum(*) => {
@ -152,6 +149,10 @@ impl AstConv for CrateCtxt {
} }
} }
fn get_trait_def(&self, id: ast::def_id) -> @ty::TraitDef {
get_trait_def(self, id)
}
fn ty_infer(&self, span: span) -> ty::t { fn ty_infer(&self, span: span) -> ty::t {
self.tcx.sess.span_bug(span, self.tcx.sess.span_bug(span,
~"found `ty_infer` in unexpected place"); ~"found `ty_infer` in unexpected place");
@ -186,8 +187,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
ast::struct_variant_kind(struct_def) => { ast::struct_variant_kind(struct_def) => {
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics), generics: ty_generics(ccx, rp, generics),
region_param: rp,
ty: enum_ty ty: enum_ty
}; };
@ -208,8 +208,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
None => {} None => {}
Some(result_ty) => { Some(result_ty) => {
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics), generics: ty_generics(ccx, rp, generics),
region_param: rp,
ty: result_ty ty: result_ty
}; };
tcx.tcache.insert(local_def(variant.node.id), tpt); tcx.tcache.insert(local_def(variant.node.id), tpt);
@ -220,8 +219,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
} }
pub fn ensure_trait_methods(ccx: &CrateCtxt, pub fn ensure_trait_methods(ccx: &CrateCtxt,
trait_id: ast::node_id, trait_id: ast::node_id)
trait_ty: ty::t)
{ {
let tcx = ccx.tcx; let tcx = ccx.tcx;
let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x); let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|&x| *x);
@ -230,7 +228,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
node: ast::item_trait(ref generics, _, ref ms), node: ast::item_trait(ref generics, _, ref ms),
_ _
}, _) => { }, _) => {
let trait_bounds = ty_param_bounds(ccx, generics); let trait_ty_generics = ty_generics(ccx, region_paramd, generics);
// For each method, construct a suitable ty::method and // For each method, construct a suitable ty::method and
// store it into the `tcx.methods` table: // store it into the `tcx.methods` table:
@ -252,9 +250,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
}; };
if ty_method.self_ty == ast::sty_static { if ty_method.self_ty == ast::sty_static {
make_static_method_ty(ccx, region_paramd, make_static_method_ty(ccx, trait_id, ty_method,
ty_method, trait_ty, &trait_ty_generics);
trait_bounds);
} }
tcx.methods.insert(ty_method.def_id, ty_method); tcx.methods.insert(ty_method.def_id, ty_method);
@ -275,12 +272,9 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
} }
fn make_static_method_ty(ccx: &CrateCtxt, fn make_static_method_ty(ccx: &CrateCtxt,
rp: Option<ty::region_variance>, trait_id: ast::node_id,
m: &ty::method, m: &ty::method,
// Take this as an argument b/c we may check trait_ty_generics: &ty::Generics) {
// the impl before the trait.
trait_ty: ty::t,
trait_bounds: @~[ty::param_bounds]) {
// We need to create a typaram that replaces self. This param goes // We need to create a typaram that replaces self. This param goes
// *in between* the typarams from the trait and those from the // *in between* the typarams from the trait and those from the
// method (since its bound can depend on the trait? or // method (since its bound can depend on the trait? or
@ -291,12 +285,13 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
let dummy_defid = ast::def_id {crate: 0, node: 0}; let dummy_defid = ast::def_id {crate: 0, node: 0};
let non_shifted_trait_tps = do vec::from_fn(trait_bounds.len()) |i| { let num_trait_bounds = trait_ty_generics.bounds.len();
let non_shifted_trait_tps = do vec::from_fn(num_trait_bounds) |i| {
ty::mk_param(ccx.tcx, i, dummy_defid) ty::mk_param(ccx.tcx, i, dummy_defid)
}; };
let self_param = ty::mk_param(ccx.tcx, trait_bounds.len(), let self_param = ty::mk_param(ccx.tcx, num_trait_bounds,
dummy_defid); dummy_defid);
let shifted_method_tps = do vec::from_fn(m.tps.len()) |i| { let shifted_method_tps = do vec::from_fn(m.generics.bounds.len()) |i| {
ty::mk_param(ccx.tcx, i + 1, dummy_defid) ty::mk_param(ccx.tcx, i + 1, dummy_defid)
}; };
@ -308,13 +303,20 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
let ty = ty::subst(ccx.tcx, let ty = ty::subst(ccx.tcx,
&substs, &substs,
ty::mk_bare_fn(ccx.tcx, copy m.fty)); ty::mk_bare_fn(ccx.tcx, copy m.fty));
let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] let trait_def = get_trait_def(ccx, local_def(trait_id));
+ *m.tps); let trait_ref = trait_def.trait_ref;
let mut new_bounds = ~[];
new_bounds.push_all(*trait_ty_generics.bounds);
new_bounds.push(@~[ty::bound_trait(trait_ref)]);
new_bounds.push_all(*m.generics.bounds);
ccx.tcx.tcache.insert(m.def_id, ccx.tcx.tcache.insert(m.def_id,
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: bounds, generics: ty::Generics {
region_param: rp, bounds: @new_bounds,
ty: ty}); region_param: trait_ty_generics.region_param
},
ty: ty
});
} }
fn ty_method_of_trait_method(self: &CrateCtxt, fn ty_method_of_trait_method(self: &CrateCtxt,
@ -335,7 +337,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
trait_self_ty, *m_self_ty, m_decl); trait_self_ty, *m_self_ty, m_decl);
ty::method { ty::method {
ident: *m_ident, ident: *m_ident,
tps: ty_param_bounds(self, m_generics), generics: ty_generics(self, None, m_generics),
transformed_self_ty: transformed_self_ty, transformed_self_ty: transformed_self_ty,
fty: fty, fty: fty,
self_ty: m_self_ty.node, self_ty: m_self_ty.node,
@ -350,25 +352,28 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
id: ast::node_id, id: ast::node_id,
sp: codemap::span, sp: codemap::span,
rp: Option<ty::region_variance>, rp: Option<ty::region_variance>,
trait_refs: &[@ast::trait_ref], ast_trait_refs: &[@ast::trait_ref],
generics: &ast::Generics) { generics: &ast::Generics)
{
let tcx = ccx.tcx; let tcx = ccx.tcx;
if tcx.supertraits.contains_key(&local_def(id)) { return; } if tcx.supertraits.contains_key(&local_def(id)) { return; }
let mut instantiated = ~[]; let mut ty_trait_refs: ~[@ty::TraitRef] = ~[];
for trait_refs.each |trait_ref| { for ast_trait_refs.each |&ast_trait_ref| {
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp, generics); let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp, generics);
if instantiated.any(|other_trait: &InstantiatedTraitRef|
{ other_trait.def_id == did }) { // NOTE Could have same trait multiple times
if ty_trait_refs.any(|other_trait| other_trait.def_id == trait_ref.def_id) {
// This means a trait inherited from the same supertrait more // This means a trait inherited from the same supertrait more
// than once. // than once.
tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \ tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \
declaration"); declaration");
return; break;
} else {
ty_trait_refs.push(trait_ref);
} }
instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt });
} }
tcx.supertraits.insert(local_def(id), @instantiated); tcx.supertraits.insert(local_def(id), @ty_trait_refs);
} }
/** /**
@ -422,15 +427,15 @@ pub fn compare_impl_method(tcx: ty::ctxt,
} }
} }
if impl_m.tps.len() != trait_m.tps.len() { if impl_m.generics.bounds.len() != trait_m.generics.bounds.len() {
tcx.sess.span_err( tcx.sess.span_err(
cm.span, cm.span,
fmt!("method `%s` has %u type %s, but its trait \ fmt!("method `%s` has %u type %s, but its trait \
declaration has %u type %s", declaration has %u type %s",
*tcx.sess.str_of(trait_m.ident), impl_m.tps.len(), *tcx.sess.str_of(trait_m.ident), impl_m.generics.bounds.len(),
pluralize(impl_m.tps.len(), ~"parameter"), pluralize(impl_m.generics.bounds.len(), ~"parameter"),
trait_m.tps.len(), trait_m.generics.bounds.len(),
pluralize(trait_m.tps.len(), ~"parameter"))); pluralize(trait_m.generics.bounds.len(), ~"parameter")));
return; return;
} }
@ -448,9 +453,9 @@ pub fn compare_impl_method(tcx: ty::ctxt,
// FIXME(#2687)---we should be checking that the bounds of the // FIXME(#2687)---we should be checking that the bounds of the
// trait imply the bounds of the subtype, but it appears // trait imply the bounds of the subtype, but it appears
// we are...not checking this. // we are...not checking this.
for trait_m.tps.eachi() |i, trait_param_bounds| { for trait_m.generics.bounds.eachi() |i, trait_param_bounds| {
// For each of the corresponding impl ty param's bounds... // For each of the corresponding impl ty param's bounds...
let impl_param_bounds = impl_m.tps[i]; let impl_param_bounds = impl_m.generics.bounds[i];
// Make sure the bounds lists have the same length // Make sure the bounds lists have the same length
// Would be nice to use the ty param names in the error message, // Would be nice to use the ty param names in the error message,
// but we don't have easy access to them here // but we don't have easy access to them here
@ -490,7 +495,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
}; };
debug!("impl_fty: %s", ppaux::ty_to_str(tcx, impl_fty)); debug!("impl_fty: %s", ppaux::ty_to_str(tcx, impl_fty));
let trait_fty = { let trait_fty = {
let dummy_tps = do vec::from_fn((*trait_m.tps).len()) |i| { let dummy_tps = do vec::from_fn(trait_m.generics.bounds.len()) |i| {
// hack: we don't know the def id of the impl tp, but it // hack: we don't know the def id of the impl tp, but it
// is not important for unification // is not important for unification
ty::mk_param(tcx, i + impl_tps, ast::def_id {crate: 0, node: 0}) ty::mk_param(tcx, i + impl_tps, ast::def_id {crate: 0, node: 0})
@ -538,37 +543,23 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
impl_ms: &[ConvertedMethod]) impl_ms: &[ConvertedMethod])
{ {
let tcx = ccx.tcx; let tcx = ccx.tcx;
let (did, tpt) = instantiate_trait_ref(ccx, a_trait_ty, rp, generics); let trait_ref = instantiate_trait_ref(ccx, a_trait_ty, rp, generics);
if did.crate == ast::local_crate { if trait_ref.def_id.crate == ast::local_crate {
// NB: This is subtle. We need to do this on the type of the trait ensure_trait_methods(ccx, trait_ref.def_id.node);
// item *itself*, not on the type that includes the parameter
// substitutions provided by the programmer at this particular
// trait ref. Otherwise, we will potentially overwrite the types of
// the methods within the trait with bogus results. (See issue #3903.)
match tcx.items.find(&did.node) {
Some(&ast_map::node_item(item, _)) => {
let tpt = ty_of_item(ccx, item);
ensure_trait_methods(ccx, did.node, tpt.ty);
}
_ => {
tcx.sess.bug(~"trait ref didn't resolve to trait");
}
}
} }
// Check that each method we impl is a method on the trait // Check that each method we impl is a method on the trait
// Trait methods we don't implement must be default methods, but if not // Trait methods we don't implement must be default methods, but if not
// we'll catch it in coherence // we'll catch it in coherence
let trait_ms = ty::trait_methods(tcx, did); let trait_ms = ty::trait_methods(tcx, trait_ref.def_id);
for impl_ms.each |impl_m| { for impl_ms.each |impl_m| {
match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) { match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
Some(trait_m) => { Some(trait_m) => {
let num_impl_tps = generics.ty_params.len(); let num_impl_tps = generics.ty_params.len();
compare_impl_method( compare_impl_method(
ccx.tcx, num_impl_tps, impl_m, trait_m, ccx.tcx, num_impl_tps, impl_m, trait_m,
&tpt.substs, selfty); &trait_ref.substs, selfty);
} }
None => { None => {
// This method is not part of the trait // This method is not part of the trait
@ -594,8 +585,10 @@ pub fn convert_field(ccx: &CrateCtxt,
/* add the field to the tcache */ /* add the field to the tcache */
ccx.tcx.tcache.insert(local_def(v.node.id), ccx.tcx.tcache.insert(local_def(v.node.id),
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
generics: ty::Generics {
bounds: bounds, bounds: bounds,
region_param: rp, region_param: rp
},
ty: tt ty: tt
}); });
} }
@ -609,28 +602,34 @@ pub struct ConvertedMethod {
pub fn convert_methods(ccx: &CrateCtxt, pub fn convert_methods(ccx: &CrateCtxt,
ms: &[@ast::method], ms: &[@ast::method],
rp: Option<ty::region_variance>,
untransformed_rcvr_ty: ty::t, untransformed_rcvr_ty: ty::t,
rcvr_bounds: @~[ty::param_bounds], rcvr_ty_generics: &ty::Generics,
rcvr_generics: &ast::Generics, rcvr_ast_generics: &ast::Generics,
rcvr_visibility: ast::visibility) rcvr_visibility: ast::visibility)
-> ~[ConvertedMethod] -> ~[ConvertedMethod]
{ {
let tcx = ccx.tcx; let tcx = ccx.tcx;
return vec::map(ms, |m| { return vec::map(ms, |m| {
let bounds = ty_param_bounds(ccx, &m.generics); let m_ty_generics =
let mty = @ty_of_method( ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics);
ccx, *m, rp, untransformed_rcvr_ty, let mty =
rcvr_generics, rcvr_visibility, &m.generics); @ty_of_method(ccx, *m, rcvr_ty_generics.region_param,
let fty = ty::mk_bare_fn(tcx, copy mty.fty); untransformed_rcvr_ty,
rcvr_ast_generics, rcvr_visibility,
&m.generics);
let fty =
ty::mk_bare_fn(tcx, copy mty.fty);
tcx.tcache.insert( tcx.tcache.insert(
local_def(m.id), local_def(m.id),
// n.b.: the type of a method is parameterized by both // n.b.: the type of a method is parameterized by both
// the tps on the receiver and those on the method itself // the tps on the receiver and those on the method itself
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: @(vec::append(/*bad*/copy *rcvr_bounds, *bounds)), generics: ty::Generics {
region_param: rp, bounds: @(vec::append(copy *rcvr_ty_generics.bounds,
*m_ty_generics.bounds)),
region_param: rcvr_ty_generics.region_param
},
ty: fty ty: fty
}); });
write_ty_to_tcx(tcx, m.id, fty); write_ty_to_tcx(tcx, m.id, fty);
@ -657,7 +656,7 @@ pub fn convert_methods(ccx: &CrateCtxt,
m.self_ty, &m.decl); m.self_ty, &m.decl);
ty::method { ty::method {
ident: m.ident, ident: m.ident,
tps: ty_param_bounds(ccx, &m.generics), generics: ty_generics(ccx, None, &m.generics),
transformed_self_ty: transformed_self_ty, transformed_self_ty: transformed_self_ty,
fty: fty, fty: fty,
self_ty: m.self_ty.node, self_ty: m.self_ty.node,
@ -700,15 +699,14 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
rp); rp);
} }
ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => { ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, generics); let i_ty_generics = ty_generics(ccx, rp, generics);
let region_parameterization = let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics); RegionParameterization::from_variance_and_generics(rp, generics);
let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty); let selfty = ccx.to_ty(&type_rscope(region_parameterization), selfty);
write_ty_to_tcx(tcx, it.id, selfty); write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id), tcx.tcache.insert(local_def(it.id),
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: i_bounds, generics: i_ty_generics,
region_param: rp,
ty: selfty}); ty: selfty});
// If there is a trait reference, treat the methods as always public. // If there is a trait reference, treat the methods as always public.
@ -722,26 +720,26 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
it.vis it.vis
}; };
let cms = convert_methods(ccx, *ms, rp, selfty, i_bounds, generics, let cms = convert_methods(ccx, *ms, selfty,
&i_ty_generics, generics,
parent_visibility); parent_visibility);
for opt_trait_ref.each |t| { for opt_trait_ref.each |t| {
check_methods_against_trait(ccx, generics, rp, selfty, *t, cms); check_methods_against_trait(ccx, generics, rp, selfty, *t, cms);
} }
} }
ast::item_trait(ref generics, ref supertraits, ref trait_methods) => { ast::item_trait(ref generics, ref supertraits, ref trait_methods) => {
let tpt = ty_of_item(ccx, it); let trait_def = trait_def_of_item(ccx, it);
debug!("item_trait(it.id=%d, tpt.ty=%s)", tcx.trait_defs.insert(local_def(it.id), trait_def);
it.id, ppaux::ty_to_str(tcx, tpt.ty)); ensure_trait_methods(ccx, it.id);
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id, tpt.ty);
ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics); ensure_supertraits(ccx, it.id, it.span, rp, *supertraits, generics);
let (_, provided_methods) = let (_, provided_methods) =
split_trait_methods(*trait_methods); split_trait_methods(*trait_methods);
let (bounds, _) = mk_substs(ccx, generics, rp); let (ty_generics, _) = mk_substs(ccx, generics, rp);
let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id)); let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
let _ = convert_methods(ccx, provided_methods, rp, let _ = convert_methods(ccx, provided_methods,
untransformed_rcvr_ty, bounds, generics, untransformed_rcvr_ty,
&ty_generics, generics,
it.vis); it.vis);
} }
ast::item_struct(struct_def, ref generics) => { ast::item_struct(struct_def, ref generics) => {
@ -794,14 +792,16 @@ pub fn convert_struct(ccx: &CrateCtxt,
write_ty_to_tcx(tcx, dtor.node.id, t_dtor); write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id), tcx.tcache.insert(local_def(dtor.node.id),
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: tpt.bounds, generics: ty::Generics {
region_param: rp, bounds: tpt.generics.bounds,
region_param: rp
},
ty: t_dtor}); ty: t_dtor});
}; };
// Write the type of each of the members // Write the type of each of the members
for struct_def.fields.each |f| { for struct_def.fields.each |f| {
convert_field(ccx, rp, tpt.bounds, *f, generics); convert_field(ccx, rp, tpt.generics.bounds, *f, generics);
} }
let (_, substs) = mk_substs(ccx, generics, rp); let (_, substs) = mk_substs(ccx, generics, rp);
let selfty = ty::mk_struct(tcx, local_def(id), substs); let selfty = ty::mk_struct(tcx, local_def(id), substs);
@ -824,8 +824,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty); let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty { tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty {
bounds: tpt.bounds, generics: tpt.generics,
region_param: tpt.region_param,
ty: ctor_fn_ty ty: ctor_fn_ty
}); });
} }
@ -842,38 +841,75 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
ccx.tcx.tcache.insert(local_def(i.id), tpt); ccx.tcx.tcache.insert(local_def(i.id), tpt);
} }
/*
Instantiates the path for the given trait reference, assuming that
it's bound to a valid trait type. Returns the def_id for the defining
trait. Fails if the type is a type other than an trait type.
*/
pub fn instantiate_trait_ref(ccx: &CrateCtxt, pub fn instantiate_trait_ref(ccx: &CrateCtxt,
t: @ast::trait_ref, ast_trait_ref: @ast::trait_ref,
rp: Option<ty::region_variance>, rp: Option<ty::region_variance>,
generics: &ast::Generics) generics: &ast::Generics) -> @ty::TraitRef
-> (ast::def_id, ty_param_substs_and_ty) { {
/*!
let sp = t.path.span, err = ~"can only implement trait types", * Instantiates the path for the given trait reference, assuming that
sess = ccx.tcx.sess; * it's bound to a valid trait type. Returns the def_id for the defining
* trait. Fails if the type is a type other than an trait type.
*/
let rp = RegionParameterization::from_variance_and_generics(rp, generics); let rp = RegionParameterization::from_variance_and_generics(rp, generics);
let rscope = type_rscope(rp); let rscope = type_rscope(rp);
match lookup_def_tcx(ccx.tcx, t.path.span, t.ref_id) { match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
ast::def_trait(t_id) => { ast::def_trait(trait_did) => {
let tpt = astconv::ast_path_to_ty(ccx, &rscope, t_id, t.path); let trait_ref =
astconv::ast_path_to_trait_ref(
ccx, &rscope, trait_did, ast_trait_ref.path);
ccx.tcx.trait_refs.insert(
ast_trait_ref.ref_id, trait_ref);
return trait_ref;
}
_ => {
ccx.tcx.sess.span_fatal(
ast_trait_ref.path.span,
fmt!("%s is not a trait",
path_to_str(ast_trait_ref.path,
ccx.tcx.sess.intr())));
}
}
}
write_tpt_to_tcx(ccx.tcx, t.ref_id, &tpt); fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::def_id) -> @ty::TraitDef {
if trait_id.crate != ast::local_crate {
ty::lookup_trait_def(ccx.tcx, trait_id)
} else {
match ccx.tcx.items.get(&trait_id.node) {
&ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
_ => ccx.tcx.sess.bug(fmt!("get_trait_def(%d): not an item",
trait_id.node))
}
}
}
match ty::get(tpt.ty).sty { pub fn trait_def_of_item(ccx: &CrateCtxt, it: @ast::item) -> @ty::TraitDef {
ty::ty_trait(*) => { let def_id = local_def(it.id);
(t_id, tpt) let tcx = ccx.tcx;
match tcx.trait_defs.find(&def_id) {
Some(&def) => return def,
_ => {}
} }
_ => sess.span_fatal(sp, err), let rp = tcx.region_paramd_items.find(&it.id).map_consume(|x| *x);
match it.node {
ast::item_trait(ref generics, _, _) => {
let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let trait_ref = @ty::TraitRef {def_id: def_id,
substs: substs};
let trait_def = @ty::TraitDef {generics: ty_generics,
trait_ref: trait_ref};
tcx.trait_defs.insert(def_id, trait_def);
return trait_def;
} }
ref s => {
tcx.sess.span_bug(
it.span,
fmt!("trait_def_of_item invoked on %?", s));
} }
_ => sess.span_fatal(sp, err)
} }
} }
@ -894,7 +930,8 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
return tpt; return tpt;
} }
ast::item_fn(ref decl, purity, _, ref generics, _) => { ast::item_fn(ref decl, purity, _, ref generics, _) => {
let bounds = ty_param_bounds(ccx, generics); assert!(rp.is_none());
let ty_generics = ty_generics(ccx, None, generics);
let tofd = astconv::ty_of_bare_fn(ccx, let tofd = astconv::ty_of_bare_fn(ccx,
&empty_rscope, &empty_rscope,
purity, purity,
@ -902,8 +939,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
&generics.lifetimes, &generics.lifetimes,
decl); decl);
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, generics: ty::Generics {
region_param: None, bounds: ty_generics.bounds,
region_param: None
},
ty: ty::mk_bare_fn(ccx.tcx, tofd) ty: ty::mk_bare_fn(ccx.tcx, tofd)
}; };
debug!("type of %s (id %d) is %s", debug!("type of %s (id %d) is %s",
@ -934,8 +973,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
} }
}; };
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, generics), generics: ty_generics(ccx, rp, generics),
region_param: rp,
ty: ty ty: ty
} }
}; };
@ -945,36 +983,25 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
} }
ast::item_enum(_, ref generics) => { ast::item_enum(_, ref generics) => {
// Create a new generic polytype. // Create a new generic polytype.
let (bounds, substs) = mk_substs(ccx, generics, rp); let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_enum(tcx, local_def(it.id), substs); let t = ty::mk_enum(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, generics: ty_generics,
region_param: rp,
ty: t ty: t
}; };
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_trait(ref generics, _, _) => { ast::item_trait(*) => {
let (bounds, substs) = mk_substs(ccx, generics, rp); tcx.sess.span_bug(
let t = ty::mk_trait(tcx, it.span,
local_def(it.id), fmt!("Invoked ty_of_item on trait"));
substs,
ty::BareTraitStore);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: rp,
ty: t
};
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
} }
ast::item_struct(_, ref generics) => { ast::item_struct(_, ref generics) => {
let (bounds, substs) = mk_substs(ccx, generics, rp); let (ty_generics, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_struct(tcx, local_def(it.id), substs); let t = ty::mk_struct(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, generics: ty_generics,
region_param: rp,
ty: t ty: t
}; };
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
@ -997,76 +1024,82 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item)
} }
ast::foreign_item_const(t) => { ast::foreign_item_const(t) => {
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
generics: ty::Generics {
bounds: @~[], bounds: @~[],
region_param: None, region_param: None,
},
ty: ast_ty_to_ty(ccx, &empty_rscope, t) ty: ast_ty_to_ty(ccx, &empty_rscope, t)
} }
} }
} }
} }
// Translate the AST's notion of ty param bounds (which are an enum consisting pub fn ty_generics(ccx: &CrateCtxt,
// of a newtyped Ty or a region) to ty's notion of ty param bounds, which can rp: Option<ty::region_variance>,
// either be user-defined traits, or one of the four built-in traits (formerly generics: &ast::Generics) -> ty::Generics {
// known as kinds): Const, Copy, Durable, and Send. return ty::Generics {
pub fn compute_bounds(ccx: &CrateCtxt, region_param: rp,
ast_bounds: @OptVec<ast::TyParamBound>) bounds: @generics.ty_params.map_to_vec(|param| {
-> ty::param_bounds {
@ast_bounds.flat_map_to_vec(|b| {
match b {
&TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items;
let ity = ast_ty_to_ty(ccx, &empty_rscope, b);
match ty::get(ity).sty {
ty::ty_trait(did, _, _) => {
if did == li.owned_trait() {
~[ty::bound_owned]
} else if did == li.copy_trait() {
~[ty::bound_copy]
} else if did == li.const_trait() {
~[ty::bound_const]
} else if did == li.durable_trait() {
~[ty::bound_durable]
} else {
// Must be a user-defined trait
~[ty::bound_trait(ity)]
}
}
_ => {
ccx.tcx.sess.span_err(
(*b).span, ~"type parameter bounds must be \
trait types");
~[]
}
}
}
&RegionTyParamBound => ~[ty::bound_durable]
}
})
}
pub fn ty_param_bounds(ccx: &CrateCtxt,
generics: &ast::Generics)
-> @~[ty::param_bounds] {
@do generics.ty_params.map_to_vec |param| {
match ccx.tcx.ty_param_bounds.find(&param.id) { match ccx.tcx.ty_param_bounds.find(&param.id) {
Some(&bs) => bs, Some(&bs) => bs,
None => { None => {
let bounds = compute_bounds(ccx, param.bounds); let bounds = compute_bounds(ccx, rp, generics, param.bounds);
ccx.tcx.ty_param_bounds.insert(param.id, bounds); ccx.tcx.ty_param_bounds.insert(param.id, bounds);
bounds bounds
} }
} }
})
};
fn compute_bounds(
ccx: &CrateCtxt,
rp: Option<ty::region_variance>,
generics: &ast::Generics,
ast_bounds: @OptVec<ast::TyParamBound>) -> ty::param_bounds
{
/*!
*
* Translate the AST's notion of ty param bounds (which are an
* enum consisting of a newtyped Ty or a region) to ty's
* notion of ty param bounds, which can either be user-defined
* traits, or one of the four built-in traits (formerly known
* as kinds): Const, Copy, Durable, and Send.
*/
@ast_bounds.flat_map_to_vec(|b| {
match b {
&TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items;
let trait_ref = instantiate_trait_ref(ccx, b, rp, generics);
if trait_ref.def_id == li.owned_trait() {
~[ty::bound_owned]
} else if trait_ref.def_id == li.copy_trait() {
~[ty::bound_copy]
} else if trait_ref.def_id == li.const_trait() {
~[ty::bound_const]
} else if trait_ref.def_id == li.durable_trait() {
~[ty::bound_durable]
} else {
// Must be a user-defined trait
~[ty::bound_trait(trait_ref)]
}
}
&RegionTyParamBound => {
~[ty::bound_durable]
}
}
})
} }
} }
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
decl: &ast::fn_decl, decl: &ast::fn_decl,
def_id: ast::def_id, def_id: ast::def_id,
generics: &ast::Generics) ast_generics: &ast::Generics)
-> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(ccx, generics); let ty_generics = ty_generics(ccx, None, ast_generics);
let region_param_names = RegionParamNames::from_generics(generics); let region_param_names = RegionParamNames::from_generics(ast_generics);
let rb = in_binding_rscope(&empty_rscope, region_param_names); let rb = in_binding_rscope(&empty_rscope, region_param_names);
let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) ); let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, *a, None) );
let output_ty = ast_ty_to_ty(ccx, &rb, decl.output); let output_ty = ast_ty_to_ty(ccx, &rb, decl.output);
@ -1081,33 +1114,24 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
output: output_ty} output: output_ty}
}); });
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, generics: ty_generics,
region_param: None,
ty: t_fn ty: t_fn
}; };
ccx.tcx.tcache.insert(def_id, tpt); ccx.tcx.tcache.insert(def_id, tpt);
return tpt; return tpt;
} }
pub fn mk_generics(ccx: &CrateCtxt, generics: &ast::Generics) pub fn mk_substs(ccx: &CrateCtxt,
-> (@~[ty::param_bounds], ~[ty::t]) ast_generics: &ast::Generics,
rp: Option<ty::region_variance>) -> (ty::Generics, ty::substs)
{ {
let mut i = 0u; let mut i = 0;
let bounds = ty_param_bounds(ccx, generics); let ty_generics = ty_generics(ccx, rp, ast_generics);
(bounds, let params = ast_generics.ty_params.map_to_vec(|atp| {
generics.ty_params.map_to_vec(|atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
i += 1u; i += 1u;
t t
})) });
}
pub fn mk_substs(ccx: &CrateCtxt,
generics: &ast::Generics,
rp: Option<ty::region_variance>)
-> (@~[ty::param_bounds], ty::substs)
{
let (bounds, params) = mk_generics(ccx, generics);
let self_r = rscope::bound_self_region(rp); let self_r = rscope::bound_self_region(rp);
(bounds, substs { self_r: self_r, self_ty: None, tps: params }) (ty_generics, substs {self_r: self_r, self_ty: None, tps: params})
} }

View file

@ -90,7 +90,7 @@ pub trait Combine {
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]>; fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]>;
fn self_tys(&self, a: Option<ty::t>, b: Option<ty::t>) fn self_tys(&self, a: Option<ty::t>, b: Option<ty::t>)
-> cres<Option<ty::t>>; -> cres<Option<ty::t>>;
fn substs(&self, did: ast::def_id, as_: &ty::substs, fn substs(&self, generics: &ty::Generics, as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs>; bs: &ty::substs) -> cres<ty::substs>;
fn bare_fn_tys(&self, a: &ty::BareFnTy, fn bare_fn_tys(&self, a: &ty::BareFnTy,
b: &ty::BareFnTy) -> cres<ty::BareFnTy>; b: &ty::BareFnTy) -> cres<ty::BareFnTy>;
@ -114,6 +114,7 @@ pub trait Combine {
a: ty::TraitStore, a: ty::TraitStore,
b: ty::TraitStore) b: ty::TraitStore)
-> cres<ty::TraitStore>; -> cres<ty::TraitStore>;
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>;
} }
pub struct CombineFields { pub struct CombineFields {
@ -192,32 +193,31 @@ pub fn eq_opt_regions<C:Combine>(
} }
pub fn super_substs<C:Combine>( pub fn super_substs<C:Combine>(
self: &C, did: ast::def_id, self: &C, generics: &ty::Generics,
a: &ty::substs, b: &ty::substs) -> cres<ty::substs> { a: &ty::substs, b: &ty::substs) -> cres<ty::substs> {
fn relate_region_param<C:Combine>( fn relate_region_param<C:Combine>(
self: &C, self: &C,
did: ast::def_id, generics: &ty::Generics,
a: Option<ty::Region>, a: Option<ty::Region>,
b: Option<ty::Region>) b: Option<ty::Region>)
-> cres<Option<ty::Region>> -> cres<Option<ty::Region>>
{ {
let polyty = ty::lookup_item_type(self.infcx().tcx, did); match (&generics.region_param, &a, &b) {
match (polyty.region_param, a, b) { (&None, &None, &None) => {
(None, None, None) => {
Ok(None) Ok(None)
} }
(Some(ty::rv_invariant), Some(a), Some(b)) => { (&Some(ty::rv_invariant), &Some(a), &Some(b)) => {
do eq_regions(self, a, b).then { do eq_regions(self, a, b).then {
Ok(Some(a)) Ok(Some(a))
} }
} }
(Some(ty::rv_covariant), Some(a), Some(b)) => { (&Some(ty::rv_covariant), &Some(a), &Some(b)) => {
do self.regions(a, b).chain |r| { do self.regions(a, b).chain |r| {
Ok(Some(r)) Ok(Some(r))
} }
} }
(Some(ty::rv_contravariant), Some(a), Some(b)) => { (&Some(ty::rv_contravariant), &Some(a), &Some(b)) => {
do self.contraregions(a, b).chain |r| { do self.contraregions(a, b).chain |r| {
Ok(Some(r)) Ok(Some(r))
} }
@ -233,14 +233,14 @@ pub fn super_substs<C:Combine>(
b had opt_region %s with variance %?", b had opt_region %s with variance %?",
a.inf_str(self.infcx()), a.inf_str(self.infcx()),
b.inf_str(self.infcx()), b.inf_str(self.infcx()),
polyty.region_param)); generics.region_param));
} }
} }
} }
do self.tps(a.tps, b.tps).chain |tps| { do self.tps(a.tps, b.tps).chain |tps| {
do self.self_tys(a.self_ty, b.self_ty).chain |self_ty| { do self.self_tys(a.self_ty, b.self_ty).chain |self_ty| {
do relate_region_param(self, did, do relate_region_param(self, generics,
a.self_r, b.self_r).chain |self_r| a.self_r, b.self_r).chain |self_r|
{ {
Ok(substs { Ok(substs {
@ -520,7 +520,8 @@ pub fn super_tys<C:Combine>(
(ty::ty_enum(a_id, ref a_substs), (ty::ty_enum(a_id, ref a_substs),
ty::ty_enum(b_id, ref b_substs)) ty::ty_enum(b_id, ref b_substs))
if a_id == b_id => { if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| { let type_def = ty::lookup_item_type(tcx, a_id);
do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
Ok(ty::mk_enum(tcx, a_id, substs)) Ok(ty::mk_enum(tcx, a_id, substs))
} }
} }
@ -528,7 +529,8 @@ pub fn super_tys<C:Combine>(
(ty::ty_trait(a_id, ref a_substs, a_store), (ty::ty_trait(a_id, ref a_substs, a_store),
ty::ty_trait(b_id, ref b_substs, b_store)) ty::ty_trait(b_id, ref b_substs, b_store))
if a_id == b_id => { if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| { let trait_def = ty::lookup_trait_def(tcx, a_id);
do self.substs(&trait_def.generics, a_substs, b_substs).chain |substs| {
do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| { do self.trait_stores(ty::terr_trait, a_store, b_store).chain |s| {
Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s)) Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, s))
} }
@ -537,7 +539,8 @@ pub fn super_tys<C:Combine>(
(ty::ty_struct(a_id, ref a_substs), ty::ty_struct(b_id, ref b_substs)) (ty::ty_struct(a_id, ref a_substs), ty::ty_struct(b_id, ref b_substs))
if a_id == b_id => { if a_id == b_id => {
do self.substs(a_id, a_substs, b_substs).chain |substs| { let type_def = ty::lookup_item_type(tcx, a_id);
do self.substs(&type_def.generics, a_substs, b_substs).chain |substs| {
Ok(ty::mk_struct(tcx, a_id, substs)) Ok(ty::mk_struct(tcx, a_id, substs))
} }
} }
@ -634,3 +637,25 @@ pub fn super_tys<C:Combine>(
Ok(ty::mk_mach_float(tcx, val)) Ok(ty::mk_mach_float(tcx, val))
} }
} }
pub fn super_trait_refs<C:Combine>(
self: &C, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef>
{
// Different traits cannot be related
// - NOTE in the future, expand out subtraits!
if a.def_id != b.def_id {
Err(ty::terr_traits(
expected_found(self, a.def_id, b.def_id)))
} else {
let tcx = self.infcx().tcx;
let trait_def = ty::lookup_trait_def(tcx, a.def_id);
let substs = if_ok!(self.substs(&trait_def.generics, &a.substs, &b.substs));
Ok(ty::TraitRef {
def_id: a.def_id,
substs: substs
})
}
}

View file

@ -299,10 +299,11 @@ impl Combine for Glb {
super_closure_tys(self, a, b) super_closure_tys(self, a, b)
} }
fn substs(&self, did: ast::def_id, fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs, as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> { bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs) super_substs(self, generics, as_, bs)
} }
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -313,5 +314,9 @@ impl Combine for Glb {
-> cres<Option<ty::t>> { -> cres<Option<ty::t>> {
super_self_tys(self, a, b) super_self_tys(self, a, b)
} }
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
} }

View file

@ -244,10 +244,11 @@ impl Combine for Lub {
super_args(self, a, b) super_args(self, a, b)
} }
fn substs(&self, did: ast::def_id, fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs, as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> { bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs) super_substs(self, generics, as_, bs)
} }
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -258,4 +259,8 @@ impl Combine for Lub {
-> cres<Option<ty::t>> { -> cres<Option<ty::t>> {
super_self_tys(self, a, b) super_self_tys(self, a, b)
} }
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
} }

View file

@ -265,7 +265,7 @@ use middle::typeck::infer::to_str::InferStr;
use middle::typeck::infer::unify::{ValsAndBindings, Root}; use middle::typeck::infer::unify::{ValsAndBindings, Root};
use middle::typeck::isr_alist; use middle::typeck::isr_alist;
use util::common::indent; use util::common::indent;
use util::ppaux::{bound_region_to_str, ty_to_str}; use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str};
use core::cmp::Eq; use core::cmp::Eq;
use core::result::{Result, Ok, Err}; use core::result::{Result, Ok, Err};
@ -419,6 +419,23 @@ pub fn mk_eqty(cx: @mut InferCtxt,
}.to_ures() }.to_ures()
} }
pub fn mk_sub_trait_refs(cx: @mut InferCtxt,
a_is_expected: bool,
span: span,
a: &ty::TraitRef,
b: &ty::TraitRef)
-> ures
{
debug!("mk_sub_trait_refs(%s <: %s)",
a.inf_str(cx), b.inf_str(cx));
do indent {
do cx.commit {
let suber = cx.sub(a_is_expected, span);
suber.trait_refs(a, b)
}
}.to_ures()
}
pub fn mk_coercety(cx: @mut InferCtxt, pub fn mk_coercety(cx: @mut InferCtxt,
a_is_expected: bool, a_is_expected: bool,
span: span, span: span,
@ -700,6 +717,11 @@ pub impl InferCtxt {
self.resolve_type_vars_if_possible(t)) self.resolve_type_vars_if_possible(t))
} }
fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str {
let t = self.resolve_type_vars_in_trait_ref_if_possible(t);
trait_ref_to_str(self.tcx, &t)
}
fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t { fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t {
match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) { match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) {
result::Ok(new_type) => new_type, result::Ok(new_type) => new_type,
@ -707,6 +729,31 @@ pub impl InferCtxt {
} }
} }
fn resolve_type_vars_in_trait_ref_if_possible(@mut self,
trait_ref: &ty::TraitRef)
-> ty::TraitRef
{
// make up a dummy type just to reuse/abuse the resolve machinery
let dummy0 = ty::mk_trait(self.tcx,
trait_ref.def_id,
copy trait_ref.substs,
ty::UniqTraitStore);
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
match ty::get(dummy1).sty {
ty::ty_trait(ref def_id, ref substs, _) => {
ty::TraitRef {def_id: *def_id,
substs: copy *substs}
}
_ => {
self.tcx.sess.bug(
fmt!("resolve_type_vars_if_possible() yielded %s \
when supplied with %s",
self.ty_to_str(dummy0),
self.ty_to_str(dummy1)));
}
}
}
fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str, fn type_error_message(@mut self, sp: span, mk_msg: &fn(~str) -> ~str,
actual_ty: ty::t, err: Option<&ty::type_err>) { actual_ty: ty::t, err: Option<&ty::type_err>) {
let actual_ty = self.resolve_type_vars_if_possible(actual_ty); let actual_ty = self.resolve_type_vars_if_possible(actual_ty);

View file

@ -256,10 +256,11 @@ impl Combine for Sub {
super_args(self, a, b) super_args(self, a, b)
} }
fn substs(&self, did: ast::def_id, fn substs(&self,
generics: &ty::Generics,
as_: &ty::substs, as_: &ty::substs,
bs: &ty::substs) -> cres<ty::substs> { bs: &ty::substs) -> cres<ty::substs> {
super_substs(self, did, as_, bs) super_substs(self, generics, as_, bs)
} }
fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { fn tps(&self, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> {
@ -270,5 +271,9 @@ impl Combine for Sub {
-> cres<Option<ty::t>> { -> cres<Option<ty::t>> {
super_self_tys(self, a, b) super_self_tys(self, a, b)
} }
fn trait_refs(&self, a: &ty::TraitRef, b: &ty::TraitRef) -> cres<ty::TraitRef> {
super_trait_refs(self, a, b)
}
} }

View file

@ -16,7 +16,7 @@ use middle::ty;
use middle::typeck::infer::{Bound, Bounds}; use middle::typeck::infer::{Bound, Bounds};
use middle::typeck::infer::InferCtxt; use middle::typeck::infer::InferCtxt;
use middle::typeck::infer::unify::{Redirect, Root, VarValue}; use middle::typeck::infer::unify::{Redirect, Root, VarValue};
use util::ppaux::{mt_to_str, ty_to_str}; use util::ppaux::{mt_to_str, ty_to_str, trait_ref_to_str};
use syntax::ast; use syntax::ast;
@ -91,3 +91,9 @@ impl InferStr for ast::float_ty {
self.to_str() self.to_str()
} }
} }
impl InferStr for ty::TraitRef {
fn inf_str(&self, cx: &InferCtxt) -> ~str {
trait_ref_to_str(cx.tcx, self)
}
}

View file

@ -222,8 +222,8 @@ pub fn lookup_def_ccx(ccx: @mut CrateCtxt, sp: span, id: ast::node_id)
pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
ty::ty_param_bounds_and_ty { ty::ty_param_bounds_and_ty {
bounds: @~[], generics: ty::Generics {bounds: @~[],
region_param: None, region_param: None},
ty: t ty: t
} }
} }

View file

@ -239,7 +239,6 @@ pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str { pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
match s { match s {
ty::BareTraitStore => ~"",
ty::UniqTraitStore => ~"~", ty::UniqTraitStore => ~"~",
ty::BoxTraitStore => ~"@", ty::BoxTraitStore => ~"@",
ty::RegionTraitStore(r) => region_to_str_space(cx, "&", r) ty::RegionTraitStore(r) => region_to_str_space(cx, "&", r)
@ -285,6 +284,12 @@ pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
ty_to_str(cx, typ.output)) ty_to_str(cx, typ.output))
} }
pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
let path = ty::item_path(cx, trait_ref.def_id);
let base = ast_map::path_to_str(path, cx.sess.intr());
parameterized(cx, base, trait_ref.substs.self_r, trait_ref.substs.tps)
}
pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str { fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str {
let ty::arg {mode: mode, ty: ty} = input; let ty::arg {mode: mode, ty: ty} = input;

View file

@ -144,7 +144,7 @@ pub static crate_node_id: node_id = 0;
// the "special" built-in traits (see middle::lang_items) and // the "special" built-in traits (see middle::lang_items) and
// detects Copy, Send, Owned, and Const. // detects Copy, Send, Owned, and Const.
pub enum TyParamBound { pub enum TyParamBound {
TraitTyParamBound(@Ty), TraitTyParamBound(@trait_ref),
RegionTyParamBound RegionTyParamBound
} }

View file

@ -227,10 +227,9 @@ priv impl @ext_ctxt {
path: @ast::path, path: @ast::path,
bounds: @OptVec<ast::TyParamBound> bounds: @OptVec<ast::TyParamBound>
) -> ast::TyParam { ) -> ast::TyParam {
let bound = ast::TraitTyParamBound(@ast::Ty { let bound = ast::TraitTyParamBound(@ast::trait_ref {
id: self.next_id(), ref_id: self.next_id(),
node: ast::ty_path(path, self.next_id()), path: path
span: span,
}); });
ast::TyParam { ast::TyParam {
@ -466,10 +465,9 @@ fn mk_impl(
// All the type parameters need to bound to the trait. // All the type parameters need to bound to the trait.
let mut impl_tps = opt_vec::with(ty_param); let mut impl_tps = opt_vec::with(ty_param);
for generics.ty_params.each |tp| { for generics.ty_params.each |tp| {
let t_bound = ast::TraitTyParamBound(@ast::Ty { let t_bound = ast::TraitTyParamBound(@ast::trait_ref {
id: cx.next_id(), path: path,
node: ast::ty_path(path, cx.next_id()), ref_id: cx.next_id(),
span: span,
}); });
impl_tps.push(ast::TyParam { impl_tps.push(ast::TyParam {

View file

@ -337,6 +337,17 @@ pub fn mk_ty_path_global(cx: @ext_ctxt,
let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span }; let ty = @ast::Ty { id: cx.next_id(), node: ty, span: span };
ty ty
} }
pub fn mk_trait_ref_global(cx: @ext_ctxt,
span: span,
+idents: ~[ ast::ident ])
-> @ast::trait_ref
{
let path = build::mk_raw_path_global(span, idents);
@ast::trait_ref {
path: path,
ref_id: cx.next_id()
}
}
pub fn mk_simple_ty_path(cx: @ext_ctxt, pub fn mk_simple_ty_path(cx: @ext_ctxt,
span: span, span: span,
ident: ast::ident) ident: ast::ident)

View file

@ -177,7 +177,7 @@ pub fn create_derived_impl(cx: @ext_ctxt,
// Create the type parameters. // Create the type parameters.
let impl_ty_params = generics.ty_params.map(|ty_param| { let impl_ty_params = generics.ty_params.map(|ty_param| {
let bound = build::mk_ty_path_global(cx, let bound = build::mk_trait_ref_global(cx,
span, span,
trait_path.map(|x| *x)); trait_path.map(|x| *x));
let bounds = @opt_vec::with(TraitTyParamBound(bound)); let bounds = @opt_vec::with(TraitTyParamBound(bound));

View file

@ -134,7 +134,7 @@ pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl {
fn fold_ty_param_bound(tpb: &TyParamBound, fld: @ast_fold) -> TyParamBound { fn fold_ty_param_bound(tpb: &TyParamBound, fld: @ast_fold) -> TyParamBound {
match *tpb { match *tpb {
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)), TraitTyParamBound(ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
RegionTyParamBound => RegionTyParamBound RegionTyParamBound => RegionTyParamBound
} }
} }

View file

@ -2750,8 +2750,8 @@ pub impl Parser {
self.bump(); self.bump();
} }
token::MOD_SEP | token::IDENT(*) => { token::MOD_SEP | token::IDENT(*) => {
let maybe_bound = match *self.token { let obsolete_bound = match *self.token {
token::MOD_SEP => None, token::MOD_SEP => false,
token::IDENT(copy sid, _) => { token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) { match *self.id_to_str(sid) {
~"send" | ~"send" |
@ -2761,27 +2761,18 @@ pub impl Parser {
self.obsolete( self.obsolete(
*self.span, *self.span,
ObsoleteLowerCaseKindBounds); ObsoleteLowerCaseKindBounds);
self.bump();
// Bogus value, but doesn't matter, since true
// is an error
Some(TraitTyParamBound(
self.mk_ty_path(sid)))
} }
_ => None _ => false
} }
} }
_ => fail!() _ => fail!()
}; };
match maybe_bound { if !obsolete_bound {
Some(bound) => { let tref = self.parse_trait_ref();
self.bump(); result.push(TraitTyParamBound(tref));
result.push(bound);
}
None => {
let ty = self.parse_ty(true);
result.push(TraitTyParamBound(ty));
}
} }
} }
_ => break, _ => break,

View file

@ -562,7 +562,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
match opt_trait { match opt_trait {
Some(t) => { Some(t) => {
print_path(s, t.path, false); print_trait_ref(s, t);
space(s.s); space(s.s);
word_space(s, ~"for"); word_space(s, ~"for");
} }
@ -619,6 +619,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
(s.ann.post)(ann_node); (s.ann.post)(ann_node);
} }
fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
print_path(s, t.path, false);
}
pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def, pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
generics: &ast::Generics, ident: ast::ident, generics: &ast::Generics, ident: ast::ident,
span: codemap::span, visibility: ast::visibility) { span: codemap::span, visibility: ast::visibility) {
@ -1744,7 +1748,7 @@ pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
} }
match *bound { match *bound {
TraitTyParamBound(ty) => print_type(s, ty), TraitTyParamBound(tref) => print_trait_ref(s, tref),
RegionTyParamBound => word(s.s, ~"'static"), RegionTyParamBound => word(s.s, ~"'static"),
} }
} }

View file

@ -147,6 +147,10 @@ pub fn visit_local<E>(loc: @local, e: E, v: vt<E>) {
} }
} }
fn visit_trait_ref<E>(tref: @ast::trait_ref, e: E, v: vt<E>) {
visit_path(tref.path, e, v);
}
pub fn visit_item<E>(i: @item, e: E, v: vt<E>) { pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
match i.node { match i.node {
item_const(t, ex) => { item_const(t, ex) => {
@ -189,8 +193,8 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
} }
item_impl(ref tps, ref traits, ty, ref methods) => { item_impl(ref tps, ref traits, ty, ref methods) => {
(v.visit_generics)(tps, e, v); (v.visit_generics)(tps, e, v);
for traits.each |p| { for traits.each |&p| {
visit_path(p.path, e, v); visit_trait_ref(p, e, v);
} }
(v.visit_ty)(ty, e, v); (v.visit_ty)(ty, e, v);
for methods.each |m| { for methods.each |m| {
@ -327,8 +331,8 @@ pub fn visit_ty_param_bounds<E>(bounds: @OptVec<TyParamBound>,
e: E, v: vt<E>) { e: E, v: vt<E>) {
for bounds.each |bound| { for bounds.each |bound| {
match *bound { match *bound {
TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v), TraitTyParamBound(ty) => visit_trait_ref(ty, e, v),
RegionTyParamBound => () RegionTyParamBound => {}
} }
} }
} }

View file

@ -15,7 +15,7 @@ trait channel<T> {
} }
// `chan` is not a trait, it's an enum // `chan` is not a trait, it's an enum
impl chan for int { //~ ERROR can only implement trait types impl chan for int { //~ ERROR chan is not a trait
fn send(&self, v: int) { fail!() } fn send(&self, v: int) { fail!() }
} }

View file

@ -12,7 +12,7 @@ trait add {
fn plus(&self, x: Self) -> Self; fn plus(&self, x: Self) -> Self;
} }
fn do_add(x: add, y: add) -> add { fn do_add(x: @add, y: @add) -> @add {
x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait
} }

View file

@ -13,7 +13,7 @@ pub fn main() {
fn to_str(&self) -> ~str; fn to_str(&self) -> ~str;
} }
fn to_string(t: Text) { fn to_string(t: @Text) {
io::println(t.to_str()); io::println(t.to_str());
} }

View file

@ -417,9 +417,9 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
} }
fn visit_trait(&self) -> bool { fn visit_trait(&self) -> bool {
self.align_to::<TyVisitor>(); self.align_to::<@TyVisitor>();
if ! self.inner.visit_trait() { return false; } if ! self.inner.visit_trait() { return false; }
self.bump_past::<TyVisitor>(); self.bump_past::<@TyVisitor>();
true true
} }