Merge remote-tracking branch 'remotes/origin/incoming' into incoming

This commit is contained in:
Erick Tryzelaar 2013-02-28 07:25:31 -08:00
commit 3953bdd812
42 changed files with 1304 additions and 810 deletions

View file

@ -74,10 +74,53 @@ impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
} }
} }
impl<A:ToStr> ToStr for &[A] {
#[inline(always)]
pure fn to_str(&self) -> ~str {
unsafe {
// FIXME #4568
// Bleh -- not really unsafe
// push_str and push_char
let mut acc = ~"[", first = true;
for self.each |elt| {
unsafe {
if first { first = false; }
else { str::push_str(&mut acc, ~", "); }
str::push_str(&mut acc, elt.to_str());
}
}
str::push_char(&mut acc, ']');
acc
}
}
}
impl<A:ToStr> ToStr for ~[A] { impl<A:ToStr> ToStr for ~[A] {
#[inline(always)] #[inline(always)]
pure fn to_str(&self) -> ~str { pure fn to_str(&self) -> ~str {
unsafe { unsafe {
// FIXME #4568
// Bleh -- not really unsafe
// push_str and push_char
let mut acc = ~"[", first = true;
for self.each |elt| {
unsafe {
if first { first = false; }
else { str::push_str(&mut acc, ~", "); }
str::push_str(&mut acc, elt.to_str());
}
}
str::push_char(&mut acc, ']');
acc
}
}
}
impl<A:ToStr> ToStr for @[A] {
#[inline(always)]
pure fn to_str(&self) -> ~str {
unsafe {
// FIXME #4568
// Bleh -- not really unsafe // Bleh -- not really unsafe
// push_str and push_char // push_str and push_char
let mut acc = ~"[", first = true; let mut acc = ~"[", first = true;

View file

@ -202,14 +202,14 @@ fn is_bench_fn(i: @ast::item) -> bool {
vec::len(attr::find_attrs_by_name(i.attrs, ~"bench")) > 0u; vec::len(attr::find_attrs_by_name(i.attrs, ~"bench")) > 0u;
fn has_test_signature(i: @ast::item) -> bool { fn has_test_signature(i: @ast::item) -> bool {
match /*bad*/copy i.node { match i.node {
ast::item_fn(decl, _, tps, _) => { ast::item_fn(ref decl, _, ref generics, _) => {
let input_cnt = vec::len(decl.inputs); let input_cnt = vec::len(decl.inputs);
let no_output = match decl.output.node { let no_output = match decl.output.node {
ast::ty_nil => true, ast::ty_nil => true,
_ => false _ => false
}; };
let tparm_cnt = vec::len(tps); let tparm_cnt = generics.ty_params.len();
// NB: inadequate check, but we're running // NB: inadequate check, but we're running
// well before resolve, can't get too deep. // well before resolve, can't get too deep.
input_cnt == 1u input_cnt == 1u

View file

@ -49,6 +49,8 @@ use syntax::diagnostic::span_handler;
use syntax::parse::token::special_idents; use syntax::parse::token::special_idents;
use syntax::print::pprust; use syntax::print::pprust;
use syntax::{ast_util, visit}; use syntax::{ast_util, visit};
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax; use syntax;
use writer = std::ebml::writer; use writer = std::ebml::writer;
@ -187,10 +189,11 @@ fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext,
} }
} }
fn encode_type_param_bounds(ebml_w: writer::Encoder, ecx: @EncodeContext, fn encode_type_param_bounds(ebml_w: writer::Encoder,
params: &[ty_param]) { ecx: @EncodeContext,
params: &OptVec<TyParam>) {
let ty_param_bounds = let ty_param_bounds =
@params.map(|param| ecx.tcx.ty_param_bounds.get(&param.id)); @params.map_to_vec(|param| ecx.tcx.ty_param_bounds.get(&param.id));
encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds); encode_ty_type_param_bounds(ebml_w, ecx, ty_param_bounds);
} }
@ -265,7 +268,7 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder,
id: node_id, variants: &[variant], id: node_id, variants: &[variant],
path: &[ast_map::path_elt], path: &[ast_map::path_elt],
index: @mut ~[entry<int>], index: @mut ~[entry<int>],
ty_params: &[ty_param]) { generics: &ast::Generics) {
let mut disr_val = 0; let mut disr_val = 0;
let mut i = 0; let mut i = 0;
let vi = ty::enum_variants(ecx.tcx, let vi = ty::enum_variants(ecx.tcx,
@ -281,7 +284,7 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder,
node_id_to_type(ecx.tcx, variant.node.id)); node_id_to_type(ecx.tcx, variant.node.id));
match variant.node.kind { match variant.node.kind {
ast::tuple_variant_kind(ref args) ast::tuple_variant_kind(ref args)
if args.len() > 0 && ty_params.len() == 0 => { if args.len() > 0 && generics.ty_params.len() == 0 => {
encode_symbol(ecx, ebml_w, variant.node.id); encode_symbol(ecx, ebml_w, variant.node.id);
} }
ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) | ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) |
@ -292,7 +295,7 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder,
encode_disr_val(ecx, ebml_w, vi[i].disr_val); encode_disr_val(ecx, ebml_w, vi[i].disr_val);
disr_val = vi[i].disr_val; disr_val = vi[i].disr_val;
} }
encode_type_param_bounds(ebml_w, ecx, ty_params); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_path(ecx, ebml_w, path, encode_path(ecx, ebml_w, path,
ast_map::path_name(variant.node.name)); ast_map::path_name(variant.node.name));
ebml_w.end_tag(); ebml_w.end_tag();
@ -465,14 +468,18 @@ fn encode_info_for_struct(ecx: @EncodeContext, ebml_w: writer::Encoder,
} }
// This is for encoding info for ctors and dtors // This is for encoding info for ctors and dtors
fn encode_info_for_ctor(ecx: @EncodeContext, ebml_w: writer::Encoder, fn encode_info_for_ctor(ecx: @EncodeContext,
id: node_id, ident: ident, path: &[ast_map::path_elt], ebml_w: writer::Encoder,
item: Option<inlined_item>, tps: &[ty_param]) { id: node_id,
ident: ident,
path: &[ast_map::path_elt],
item: Option<inlined_item>,
generics: &ast::Generics) {
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_name(ecx, ebml_w, ident); encode_name(ecx, ebml_w, ident);
encode_def_id(ebml_w, local_def(id)); encode_def_id(ebml_w, local_def(id));
encode_family(ebml_w, purity_fn_family(ast::impure_fn)); encode_family(ebml_w, purity_fn_family(ast::impure_fn));
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
let its_ty = node_id_to_type(ecx.tcx, id); let its_ty = node_id_to_type(ecx.tcx, id);
debug!("fn name = %s ty = %s its node id = %d", debug!("fn name = %s ty = %s its node id = %d",
*ecx.tcx.sess.str_of(ident), *ecx.tcx.sess.str_of(ident),
@ -518,9 +525,12 @@ fn encode_info_for_method(ecx: @EncodeContext,
should_inline: bool, should_inline: bool,
parent_id: node_id, parent_id: node_id,
m: @method, m: @method,
+all_tps: ~[ty_param]) { owner_generics: &ast::Generics,
debug!("encode_info_for_method: %d %s %u", m.id, method_generics: &ast::Generics) {
*ecx.tcx.sess.str_of(m.ident), all_tps.len()); debug!("encode_info_for_method: %d %s %u %u", m.id,
*ecx.tcx.sess.str_of(m.ident),
owner_generics.ty_params.len(),
method_generics.ty_params.len());
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(m.id)); encode_def_id(ebml_w, local_def(m.id));
match m.self_ty.node { match m.self_ty.node {
@ -529,8 +539,13 @@ fn encode_info_for_method(ecx: @EncodeContext,
} }
_ => encode_family(ebml_w, purity_fn_family(m.purity)) _ => encode_family(ebml_w, purity_fn_family(m.purity))
} }
let len = all_tps.len();
encode_type_param_bounds(ebml_w, ecx, all_tps); let mut combined_ty_params = opt_vec::Empty;
combined_ty_params.push_all(&owner_generics.ty_params);
combined_ty_params.push_all(&method_generics.ty_params);
let len = combined_ty_params.len();
encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id)); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
encode_name(ecx, ebml_w, m.ident); encode_name(ecx, ebml_w, m.ident);
encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident)); encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
@ -604,13 +619,13 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
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();
} }
item_fn(_, purity, tps, _) => { item_fn(_, purity, ref generics, _) => {
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, purity_fn_family(purity)); encode_family(ebml_w, purity_fn_family(purity));
let tps_len = tps.len(); let tps_len = generics.ty_params.len();
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
encode_attributes(ebml_w, item.attrs); encode_attributes(ebml_w, item.attrs);
@ -634,24 +649,24 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
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();
} }
item_ty(_, tps) => { item_ty(_, ref generics) => {
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, 'y'); encode_family(ebml_w, 'y');
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident); encode_name(ecx, ebml_w, item.ident);
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ecx, ebml_w, item); encode_region_param(ecx, ebml_w, item);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_enum(ref enum_definition, ref tps) => { item_enum(ref enum_definition, ref generics) => {
add_to_index(); add_to_index();
do ebml_w.wr_tag(tag_items_data_item) { do ebml_w.wr_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, 't'); encode_family(ebml_w, 't');
encode_type_param_bounds(ebml_w, ecx, *tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident); encode_name(ecx, ebml_w, item.ident);
for (*enum_definition).variants.each |v| { for (*enum_definition).variants.each |v| {
@ -667,9 +682,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
(*enum_definition).variants, (*enum_definition).variants,
path, path,
index, index,
*tps); generics);
} }
item_struct(struct_def, tps) => { item_struct(struct_def, ref generics) => {
/* First, encode the fields /* First, encode the fields
These come first because we need to write them to make These come first because we need to write them to make
the index, and the index needs to be in the item for the the index, and the index needs to be in the item for the
@ -686,24 +701,25 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
*ecx.tcx.sess.str_of(item.ident) + *ecx.tcx.sess.str_of(item.ident) +
~"_dtor"), ~"_dtor"),
path, path,
if tps.len() > 0u { if generics.ty_params.len() > 0u {
Some(ii_dtor(copy *dtor, Some(ii_dtor(copy *dtor,
item.ident, item.ident,
copy tps, copy *generics,
local_def(item.id))) } local_def(item.id))) }
else { else {
None None
}, },
tps); generics);
} }
/* Index the class*/ /* Index the class*/
add_to_index(); add_to_index();
/* Now, make an item for the class itself */ /* Now, make an item for the class itself */
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, 'S'); encode_family(ebml_w, 'S');
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
// If this is a tuple- or enum-like struct, encode the type of the // If this is a tuple- or enum-like struct, encode the type of the
@ -759,13 +775,13 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
encode_index(ebml_w, bkts, write_int); encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag(); ebml_w.end_tag();
} }
item_impl(tps, opt_trait, ty, methods) => { item_impl(ref generics, opt_trait, ty, ref methods) => {
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, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
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);
@ -797,10 +813,10 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
encode_info_for_method(ecx, ebml_w, impl_path, encode_info_for_method(ecx, ebml_w, impl_path,
should_inline(m.attrs), should_inline(m.attrs),
item.id, *m, item.id, *m,
vec::append(/*bad*/copy tps, m.tps)); generics, &m.generics);
} }
} }
item_trait(ref tps, ref traits, ref ms) => { item_trait(ref generics, ref traits, ref ms) => {
let provided_methods = dvec::DVec(); let provided_methods = dvec::DVec();
add_to_index(); add_to_index();
@ -808,7 +824,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
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, *tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
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);
@ -820,7 +836,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
encode_def_id(ebml_w, local_def((*ty_m).id)); encode_def_id(ebml_w, local_def((*ty_m).id));
encode_name(ecx, ebml_w, mty.ident); encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx, encode_type_param_bounds(ebml_w, ecx,
(*ty_m).tps); &ty_m.generics.ty_params);
encode_type(ecx, ebml_w, encode_type(ecx, ebml_w,
ty::mk_bare_fn(tcx, copy mty.fty)); ty::mk_bare_fn(tcx, copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.purity)); encode_family(ebml_w, purity_fn_family(mty.fty.purity));
@ -834,7 +850,8 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
ebml_w.start_tag(tag_item_trait_method); ebml_w.start_tag(tag_item_trait_method);
encode_def_id(ebml_w, local_def(m.id)); encode_def_id(ebml_w, local_def(m.id));
encode_name(ecx, ebml_w, mty.ident); encode_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx, m.tps); encode_type_param_bounds(ebml_w, ecx,
&m.generics.ty_params);
encode_type(ecx, ebml_w, encode_type(ecx, ebml_w,
ty::mk_bare_fn(tcx, copy mty.fty)); ty::mk_bare_fn(tcx, copy mty.fty));
encode_family(ebml_w, purity_fn_family(mty.fty.purity)); encode_family(ebml_w, purity_fn_family(mty.fty.purity));
@ -880,8 +897,14 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
// Finally, output all the provided methods as items. // Finally, output all the provided methods as items.
for provided_methods.each |m| { for provided_methods.each |m| {
index.push(entry { val: m.id, pos: ebml_w.writer.tell() }); index.push(entry { val: m.id, pos: ebml_w.writer.tell() });
// We do not concatenate the generics of the owning impl and that
// of provided methods. I am not sure why this is. -ndm
let owner_generics = ast_util::empty_generics();
encode_info_for_method(ecx, ebml_w, /*bad*/copy path, encode_info_for_method(ecx, ebml_w, /*bad*/copy path,
true, item.id, *m, /*bad*/copy m.tps); true, item.id, *m,
&owner_generics, &m.generics);
} }
} }
item_mac(*) => fail!(~"item macros unimplemented") item_mac(*) => fail!(~"item macros unimplemented")
@ -898,11 +921,11 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext,
index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() }); index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
ebml_w.start_tag(tag_items_data_item); ebml_w.start_tag(tag_items_data_item);
match /*bad*/copy nitem.node { match nitem.node {
foreign_item_fn(_, purity, tps) => { foreign_item_fn(_, purity, ref generics) => {
encode_def_id(ebml_w, local_def(nitem.id)); encode_def_id(ebml_w, local_def(nitem.id));
encode_family(ebml_w, purity_fn_family(purity)); encode_family(ebml_w, purity_fn_family(purity));
encode_type_param_bounds(ebml_w, ecx, tps); encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
if abi == foreign_abi_rust_intrinsic { if abi == foreign_abi_rust_intrinsic {
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem)); (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));

View file

@ -371,10 +371,10 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
ast::ii_foreign(i) => { ast::ii_foreign(i) => {
ast::ii_foreign(fld.fold_foreign_item(i)) ast::ii_foreign(fld.fold_foreign_item(i))
} }
ast::ii_dtor(ref dtor, nm, ref tps, parent_id) => { ast::ii_dtor(ref dtor, nm, ref generics, parent_id) => {
let dtor_body = fld.fold_block(&dtor.node.body); let dtor_body = fld.fold_block(&dtor.node.body);
let dtor_attrs = fld.fold_attributes(/*bad*/copy (*dtor).node.attrs); let dtor_attrs = fld.fold_attributes(/*bad*/copy (*dtor).node.attrs);
let new_params = fold::fold_ty_params(/*bad*/copy *tps, fld); let new_generics = fold::fold_generics(generics, fld);
let dtor_id = fld.new_id((*dtor).node.id); let dtor_id = fld.new_id((*dtor).node.id);
let new_parent = xcx.tr_def_id(parent_id); let new_parent = xcx.tr_def_id(parent_id);
let new_self = fld.new_id((*dtor).node.self_id); let new_self = fld.new_id((*dtor).node.self_id);
@ -386,7 +386,7 @@ fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
body: dtor_body }, body: dtor_body },
.. (/*bad*/copy *dtor) .. (/*bad*/copy *dtor)
}, },
nm, new_params, new_parent) nm, new_generics, new_parent)
} }
} }
} }

View file

@ -753,7 +753,7 @@ fn check_item_structural_records(cx: ty::ctxt, it: @ast::item) {
fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id, fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id,
decl: &ast::fn_decl) { decl: &ast::fn_decl) {
let tys = vec::map(decl.inputs, |a| a.ty ); let tys = vec::map(decl.inputs, |a| a.ty );
for vec::each(vec::append_one(tys, decl.output)) |ty| { for vec::each(vec::append_one(tys, decl.output)) |ty| {
match ty.node { match ty.node {

View file

@ -621,7 +621,8 @@ pub fn determine_rp_in_fn(fk: &visit::fn_kind,
} }
} }
(visitor.visit_ty)(decl.output, cx, visitor); (visitor.visit_ty)(decl.output, cx, visitor);
(visitor.visit_ty_params)(visit::tps_of_fn(fk), cx, visitor); let generics = visit::generics_of_fn(fk);
(visitor.visit_generics)(&generics, cx, visitor);
(visitor.visit_block)(body, cx, visitor); (visitor.visit_block)(body, cx, visitor);
} }
} }

View file

@ -42,6 +42,7 @@ use syntax::ast::{enum_variant_kind, expr, expr_again, expr_assign_op};
use syntax::ast::{expr_fn_block, expr_index, expr_loop}; use syntax::ast::{expr_fn_block, expr_index, expr_loop};
use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl}; use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge}; use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
use syntax::ast::{Generics};
use syntax::ast::{gt, ident, impure_fn, inherited, item, item_struct}; use syntax::ast::{gt, ident, impure_fn, inherited, item, item_struct};
use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod}; use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le}; use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
@ -53,9 +54,9 @@ use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl};
use syntax::ast::{struct_dtor, struct_field, struct_variant_kind, sty_by_ref}; use syntax::ast::{struct_dtor, struct_field, struct_variant_kind, sty_by_ref};
use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty}; use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty};
use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i}; use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i};
use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path}; use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, TyParam, ty_path};
use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint}; use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint};
use syntax::ast::{type_value_ns, ty_param_bound, unnamed_field}; use syntax::ast::{type_value_ns, unnamed_field};
use syntax::ast::{variant, view_item, view_item_extern_mod}; use syntax::ast::{variant, view_item, view_item_extern_mod};
use syntax::ast::{view_item_use, view_path_glob, view_path_list}; use syntax::ast::{view_item_use, view_path_glob, view_path_list};
use syntax::ast::{view_path_simple, visibility, anonymous, named, not}; use syntax::ast::{view_path_simple, visibility, anonymous, named, not};
@ -73,6 +74,8 @@ use syntax::visit::{default_visitor, fk_method, mk_vt, Visitor, visit_block};
use syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn}; use syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn};
use syntax::visit::{visit_foreign_item, visit_item, visit_method_helper}; use syntax::visit::{visit_foreign_item, visit_item, visit_method_helper};
use syntax::visit::{visit_mod, visit_ty, vt}; use syntax::visit::{visit_mod, visit_ty, vt};
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
use managed::ptr_eq; use managed::ptr_eq;
use dvec::DVec; use dvec::DVec;
@ -216,9 +219,9 @@ pub impl<T> ResolveResult<T> {
} }
pub enum TypeParameters/& { pub enum TypeParameters/& {
NoTypeParameters, //< No type parameters. NoTypeParameters, //< No type parameters.
HasTypeParameters(&~[ty_param], //< Type parameters. HasTypeParameters(&Generics, //< Type parameters.
node_id, //< ID of the enclosing item node_id, //< ID of the enclosing item
// The index to start numbering the type parameters at. // The index to start numbering the type parameters at.
// This is zero if this is the outermost set of type // This is zero if this is the outermost set of type
@ -231,7 +234,6 @@ pub enum TypeParameters/& {
// //
// The index at the method site will be 1, because the // The index at the method site will be 1, because the
// outer T had index 0. // outer T had index 0.
uint, uint,
// The kind of the rib used for type parameters. // The kind of the rib used for type parameters.
@ -1500,14 +1502,15 @@ pub impl Resolver {
self.add_child(name, parent, ForbidDuplicateValues, self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span); foreign_item.span);
match /*bad*/copy foreign_item.node { match foreign_item.node {
foreign_item_fn(_, _, type_parameters) => { foreign_item_fn(_, _, ref generics) => {
let def = def_fn(local_def(foreign_item.id), unsafe_fn); let def = def_fn(local_def(foreign_item.id), unsafe_fn);
name_bindings.define_value(Public, def, foreign_item.span); name_bindings.define_value(Public, def, foreign_item.span);
do self.with_type_parameter_rib do self.with_type_parameter_rib(
(HasTypeParameters(&type_parameters, foreign_item.id, HasTypeParameters(
0, NormalRibKind)) { generics, foreign_item.id, 0, NormalRibKind))
{
visit_foreign_item(foreign_item, new_parent, visitor); visit_foreign_item(foreign_item, new_parent, visitor);
} }
} }
@ -3582,8 +3585,7 @@ pub impl Resolver {
// enum item: resolve all the variants' discrs, // enum item: resolve all the variants' discrs,
// then resolve the ty params // then resolve the ty params
item_enum(ref enum_def, ref type_parameters) => { item_enum(ref enum_def, ref generics) => {
for (*enum_def).variants.each() |variant| { for (*enum_def).variants.each() |variant| {
do variant.node.disr_expr.iter() |dis_expr| { do variant.node.disr_expr.iter() |dis_expr| {
// resolve the discriminator expr // resolve the discriminator expr
@ -3599,14 +3601,14 @@ pub impl Resolver {
// error if there is one? -- tjc // error if there is one? -- tjc
do self.with_type_parameter_rib( do self.with_type_parameter_rib(
HasTypeParameters( HasTypeParameters(
type_parameters, item.id, 0, NormalRibKind)) { generics, item.id, 0, NormalRibKind)) {
visit_item(item, (), visitor); visit_item(item, (), visitor);
} }
} }
item_ty(_, type_parameters) => { item_ty(_, ref generics) => {
do self.with_type_parameter_rib do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, item.id, 0, (HasTypeParameters(generics, item.id, 0,
NormalRibKind)) NormalRibKind))
|| { || {
@ -3614,20 +3616,20 @@ pub impl Resolver {
} }
} }
item_impl(type_parameters, item_impl(ref generics,
implemented_traits, implemented_traits,
self_type, self_type,
methods) => { ref methods) => {
self.resolve_implementation(item.id, self.resolve_implementation(item.id,
item.span, item.span,
type_parameters, generics,
implemented_traits, implemented_traits,
self_type, self_type,
methods, *methods,
visitor); visitor);
} }
item_trait(ref type_parameters, ref traits, ref methods) => { item_trait(ref generics, ref traits, ref methods) => {
// Create a new rib for the self type. // Create a new rib for the self type.
let self_type_rib = @Rib(NormalRibKind); let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib); (*self.type_ribs).push(self_type_rib);
@ -3636,10 +3638,10 @@ pub impl Resolver {
// Create a new rib for the trait-wide type parameters. // Create a new rib for the trait-wide type parameters.
do self.with_type_parameter_rib do self.with_type_parameter_rib
(HasTypeParameters(type_parameters, item.id, 0, (HasTypeParameters(generics, item.id, 0,
NormalRibKind)) { NormalRibKind)) {
self.resolve_type_parameters(/*bad*/copy *type_parameters, self.resolve_type_parameters(&generics.ty_params,
visitor); visitor);
// Resolve derived traits. // Resolve derived traits.
@ -3672,18 +3674,18 @@ pub impl Resolver {
match *method { match *method {
required(ref ty_m) => { required(ref ty_m) => {
do self.with_type_parameter_rib do self.with_type_parameter_rib
(HasTypeParameters(&(*ty_m).tps, (HasTypeParameters(&ty_m.generics,
item.id, item.id,
type_parameters.len(), generics.ty_params.len(),
MethodRibKind(item.id, Required))) { MethodRibKind(item.id, Required))) {
// Resolve the method-specific type // Resolve the method-specific type
// parameters. // parameters.
self.resolve_type_parameters( self.resolve_type_parameters(
/*bad*/copy (*ty_m).tps, &ty_m.generics.ty_params,
visitor); visitor);
for (*ty_m).decl.inputs.each |argument| { for ty_m.decl.inputs.each |argument| {
self.resolve_type(argument.ty, visitor); self.resolve_type(argument.ty, visitor);
} }
@ -3694,7 +3696,7 @@ pub impl Resolver {
self.resolve_method(MethodRibKind(item.id, self.resolve_method(MethodRibKind(item.id,
Provided(m.id)), Provided(m.id)),
m, m,
type_parameters.len(), generics.ty_params.len(),
visitor) visitor)
} }
} }
@ -3704,12 +3706,12 @@ pub impl Resolver {
(*self.type_ribs).pop(); (*self.type_ribs).pop();
} }
item_struct(struct_def, ty_params) => { item_struct(struct_def, ref generics) => {
self.resolve_struct(item.id, self.resolve_struct(item.id,
@copy ty_params, generics,
/*bad*/copy struct_def.fields, struct_def.fields,
struct_def.dtor, struct_def.dtor,
visitor); visitor);
} }
item_mod(ref module_) => { item_mod(ref module_) => {
@ -3722,18 +3724,14 @@ pub impl Resolver {
item_foreign_mod(foreign_module) => { item_foreign_mod(foreign_module) => {
do self.with_scope(Some(item.ident)) { do self.with_scope(Some(item.ident)) {
for foreign_module.items.each |foreign_item| { for foreign_module.items.each |foreign_item| {
match /*bad*/copy foreign_item.node { match foreign_item.node {
foreign_item_fn(_, _, type_parameters) => { foreign_item_fn(_, _, ref generics) => {
do self.with_type_parameter_rib self.with_type_parameter_rib(
(HasTypeParameters(&type_parameters, HasTypeParameters(
foreign_item.id, generics, foreign_item.id, 0,
0, NormalRibKind),
OpaqueFunctionRibKind)) || visit_foreign_item(*foreign_item, (),
|| { visitor));
visit_foreign_item(*foreign_item, (),
visitor);
}
} }
foreign_item_const(_) => { foreign_item_const(_) => {
visit_foreign_item(*foreign_item, (), visit_foreign_item(*foreign_item, (),
@ -3744,7 +3742,7 @@ pub impl Resolver {
} }
} }
item_fn(ref fn_decl, _, ref ty_params, ref block) => { item_fn(ref fn_decl, _, ref generics, ref block) => {
// If this is the main function, we must record it in the // If this is the main function, we must record it in the
// session. // session.
// FIXME #4404 android JNI hacks // FIXME #4404 android JNI hacks
@ -3771,7 +3769,7 @@ pub impl Resolver {
self.resolve_function(OpaqueFunctionRibKind, self.resolve_function(OpaqueFunctionRibKind,
Some(@/*bad*/copy *fn_decl), Some(@/*bad*/copy *fn_decl),
HasTypeParameters HasTypeParameters
(ty_params, (generics,
item.id, item.id,
0, 0,
OpaqueFunctionRibKind), OpaqueFunctionRibKind),
@ -3798,13 +3796,13 @@ pub impl Resolver {
type_parameters: TypeParameters, type_parameters: TypeParameters,
f: fn()) { f: fn()) {
match type_parameters { match type_parameters {
HasTypeParameters(type_parameters, node_id, initial_index, HasTypeParameters(generics, node_id, initial_index,
rib_kind) => { rib_kind) => {
let function_type_rib = @Rib(rib_kind); let function_type_rib = @Rib(rib_kind);
(*self.type_ribs).push(function_type_rib); self.type_ribs.push(function_type_rib);
for (*type_parameters).eachi |index, type_parameter| { for generics.ty_params.eachi |index, type_parameter| {
let name = type_parameter.ident; let name = type_parameter.ident;
debug!("with_type_parameter_rib: %d %d", node_id, debug!("with_type_parameter_rib: %d %d", node_id,
type_parameter.id); type_parameter.id);
@ -3815,7 +3813,7 @@ pub impl Resolver {
// the item that bound it // the item that bound it
self.record_def(type_parameter.id, self.record_def(type_parameter.id,
def_typaram_binder(node_id)); def_typaram_binder(node_id));
(*function_type_rib).bindings.insert(name, def_like); function_type_rib.bindings.insert(name, def_like);
} }
} }
@ -3828,7 +3826,7 @@ pub impl Resolver {
match type_parameters { match type_parameters {
HasTypeParameters(*) => { HasTypeParameters(*) => {
(*self.type_ribs).pop(); self.type_ribs.pop();
} }
NoTypeParameters => { NoTypeParameters => {
@ -3871,8 +3869,8 @@ pub impl Resolver {
NoTypeParameters => { NoTypeParameters => {
// Continue. // Continue.
} }
HasTypeParameters(type_parameters, _, _, _) => { HasTypeParameters(ref generics, _, _, _) => {
self.resolve_type_parameters(/*bad*/copy *type_parameters, self.resolve_type_parameters(&generics.ty_params,
visitor); visitor);
} }
} }
@ -3927,7 +3925,7 @@ pub impl Resolver {
} }
fn resolve_type_parameters(@mut self, fn resolve_type_parameters(@mut self,
type_parameters: ~[ty_param], type_parameters: &OptVec<TyParam>,
visitor: ResolveVisitor) { visitor: ResolveVisitor) {
for type_parameters.each |type_parameter| { for type_parameters.each |type_parameter| {
for type_parameter.bounds.each |&bound| { for type_parameter.bounds.each |&bound| {
@ -3941,19 +3939,17 @@ pub impl Resolver {
fn resolve_struct(@mut self, fn resolve_struct(@mut self,
id: node_id, id: node_id,
type_parameters: @~[ty_param], generics: &Generics,
fields: ~[@struct_field], fields: &[@struct_field],
optional_destructor: Option<struct_dtor>, optional_destructor: Option<struct_dtor>,
visitor: ResolveVisitor) { visitor: ResolveVisitor) {
// If applicable, create a rib for the type parameters. // If applicable, create a rib for the type parameters.
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
do self.with_type_parameter_rib(HasTypeParameters do self.with_type_parameter_rib(HasTypeParameters
(borrowed_type_parameters, id, 0, (generics, id, 0,
OpaqueFunctionRibKind)) { OpaqueFunctionRibKind)) {
// Resolve the type parameters. // Resolve the type parameters.
self.resolve_type_parameters(/*bad*/copy *type_parameters, self.resolve_type_parameters(&generics.ty_params, visitor);
visitor);
// Resolve fields. // Resolve fields.
for fields.each |field| { for fields.each |field| {
@ -3986,9 +3982,9 @@ pub impl Resolver {
method: @method, method: @method,
outer_type_parameter_count: uint, outer_type_parameter_count: uint,
visitor: ResolveVisitor) { visitor: ResolveVisitor) {
let borrowed_method_type_parameters = &method.tps; let method_generics = &method.generics;
let type_parameters = let type_parameters =
HasTypeParameters(borrowed_method_type_parameters, HasTypeParameters(method_generics,
method.id, method.id,
outer_type_parameter_count, outer_type_parameter_count,
rib_kind); rib_kind);
@ -4010,19 +4006,18 @@ pub impl Resolver {
fn resolve_implementation(@mut self, fn resolve_implementation(@mut self,
id: node_id, id: node_id,
span: span, span: span,
type_parameters: ~[ty_param], generics: &Generics,
opt_trait_reference: Option<@trait_ref>, opt_trait_reference: Option<@trait_ref>,
self_type: @Ty, self_type: @Ty,
methods: ~[@method], methods: ~[@method],
visitor: ResolveVisitor) { visitor: ResolveVisitor) {
// If applicable, create a rib for the type parameters. // If applicable, create a rib for the type parameters.
let outer_type_parameter_count = type_parameters.len(); let outer_type_parameter_count = generics.ty_params.len();
let borrowed_type_parameters: &~[ty_param] = &type_parameters;
do self.with_type_parameter_rib(HasTypeParameters do self.with_type_parameter_rib(HasTypeParameters
(borrowed_type_parameters, id, 0, (generics, id, 0,
NormalRibKind)) { NormalRibKind)) {
// Resolve the type parameters. // Resolve the type parameters.
self.resolve_type_parameters(/*bad*/copy type_parameters, self.resolve_type_parameters(&generics.ty_params,
visitor); visitor);
// Resolve the trait reference, if necessary. // Resolve the trait reference, if necessary.

View file

@ -2103,9 +2103,9 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
} }
} }
} }
ast::item_impl(tps, _, _, ms) => { ast::item_impl(ref generics, _, _, ref ms) => {
meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None, meth::trans_impl(ccx, /*bad*/copy *path, item.ident, *ms,
item.id); generics, None, item.id);
} }
ast::item_mod(ref m) => { ast::item_mod(ref m) => {
trans_mod(ccx, m); trans_mod(ccx, m);

View file

@ -91,7 +91,9 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
region_param: _, region_param: _,
ty: _ ty: _
} = ty::lookup_item_type(ccx.tcx, impl_did); } = ty::lookup_item_type(ccx.tcx, impl_did);
if translate && (*impl_bnds).len() + mth.tps.len() == 0u { if translate &&
impl_bnds.len() + mth.generics.ty_params.len() == 0u
{
let llfn = get_item_val(ccx, mth.id); let llfn = get_item_val(ccx, mth.id);
let path = vec::append( let path = vec::append(
ty::item_path(ccx.tcx, impl_did), ty::item_path(ccx.tcx, impl_did),

View file

@ -46,13 +46,13 @@ be generated once they are invoked with specific type parameters,
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
*/ */
pub fn trans_impl(ccx: @CrateContext, +path: path, name: ast::ident, pub fn trans_impl(ccx: @CrateContext, +path: path, name: ast::ident,
methods: ~[@ast::method], tps: ~[ast::ty_param], methods: ~[@ast::method], generics: &ast::Generics,
self_ty: Option<ty::t>, id: ast::node_id) { self_ty: Option<ty::t>, id: ast::node_id) {
let _icx = ccx.insn_ctxt("impl::trans_impl"); let _icx = ccx.insn_ctxt("impl::trans_impl");
if tps.len() > 0u { return; } if !generics.ty_params.is_empty() { return; }
let sub_path = vec::append_one(path, path_name(name)); let sub_path = vec::append_one(path, path_name(name));
for vec::each(methods) |method| { for vec::each(methods) |method| {
if method.tps.len() == 0u { if method.generics.ty_params.len() == 0u {
let llfn = get_item_val(ccx, method.id); let llfn = get_item_val(ccx, method.id);
let path = vec::append_one(/*bad*/copy sub_path, let path = vec::append_one(/*bad*/copy sub_path,
path_name(method.ident)); path_name(method.ident));
@ -410,7 +410,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
debug!("method_ty_param_count: m_id: %?, i_id: %?", m_id, i_id); debug!("method_ty_param_count: m_id: %?, i_id: %?", m_id, i_id);
if m_id.crate == ast::local_crate { if m_id.crate == ast::local_crate {
match ccx.tcx.items.find(&m_id.node) { match ccx.tcx.items.find(&m_id.node) {
Some(ast_map::node_method(m, _, _)) => m.tps.len(), Some(ast_map::node_method(m, _, _)) => m.generics.ty_params.len(),
None => { None => {
match ccx.tcx.provided_method_sources.find(&m_id) { match ccx.tcx.provided_method_sources.find(&m_id) {
Some(source) => { Some(source) => {
@ -420,9 +420,9 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
None => fail!() None => fail!()
} }
} }
Some(ast_map::node_trait_method(@ast::provided(@ref m), _, _)) Some(ast_map::node_trait_method(@ast::provided(@ref m),
=> { _, _)) => {
m.tps.len() m.generics.ty_params.len()
} }
copy e => fail!(fmt!("method_ty_param_count %?", e)) copy e => fail!(fmt!("method_ty_param_count %?", e))
} }

View file

@ -99,36 +99,39 @@ fn traverse_public_item(cx: ctx, item: @item) {
cx.rmap.insert(item.id, ()); cx.rmap.insert(item.id, ());
match /*bad*/copy item.node { match /*bad*/copy item.node {
item_mod(ref m) => traverse_public_mod(cx, item.id, m), item_mod(ref m) => traverse_public_mod(cx, item.id, m),
item_foreign_mod(nm) => { item_foreign_mod(ref nm) => {
if !traverse_exports(cx, item.id) { if !traverse_exports(cx, item.id) {
for nm.items.each |item| { for nm.items.each |item| {
cx.rmap.insert(item.id, ()); cx.rmap.insert(item.id, ());
} }
} }
} }
item_fn(_, _, ref tps, ref blk) => { item_fn(_, _, ref generics, ref blk) => {
if tps.len() > 0u || if generics.ty_params.len() > 0u ||
attr::find_inline_attr(item.attrs) != attr::ia_none { attr::find_inline_attr(item.attrs) != attr::ia_none {
traverse_inline_body(cx, blk); traverse_inline_body(cx, blk);
} }
} }
item_impl(tps, _, _, ms) => { item_impl(ref generics, _, _, ref ms) => {
for vec::each(ms) |m| { for ms.each |m| {
if tps.len() > 0u || m.tps.len() > 0u || if generics.ty_params.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none { m.generics.ty_params.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none
{
cx.rmap.insert(m.id, ()); cx.rmap.insert(m.id, ());
traverse_inline_body(cx, &m.body); traverse_inline_body(cx, &m.body);
} }
} }
} }
item_struct(struct_def, tps) => { item_struct(ref struct_def, ref generics) => {
for struct_def.ctor_id.each |&ctor_id| { for struct_def.ctor_id.each |&ctor_id| {
cx.rmap.insert(ctor_id, ()); cx.rmap.insert(ctor_id, ());
} }
do option::iter(&struct_def.dtor) |dtor| { do struct_def.dtor.iter |dtor| {
cx.rmap.insert(dtor.node.id, ()); cx.rmap.insert(dtor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs) if generics.ty_params.len() > 0u ||
!= attr::ia_none { attr::find_inline_attr(dtor.node.attrs) != attr::ia_none
{
traverse_inline_body(cx, &dtor.node.body); traverse_inline_body(cx, &dtor.node.body);
} }
} }

View file

@ -4143,10 +4143,11 @@ pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
return tbl[tycat(ty)][opcat(op)]; return tbl[tycat(ty)][opcat(op)];
} }
pub fn ty_params_to_tys(tcx: ty::ctxt, tps: ~[ast::ty_param]) -> ~[t] { pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
vec::from_fn(tps.len(), |i| { vec::from_fn(generics.ty_params.len(), |i| {
ty::mk_param(tcx, i, ast_util::local_def(tps[i].id)) let id = generics.ty_params.get(i).id;
}) ty::mk_param(tcx, i, ast_util::local_def(id))
})
} }
/// Returns an equivalent type with all the typedefs and self regions removed. /// Returns an equivalent type with all the typedefs and self regions removed.

View file

@ -127,6 +127,8 @@ use syntax::codemap;
use syntax::parse::token::special_idents; use syntax::parse::token::special_idents;
use syntax::print::pprust; use syntax::print::pprust;
use syntax::visit; use syntax::visit;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax; use syntax;
pub mod _match; pub mod _match;
@ -603,9 +605,9 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
ast::item_struct(struct_def, _) => { ast::item_struct(struct_def, _) => {
check_struct(ccx, struct_def, it.id, it.span); check_struct(ccx, struct_def, it.id, it.span);
} }
ast::item_ty(t, tps) => { ast::item_ty(t, ref generics) => {
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id); let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
check_bounds_are_used(ccx, t.span, tps, tpt_ty); check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty);
// If this is a record ty, check for duplicate fields // If this is a record ty, check for duplicate fields
match t.node { match t.node {
ast::ty_rec(ref fields) => { ast::ty_rec(ref fields) => {
@ -1073,8 +1075,9 @@ pub fn impl_self_ty(vcx: &VtableContext,
node: ast::item_impl(ref ts, _, st, _), node: ast::item_impl(ref ts, _, st, _),
_ _
}, _)) => { }, _)) => {
(ts.len(), region_param, (ts.ty_params.len(),
vcx.ccx.to_ty(rscope::type_rscope(region_param), st)) region_param,
vcx.ccx.to_ty(rscope::type_rscope(region_param), st))
} }
Some(ast_map::node_item(@ast::item { Some(ast_map::node_item(@ast::item {
node: ast::item_struct(_, ref ts), node: ast::item_struct(_, ref ts),
@ -1085,12 +1088,13 @@ pub fn impl_self_ty(vcx: &VtableContext,
(doing a no-op subst for the ty params; in the next step, (doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them) we substitute in fresh vars for them)
*/ */
(ts.len(), region_param, (ts.ty_params.len(),
ty::mk_struct(tcx, local_def(class_id), region_param,
ty::mk_struct(tcx, local_def(class_id),
substs { substs {
self_r: rscope::bound_self_region(region_param), self_r: rscope::bound_self_region(region_param),
self_ty: None, self_ty: None,
tps: ty::ty_params_to_tys(tcx, /*bad*/copy *ts) tps: ty::ty_params_to_tys(tcx, ts)
})) }))
} }
_ => { tcx.sess.bug(~"impl_self_ty: unbound item or item that \ _ => { tcx.sess.bug(~"impl_self_ty: unbound item or item that \
@ -1873,11 +1877,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
tcx.region_paramd_items.find(&class_id.node); tcx.region_paramd_items.find(&class_id.node);
match tcx.items.find(&class_id.node) { match tcx.items.find(&class_id.node) {
Some(ast_map::node_item(@ast::item { Some(ast_map::node_item(@ast::item {
node: ast::item_struct(_, ref type_parameters), node: ast::item_struct(_, ref generics),
_ _
}, _)) => { }, _)) => {
type_parameter_count = type_parameters.len(); type_parameter_count = generics.ty_params.len();
let self_region = let self_region =
bound_self_region(region_parameterized); bound_self_region(region_parameterized);
@ -1887,7 +1891,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
self_ty: None, self_ty: None,
tps: ty::ty_params_to_tys( tps: ty::ty_params_to_tys(
tcx, tcx,
/*bad*/copy *type_parameters) generics)
}); });
} }
_ => { _ => {
@ -1957,11 +1961,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
tcx.region_paramd_items.find(&enum_id.node); tcx.region_paramd_items.find(&enum_id.node);
match tcx.items.find(&enum_id.node) { match tcx.items.find(&enum_id.node) {
Some(ast_map::node_item(@ast::item { Some(ast_map::node_item(@ast::item {
node: ast::item_enum(_, ref type_parameters), node: ast::item_enum(_, ref generics),
_ _
}, _)) => { }, _)) => {
type_parameter_count = type_parameters.len(); type_parameter_count = generics.ty_params.len();
let self_region = let self_region =
bound_self_region(region_parameterized); bound_self_region(region_parameterized);
@ -1971,7 +1975,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
self_ty: None, self_ty: None,
tps: ty::ty_params_to_tys( tps: ty::ty_params_to_tys(
tcx, tcx,
/*bad*/copy *type_parameters) generics)
}); });
} }
_ => { _ => {
@ -3137,7 +3141,7 @@ pub fn may_break(cx: ty::ctxt, id: ast::node_id, b: &ast::blk) -> bool {
pub fn check_bounds_are_used(ccx: @mut CrateCtxt, pub fn check_bounds_are_used(ccx: @mut CrateCtxt,
span: span, span: span,
tps: ~[ast::ty_param], tps: &OptVec<ast::TyParam>,
ty: ty::t) { ty: ty::t) {
debug!("check_bounds_are_used(n_tps=%u, ty=%s)", debug!("check_bounds_are_used(n_tps=%u, ty=%s)",
tps.len(), ppaux::ty_to_str(ccx.tcx, ty)); tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
@ -3164,7 +3168,7 @@ pub fn check_bounds_are_used(ccx: @mut CrateCtxt,
if !*b { if !*b {
ccx.tcx.sess.span_err( ccx.tcx.sess.span_err(
span, fmt!("type parameter `%s` is unused", span, fmt!("type parameter `%s` is unused",
*ccx.tcx.sess.str_of(tps[i].ident))); *ccx.tcx.sess.str_of(tps.get(i).ident)));
} }
} }
} }

View file

@ -147,7 +147,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo { pub fn method_to_MethodInfo(ast_method: @method) -> @MethodInfo {
@MethodInfo { @MethodInfo {
did: local_def(ast_method.id), did: local_def(ast_method.id),
n_tps: ast_method.tps.len(), n_tps: ast_method.generics.ty_params.len(),
ident: ast_method.ident, ident: ast_method.ident,
self_type: ast_method.self_ty.node self_type: ast_method.self_ty.node
} }

View file

@ -60,6 +60,8 @@ use syntax::codemap::span;
use syntax::codemap; use syntax::codemap;
use syntax::print::pprust::path_to_str; use syntax::print::pprust::path_to_str;
use syntax::visit; use syntax::visit;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) { pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
@ -70,8 +72,8 @@ pub fn collect_item_types(ccx: @mut CrateCtxt, crate: @ast::crate) {
if crate_item.ident if crate_item.ident
== ::syntax::parse::token::special_idents::intrinsic { == ::syntax::parse::token::special_idents::intrinsic {
match /*bad*/copy crate_item.node { match crate_item.node {
ast::item_mod(m) => { ast::item_mod(ref m) => {
for m.items.each |intrinsic_item| { for m.items.each |intrinsic_item| {
let def_id = ast::def_id { crate: ast::local_crate, let def_id = ast::def_id { crate: ast::local_crate,
node: intrinsic_item.id }; node: intrinsic_item.id };
@ -153,7 +155,7 @@ impl AstConv for CrateCtxt {
pub fn get_enum_variant_types(ccx: @mut CrateCtxt, pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
enum_ty: ty::t, enum_ty: ty::t,
variants: &[ast::variant], variants: &[ast::variant],
+ty_params: ~[ast::ty_param], generics: &ast::Generics,
rp: Option<ty::region_variance>) { rp: Option<ty::region_variance>) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
@ -175,7 +177,7 @@ pub fn get_enum_variant_types(ccx: @mut 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, ty_params), bounds: ty_param_bounds(ccx, generics),
region_param: rp, region_param: rp,
ty: enum_ty ty: enum_ty
}; };
@ -183,7 +185,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
convert_struct(ccx, convert_struct(ccx,
rp, rp,
struct_def, struct_def,
ty_params.to_vec(), generics,
tpt, tpt,
variant.node.id); variant.node.id);
@ -196,7 +198,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
get_enum_variant_types(ccx, get_enum_variant_types(ccx,
enum_ty, enum_ty,
enum_definition.variants, enum_definition.variants,
copy ty_params, generics,
rp); rp);
result_ty = None; result_ty = None;
} }
@ -206,7 +208,7 @@ pub fn get_enum_variant_types(ccx: @mut 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, ty_params), bounds: ty_param_bounds(ccx, generics),
region_param: rp, region_param: rp,
ty: result_ty ty: result_ty
}; };
@ -276,7 +278,7 @@ pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
let region_paramd = tcx.region_paramd_items.find(&id); let region_paramd = tcx.region_paramd_items.find(&id);
match tcx.items.get(&id) { match tcx.items.get(&id) {
ast_map::node_item(@ast::item { ast_map::node_item(@ast::item {
node: ast::item_trait(ref params, _, ref ms), node: ast::item_trait(ref generics, _, ref ms),
_ _
}, _) => { }, _) => {
store_methods::<ast::trait_method>(ccx, id, (/*bad*/copy *ms), |m| { store_methods::<ast::trait_method>(ccx, id, (/*bad*/copy *ms), |m| {
@ -288,10 +290,14 @@ pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
ast::provided(method) => def_id = local_def(method.id) ast::provided(method) => def_id = local_def(method.id)
} }
let trait_bounds = ty_param_bounds(ccx, *params); let trait_bounds = ty_param_bounds(ccx, generics);
let ty_m = trait_method_to_ty_method(m); let ty_m = trait_method_to_ty_method(m);
let method_ty = ty_of_ty_method(ccx, &ty_m, region_paramd, let method_ty = ty_of_ty_method(
def_id); ccx,
&ty_m,
region_paramd,
def_id
);
if ty_m.self_ty.node == ast::sty_static { if ty_m.self_ty.node == ast::sty_static {
make_static_method_ty(ccx, &ty_m, region_paramd, make_static_method_ty(ccx, &ty_m, region_paramd,
method_ty, trait_ty, method_ty, trait_ty,
@ -489,7 +495,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
} }
pub fn check_methods_against_trait(ccx: @mut CrateCtxt, pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
tps: ~[ast::ty_param], generics: &ast::Generics,
rp: Option<ty::region_variance>, rp: Option<ty::region_variance>,
selfty: ty::t, selfty: ty::t,
a_trait_ty: @ast::trait_ref, a_trait_ty: @ast::trait_ref,
@ -523,8 +529,9 @@ pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
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(ref trait_m) => { Some(ref trait_m) => {
let num_impl_tps = generics.ty_params.len();
compare_impl_method( compare_impl_method(
ccx.tcx, tps.len(), impl_m, trait_m, ccx.tcx, num_impl_tps, impl_m, trait_m,
&tpt.substs, selfty); &tpt.substs, selfty);
} }
None => { None => {
@ -569,7 +576,7 @@ pub fn convert_methods(ccx: @mut CrateCtxt,
let tcx = ccx.tcx; let tcx = ccx.tcx;
do vec::map(ms) |m| { do vec::map(ms) |m| {
let bounds = ty_param_bounds(ccx, m.tps); let bounds = ty_param_bounds(ccx, &m.generics);
let mty = ty_of_method(ccx, *m, rp); let mty = ty_of_method(ccx, *m, rp);
let fty = ty::mk_bare_fn(tcx, copy mty.fty); let fty = ty::mk_bare_fn(tcx, copy mty.fty);
tcx.tcache.insert( tcx.tcache.insert(
@ -590,9 +597,9 @@ pub fn convert_methods(ccx: @mut CrateCtxt,
pub fn ensure_no_ty_param_bounds(ccx: @mut CrateCtxt, pub fn ensure_no_ty_param_bounds(ccx: @mut CrateCtxt,
span: span, span: span,
ty_params: &[ast::ty_param], generics: &ast::Generics,
thing: &static/str) { thing: &static/str) {
for ty_params.each |ty_param| { for generics.ty_params.each |ty_param| {
if ty_param.bounds.len() > 0 { if ty_param.bounds.len() > 0 {
ccx.tcx.sess.span_err( ccx.tcx.sess.span_err(
span, span,
@ -607,21 +614,21 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
let rp = tcx.region_paramd_items.find(&it.id); let rp = tcx.region_paramd_items.find(&it.id);
debug!("convert: item %s with id %d rp %?", debug!("convert: item %s with id %d rp %?",
*tcx.sess.str_of(it.ident), it.id, rp); *tcx.sess.str_of(it.ident), it.id, rp);
match /*bad*/copy it.node { match it.node {
// These don't define types. // These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) => {} ast::item_foreign_mod(_) | ast::item_mod(_) => {}
ast::item_enum(ref enum_definition, ref ty_params) => { ast::item_enum(ref enum_definition, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration"); ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx, get_enum_variant_types(ccx,
tpt.ty, tpt.ty,
enum_definition.variants, enum_definition.variants,
copy *ty_params, generics,
rp); rp);
} }
ast::item_impl(ref tps, trait_ref, selfty, ref ms) => { ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, *tps); let i_bounds = ty_param_bounds(ccx, generics);
let selfty = ccx.to_ty(type_rscope(rp), selfty); let selfty = ccx.to_ty(type_rscope(rp), 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),
@ -633,11 +640,11 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
// XXX: Bad copy of `ms` below. // XXX: Bad copy of `ms` below.
let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds); let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds);
for trait_ref.each |t| { for trait_ref.each |t| {
check_methods_against_trait(ccx, /*bad*/copy *tps, rp, selfty, check_methods_against_trait(ccx, generics, rp, selfty,
*t, /*bad*/copy cms); *t, /*bad*/copy cms);
} }
} }
ast::item_trait(ref tps, ref supertraits, ref trait_methods) => { ast::item_trait(ref generics, ref supertraits, ref trait_methods) => {
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
debug!("item_trait(it.id=%d, tpt.ty=%s)", debug!("item_trait(it.id=%d, tpt.ty=%s)",
it.id, ppaux::ty_to_str(tcx, tpt.ty)); it.id, ppaux::ty_to_str(tcx, tpt.ty));
@ -647,21 +654,21 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
let (_, provided_methods) = let (_, provided_methods) =
split_trait_methods(/*bad*/copy *trait_methods); split_trait_methods(/*bad*/copy *trait_methods);
let (bounds, _) = mk_substs(ccx, /*bad*/copy *tps, rp); let (bounds, _) = mk_substs(ccx, generics, rp);
let _ = convert_methods(ccx, provided_methods, rp, bounds); let _ = convert_methods(ccx, provided_methods, rp, bounds);
} }
ast::item_struct(struct_def, tps) => { ast::item_struct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, tps, "structure"); ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
// Write the class type // Write the class type
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
convert_struct(ccx, rp, struct_def, tps, tpt, it.id); convert_struct(ccx, rp, struct_def, generics, tpt, it.id);
} }
ast::item_ty(_, ref ty_params) => { ast::item_ty(_, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "type"); ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
let tpt = ty_of_item(ccx, it); let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty); write_ty_to_tcx(tcx, it.id, tpt.ty);
} }
@ -678,7 +685,7 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
pub fn convert_struct(ccx: @mut CrateCtxt, pub fn convert_struct(ccx: @mut CrateCtxt,
rp: Option<ty::region_variance>, rp: Option<ty::region_variance>,
struct_def: @ast::struct_def, struct_def: @ast::struct_def,
+tps: ~[ast::ty_param], generics: &ast::Generics,
tpt: ty::ty_param_bounds_and_ty, tpt: ty::ty_param_bounds_and_ty,
id: ast::node_id) { id: ast::node_id) {
let tcx = ccx.tcx; let tcx = ccx.tcx;
@ -703,7 +710,7 @@ pub fn convert_struct(ccx: @mut CrateCtxt,
for struct_def.fields.each |f| { for struct_def.fields.each |f| {
convert_field(ccx, rp, tpt.bounds, *f); convert_field(ccx, rp, tpt.bounds, *f);
} }
let (_, substs) = mk_substs(ccx, tps, 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);
// If this struct is enum-like or tuple-like, create the type of its // If this struct is enum-like or tuple-like, create the type of its
@ -747,7 +754,7 @@ pub fn ty_of_method(ccx: @mut CrateCtxt,
rp: Option<ty::region_variance>) -> ty::method { rp: Option<ty::region_variance>) -> ty::method {
ty::method { ty::method {
ident: m.ident, ident: m.ident,
tps: ty_param_bounds(ccx, m.tps), tps: ty_param_bounds(ccx, &m.generics),
fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity, fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity,
ast::RustAbi, &m.decl), ast::RustAbi, &m.decl),
self_ty: m.self_ty.node, self_ty: m.self_ty.node,
@ -762,7 +769,7 @@ pub fn ty_of_ty_method(self: @mut CrateCtxt,
id: ast::def_id) -> ty::method { id: ast::def_id) -> ty::method {
ty::method { ty::method {
ident: m.ident, ident: m.ident,
tps: ty_param_bounds(self, m.tps), tps: ty_param_bounds(self, &m.generics),
fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity, fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity,
ast::RustAbi, &m.decl), ast::RustAbi, &m.decl),
// assume public, because this is only invoked on trait methods // assume public, because this is only invoked on trait methods
@ -810,17 +817,17 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
_ => {} _ => {}
} }
let rp = tcx.region_paramd_items.find(&it.id); let rp = tcx.region_paramd_items.find(&it.id);
match /*bad*/copy it.node { match it.node {
ast::item_const(t, _) => { ast::item_const(t, _) => {
let typ = ccx.to_ty(empty_rscope, t); let typ = ccx.to_ty(empty_rscope, t);
let tpt = no_params(typ); let tpt = no_params(typ);
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_fn(decl, purity, tps, _) => { ast::item_fn(ref decl, purity, ref generics, _) => {
let bounds = ty_param_bounds(ccx, tps); let bounds = ty_param_bounds(ccx, generics);
let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity, let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity,
ast::RustAbi, &decl); ast::RustAbi, decl);
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, bounds: bounds,
region_param: None, region_param: None,
@ -833,7 +840,7 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
ccx.tcx.tcache.insert(local_def(it.id), tpt); ccx.tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_ty(t, tps) => { ast::item_ty(t, ref generics) => {
match tcx.tcache.find(&local_def(it.id)) { match tcx.tcache.find(&local_def(it.id)) {
Some(tpt) => return tpt, Some(tpt) => return tpt,
None => { } None => { }
@ -847,12 +854,12 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
// like "foo<X>". This is because otherwise ty_to_str will // like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to // print the name as merely "foo", as it has no way to
// reconstruct the value of X. // reconstruct the value of X.
if !vec::is_empty(tps) { t0 } else { if !generics.is_empty() { t0 } else {
ty::mk_with_id(tcx, t0, def_id) ty::mk_with_id(tcx, t0, def_id)
} }
}; };
ty_param_bounds_and_ty { ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, tps), bounds: ty_param_bounds(ccx, generics),
region_param: rp, region_param: rp,
ty: ty ty: ty
} }
@ -861,9 +868,9 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_enum(_, tps) => { ast::item_enum(_, ref generics) => {
// Create a new generic polytype. // Create a new generic polytype.
let (bounds, substs) = mk_substs(ccx, tps, rp); let (bounds, 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, bounds: bounds,
@ -873,8 +880,8 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_trait(tps, _, _) => { ast::item_trait(ref generics, _, _) => {
let (bounds, substs) = mk_substs(ccx, tps, rp); let (bounds, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_trait(tcx, local_def(it.id), substs, ty::vstore_box); let t = ty::mk_trait(tcx, local_def(it.id), substs, ty::vstore_box);
let tpt = ty_param_bounds_and_ty { let tpt = ty_param_bounds_and_ty {
bounds: bounds, bounds: bounds,
@ -884,8 +891,8 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt); tcx.tcache.insert(local_def(it.id), tpt);
return tpt; return tpt;
} }
ast::item_struct(_, tps) => { ast::item_struct(_, ref generics) => {
let (bounds, substs) = mk_substs(ccx, tps, rp); let (bounds, 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, bounds: bounds,
@ -904,8 +911,13 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item) pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item)
-> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
match /*bad*/copy it.node { match /*bad*/copy it.node {
ast::foreign_item_fn(ref fn_decl, _, ref params) => { ast::foreign_item_fn(ref fn_decl, _, ref generics) => {
ty_of_foreign_fn_decl(ccx, fn_decl, *params, local_def(it.id)) ty_of_foreign_fn_decl(
ccx,
fn_decl,
local_def(it.id),
generics
)
} }
ast::foreign_item_const(t) => { ast::foreign_item_const(t) => {
let rb = in_binding_rscope(empty_rscope); let rb = in_binding_rscope(empty_rscope);
@ -923,9 +935,9 @@ pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item)
// either be user-defined traits, or one of the four built-in traits (formerly // either be user-defined traits, or one of the four built-in traits (formerly
// known as kinds): Const, Copy, Durable, and Send. // known as kinds): Const, Copy, Durable, and Send.
pub fn compute_bounds(ccx: @mut CrateCtxt, pub fn compute_bounds(ccx: @mut CrateCtxt,
ast_bounds: @~[ast::ty_param_bound]) ast_bounds: @OptVec<ast::TyParamBound>)
-> ty::param_bounds { -> ty::param_bounds {
@do vec::flat_map(*ast_bounds) |b| { @ast_bounds.flat_map_to_vec(|b| {
match b { match b {
&TraitTyParamBound(b) => { &TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items; let li = &ccx.tcx.lang_items;
@ -955,13 +967,13 @@ pub fn compute_bounds(ccx: @mut CrateCtxt,
} }
&RegionTyParamBound => ~[ty::bound_durable] &RegionTyParamBound => ~[ty::bound_durable]
} }
} })
} }
pub fn ty_param_bounds(ccx: @mut CrateCtxt, pub fn ty_param_bounds(ccx: @mut CrateCtxt,
params: &[ast::ty_param]) generics: &ast::Generics)
-> @~[ty::param_bounds] { -> @~[ty::param_bounds] {
@do params.map |param| { @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 => {
@ -975,10 +987,10 @@ pub fn ty_param_bounds(ccx: @mut CrateCtxt,
pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt, pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
decl: &ast::fn_decl, decl: &ast::fn_decl,
ty_params: &[ast::ty_param], def_id: ast::def_id,
def_id: ast::def_id) generics: &ast::Generics)
-> ty::ty_param_bounds_and_ty { -> ty::ty_param_bounds_and_ty {
let bounds = ty_param_bounds(ccx, ty_params); let bounds = ty_param_bounds(ccx, generics);
let rb = in_binding_rscope(empty_rscope); let rb = in_binding_rscope(empty_rscope);
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);
@ -999,13 +1011,13 @@ pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
return tpt; return tpt;
} }
pub fn mk_ty_params(ccx: @mut CrateCtxt, atps: ~[ast::ty_param]) pub fn mk_generics(ccx: @mut CrateCtxt, generics: &ast::Generics)
-> (@~[ty::param_bounds], ~[ty::t]) { -> (@~[ty::param_bounds], ~[ty::t])
{
let mut i = 0u; let mut i = 0u;
let bounds = ty_param_bounds(ccx, atps); let bounds = ty_param_bounds(ccx, generics);
(bounds, (bounds,
vec::map(atps, |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
@ -1013,10 +1025,11 @@ pub fn mk_ty_params(ccx: @mut CrateCtxt, atps: ~[ast::ty_param])
} }
pub fn mk_substs(ccx: @mut CrateCtxt, pub fn mk_substs(ccx: @mut CrateCtxt,
+atps: ~[ast::ty_param], generics: &ast::Generics,
rp: Option<ty::region_variance>) rp: Option<ty::region_variance>)
-> (@~[ty::param_bounds], ty::substs) { -> (@~[ty::param_bounds], ty::substs)
let (bounds, params) = mk_ty_params(ccx, atps); {
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 }) (bounds, substs { self_r: self_r, self_ty: None, tps: params })
} }

View file

@ -77,7 +77,7 @@ fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> {
ident: ident, ident: ident,
node: ast::foreign_item_fn(ref decl, _, ref tys), _ node: ast::foreign_item_fn(ref decl, _, ref tys), _
}, _, _) => { }, _, _) => {
Some(pprust::fun_to_str(*decl, ident, copy *tys, Some(pprust::fun_to_str(decl, ident, tys,
extract::interner())) extract::interner()))
} }
_ => fail!(~"get_fn_sig: fn_id not bound to a fn item") _ => fail!(~"get_fn_sig: fn_id not bound to a fn item")
@ -213,17 +213,17 @@ fn get_method_sig(
match method { match method {
ast::required(ty_m) => { ast::required(ty_m) => {
Some(pprust::fun_to_str( Some(pprust::fun_to_str(
ty_m.decl, &ty_m.decl,
ty_m.ident, ty_m.ident,
copy ty_m.tps, &ty_m.generics,
extract::interner() extract::interner()
)) ))
} }
ast::provided(m) => { ast::provided(m) => {
Some(pprust::fun_to_str( Some(pprust::fun_to_str(
m.decl, &m.decl,
m.ident, m.ident,
copy m.tps, &m.generics,
extract::interner() extract::interner()
)) ))
} }
@ -240,9 +240,9 @@ fn get_method_sig(
}) { }) {
Some(method) => { Some(method) => {
Some(pprust::fun_to_str( Some(pprust::fun_to_str(
method.decl, &method.decl,
method.ident, method.ident,
copy method.tps, &method.generics,
extract::interner() extract::interner()
)) ))
} }
@ -339,7 +339,7 @@ fn fold_type(
Some(fmt!( Some(fmt!(
"type %s%s = %s", "type %s%s = %s",
to_str(ident), to_str(ident),
pprust::typarams_to_str(*params, pprust::generics_to_str(params,
extract::interner()), extract::interner()),
pprust::ty_to_str(ty, pprust::ty_to_str(ty,
extract::interner()) extract::interner())

View file

@ -251,7 +251,11 @@ pub fn sha1() -> Sha1 {
let rr = mk_result(self); let rr = mk_result(self);
let mut s = ~""; let mut s = ~"";
for vec::each(rr) |b| { for vec::each(rr) |b| {
s += uint::to_str_radix(*b as uint, 16u); let hex = uint::to_str_radix(*b as uint, 16u);
if hex.len() == 1 {
s += "0";
}
s += hex;
} }
return s; return s;
} }
@ -283,6 +287,7 @@ mod tests {
struct Test { struct Test {
input: ~str, input: ~str,
output: ~[u8], output: ~[u8],
output_str: ~str,
} }
fn a_million_letter_a() -> ~str { fn a_million_letter_a() -> ~str {
@ -306,6 +311,7 @@ mod tests {
0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8, 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
], ],
output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d"
}, },
Test { Test {
input: input:
@ -318,6 +324,7 @@ mod tests {
0xF9u8, 0x51u8, 0x29u8, 0xE5u8, 0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
0xE5u8, 0x46u8, 0x70u8, 0xF1u8, 0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
], ],
output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1"
}, },
Test { Test {
input: a_million_letter_a(), input: a_million_letter_a(),
@ -328,6 +335,7 @@ mod tests {
0xDBu8, 0xADu8, 0x27u8, 0x31u8, 0xDBu8, 0xADu8, 0x27u8, 0x31u8,
0x65u8, 0x34u8, 0x01u8, 0x6Fu8, 0x65u8, 0x34u8, 0x01u8, 0x6Fu8,
], ],
output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f"
}, },
]; ];
// Examples from wikipedia // Examples from wikipedia
@ -342,6 +350,7 @@ mod tests {
0xbbu8, 0x76u8, 0xe7u8, 0x39u8, 0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
0x1bu8, 0x93u8, 0xebu8, 0x12u8, 0x1bu8, 0x93u8, 0xebu8, 0x12u8,
], ],
output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
}, },
Test { Test {
input: ~"The quick brown fox jumps over the lazy cog", input: ~"The quick brown fox jumps over the lazy cog",
@ -352,6 +361,7 @@ mod tests {
0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
0x10u8, 0x0du8, 0xb4u8, 0xb3u8, 0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
], ],
output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
}, },
]; ];
let tests = fips_180_1_tests + wikipedia_tests; let tests = fips_180_1_tests + wikipedia_tests;
@ -373,6 +383,11 @@ mod tests {
sh.input_str(t.input); sh.input_str(t.input);
let out = sh.result(); let out = sh.result();
check_vec_eq(t.output, out); check_vec_eq(t.output, out);
let out_str = sh.result_str();
assert(out_str.len() == 40);
assert(out_str == t.output_str);
sh.reset(); sh.reset();
} }
@ -389,6 +404,11 @@ mod tests {
} }
let out = sh.result(); let out = sh.result();
check_vec_eq(t.output, out); check_vec_eq(t.output, out);
let out_str = sh.result_str();
assert(out_str.len() == 40);
assert(out_str == t.output_str);
sh.reset(); sh.reset();
} }
} }

View file

@ -21,6 +21,8 @@ use core::to_bytes;
use core::to_str::ToStr; use core::to_str::ToStr;
use std::serialize::{Encodable, Decodable, Encoder, Decoder}; use std::serialize::{Encodable, Decodable, Encoder, Decoder};
use opt_vec::OptVec;
/* can't import macros yet, so this is copied from token.rs. See its comment /* can't import macros yet, so this is copied from token.rs. See its comment
* there. */ * there. */
macro_rules! interner_key ( macro_rules! interner_key (
@ -96,6 +98,9 @@ impl to_bytes::IterBytes for ident {
// Functions may or may not have names. // Functions may or may not have names.
pub type fn_ident = Option<ident>; pub type fn_ident = Option<ident>;
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub struct Lifetime { pub struct Lifetime {
id: node_id, id: node_id,
span: span, span: span,
@ -135,7 +140,7 @@ pub const crate_node_id: node_id = 0;
// typeck::collect::compute_bounds matches these against // typeck::collect::compute_bounds matches these against
// 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 ty_param_bound { pub enum TyParamBound {
TraitTyParamBound(@Ty), TraitTyParamBound(@Ty),
RegionTyParamBound RegionTyParamBound
} }
@ -143,10 +148,24 @@ pub enum ty_param_bound {
#[auto_encode] #[auto_encode]
#[auto_decode] #[auto_decode]
#[deriving_eq] #[deriving_eq]
pub struct ty_param { pub struct TyParam {
ident: ident, ident: ident,
id: node_id, id: node_id,
bounds: @~[ty_param_bound] bounds: @OptVec<TyParamBound>
}
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub struct Generics {
lifetimes: OptVec<Lifetime>,
ty_params: OptVec<TyParam>
}
impl Generics {
fn is_empty(&self) -> bool {
self.lifetimes.len() + self.ty_params.len() == 0
}
} }
#[auto_encode] #[auto_encode]
@ -273,8 +292,8 @@ pub enum pat_ {
// records this pattern's node_id in an auxiliary // records this pattern's node_id in an auxiliary
// set (of "pat_idents that refer to nullary enums") // set (of "pat_idents that refer to nullary enums")
pat_ident(binding_mode, @path, Option<@pat>), pat_ident(binding_mode, @path, Option<@pat>),
pat_enum(@path, Option<~[@pat]>), // "none" means a * pattern where pat_enum(@path, Option<~[@pat]>), /* "none" means a * pattern where
// we don't bind the fields to names * we don't bind the fields to names */
pat_rec(~[field_pat], bool), pat_rec(~[field_pat], bool),
pat_struct(@path, ~[field_pat], bool), pat_struct(@path, ~[field_pat], bool),
pat_tup(~[@pat]), pat_tup(~[@pat]),
@ -749,7 +768,7 @@ pub struct ty_method {
attrs: ~[attribute], attrs: ~[attribute],
purity: purity, purity: purity,
decl: fn_decl, decl: fn_decl,
tps: ~[ty_param], generics: Generics,
self_ty: self_ty, self_ty: self_ty,
id: node_id, id: node_id,
span: span, span: span,
@ -1012,7 +1031,7 @@ pub type self_ty = spanned<self_ty_>;
pub struct method { pub struct method {
ident: ident, ident: ident,
attrs: ~[attribute], attrs: ~[attribute],
tps: ~[ty_param], generics: Generics,
self_ty: self_ty, self_ty: self_ty,
purity: purity, purity: purity,
decl: fn_decl, decl: fn_decl,
@ -1248,14 +1267,14 @@ pub struct item {
#[deriving_eq] #[deriving_eq]
pub enum item_ { pub enum item_ {
item_const(@Ty, @expr), item_const(@Ty, @expr),
item_fn(fn_decl, purity, ~[ty_param], blk), item_fn(fn_decl, purity, Generics, blk),
item_mod(_mod), item_mod(_mod),
item_foreign_mod(foreign_mod), item_foreign_mod(foreign_mod),
item_ty(@Ty, ~[ty_param]), item_ty(@Ty, Generics),
item_enum(enum_def, ~[ty_param]), item_enum(enum_def, Generics),
item_struct(@struct_def, ~[ty_param]), item_struct(@struct_def, Generics),
item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]), item_trait(Generics, ~[@trait_ref], ~[trait_method]),
item_impl(~[ty_param], item_impl(Generics,
Option<@trait_ref>, // (optional) trait this impl implements Option<@trait_ref>, // (optional) trait this impl implements
@Ty, // self @Ty, // self
~[@method]), ~[@method]),
@ -1302,7 +1321,7 @@ pub struct foreign_item {
#[auto_decode] #[auto_decode]
#[deriving_eq] #[deriving_eq]
pub enum foreign_item_ { pub enum foreign_item_ {
foreign_item_fn(fn_decl, purity, ~[ty_param]), foreign_item_fn(fn_decl, purity, Generics),
foreign_item_const(@Ty) foreign_item_const(@Ty)
} }
@ -1316,7 +1335,7 @@ pub enum inlined_item {
ii_item(@item), ii_item(@item),
ii_method(def_id /* impl id */, @method), ii_method(def_id /* impl id */, @method),
ii_foreign(@foreign_item), ii_foreign(@foreign_item),
ii_dtor(struct_dtor, ident, ~[ty_param], def_id /* parent id */) ii_dtor(struct_dtor, ident, Generics, def_id /* parent id */)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -101,7 +101,7 @@ pub enum ast_node {
node_arg(arg, uint), node_arg(arg, uint),
node_local(uint), node_local(uint),
// Destructor for a struct // Destructor for a struct
node_dtor(~[ty_param], @struct_dtor, def_id, @path), node_dtor(Generics, @struct_dtor, def_id, @path),
node_block(blk), node_block(blk),
node_struct_ctor(@struct_def, @item, @path), node_struct_ctor(@struct_def, @item, @path),
} }
@ -199,7 +199,7 @@ pub fn map_fn(
cx.local_id += 1u; cx.local_id += 1u;
} }
match *fk { match *fk {
visit::fk_dtor(tps, ref attrs, self_id, parent_id) => { visit::fk_dtor(generics, ref attrs, self_id, parent_id) => {
let dt = @spanned { let dt = @spanned {
node: ast::struct_dtor_ { node: ast::struct_dtor_ {
id: id, id: id,
@ -212,7 +212,7 @@ pub fn map_fn(
cx.map.insert( cx.map.insert(
id, id,
node_dtor( node_dtor(
/* FIXME (#2543) */ vec::from_slice(tps), /* FIXME (#2543) */ copy *generics,
dt, dt,
parent_id, parent_id,
@/* FIXME (#2543) */ copy cx.path)); @/* FIXME (#2543) */ copy cx.path));

View file

@ -16,6 +16,7 @@ use ast_util;
use codemap::{span, BytePos, dummy_sp}; use codemap::{span, BytePos, dummy_sp};
use parse::token; use parse::token;
use visit; use visit;
use opt_vec;
use core::cmp; use core::cmp;
use core::int; use core::int;
@ -269,7 +270,7 @@ pub fn trait_method_to_ty_method(method: &trait_method) -> ty_method {
attrs: copy m.attrs, attrs: copy m.attrs,
purity: m.purity, purity: m.purity,
decl: copy m.decl, decl: copy m.decl,
tps: copy m.tps, generics: copy m.generics,
self_ty: m.self_ty, self_ty: m.self_ty,
id: m.id, id: m.id,
span: m.span, span: m.span,
@ -327,8 +328,9 @@ impl inlined_item_utils for inlined_item {
ii_item(i) => (v.visit_item)(i, e, v), ii_item(i) => (v.visit_item)(i, e, v),
ii_foreign(i) => (v.visit_foreign_item)(i, e, v), ii_foreign(i) => (v.visit_foreign_item)(i, e, v),
ii_method(_, m) => visit::visit_method_helper(m, e, v), ii_method(_, m) => visit::visit_method_helper(m, e, v),
ii_dtor(/*bad*/ copy dtor, _, /*bad*/ copy tps, parent_id) => { ii_dtor(/*bad*/ copy dtor, _, ref generics, parent_id) => {
visit::visit_struct_dtor_helper(dtor, tps, parent_id, e, v); visit::visit_struct_dtor_helper(dtor, generics,
parent_id, e, v);
} }
} }
} }
@ -375,6 +377,11 @@ pub fn dtor_dec() -> fn_decl {
} }
} }
pub fn empty_generics() -> Generics {
Generics {lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty}
}
// ______________________________________________________________________ // ______________________________________________________________________
// Enumerating the IDs which appear in an AST // Enumerating the IDs which appear in an AST
@ -390,6 +397,14 @@ pub fn empty(range: id_range) -> bool {
} }
pub fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { pub fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
let visit_generics = fn@(generics: &Generics) {
for generics.ty_params.each |p| {
vfn(p.id);
}
for generics.lifetimes.each |p| {
vfn(p.id);
}
};
visit::mk_simple_visitor(@visit::SimpleVisitor { visit::mk_simple_visitor(@visit::SimpleVisitor {
visit_mod: |_m, _sp, id| vfn(id), visit_mod: |_m, _sp, id| vfn(id),
@ -457,29 +472,25 @@ pub fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
} }
}, },
visit_ty_params: fn@(ps: &[ty_param]) { visit_generics: visit_generics,
for ps.each |p| {
vfn(p.id);
}
},
visit_fn: fn@(fk: &visit::fn_kind, d: &ast::fn_decl, visit_fn: fn@(fk: &visit::fn_kind, d: &ast::fn_decl,
_b: &ast::blk, _sp: span, id: ast::node_id) { _b: &ast::blk, _sp: span, id: ast::node_id) {
vfn(id); vfn(id);
match *fk { match *fk {
visit::fk_dtor(ref tps, _, self_id, parent_id) => { visit::fk_dtor(generics, _, self_id, parent_id) => {
for tps.each |tp| { vfn(tp.id); } visit_generics(generics);
vfn(id); vfn(id);
vfn(self_id); vfn(self_id);
vfn(parent_id.node); vfn(parent_id.node);
} }
visit::fk_item_fn(_, ref tps, _) => { visit::fk_item_fn(_, generics, _) => {
for tps.each |tp| { vfn(tp.id); } visit_generics(generics);
} }
visit::fk_method(_, ref tps, m) => { visit::fk_method(_, generics, m) => {
vfn(m.self_id); vfn(m.self_id);
for tps.each |tp| { vfn(tp.id); } visit_generics(generics);
} }
visit::fk_anon(_) | visit::fk_anon(_) |
visit::fk_fn_block => { visit::fk_fn_block => {
@ -497,7 +508,9 @@ pub fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
visit_trait_method: fn@(_ty_m: &trait_method) { visit_trait_method: fn@(_ty_m: &trait_method) {
}, },
visit_struct_def: fn@(_sd: @struct_def, _id: ident, _tps: &[ty_param], visit_struct_def: fn@(_sd: @struct_def,
_id: ident,
_generics: &Generics,
_id: node_id) { _id: node_id) {
}, },

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
/* /*!
The compiler code necessary to implement the #[auto_encode] and The compiler code necessary to implement the #[auto_encode] and
#[auto_decode] extension. The idea here is that type-defining items may #[auto_decode] extension. The idea here is that type-defining items may
@ -96,6 +96,9 @@ use attr;
use codemap::span; use codemap::span;
use ext::base::*; use ext::base::*;
use parse; use parse;
use opt_vec;
use opt_vec::OptVec;
use ext::build;
use core::vec; use core::vec;
use std::oldmap; use std::oldmap;
@ -127,24 +130,24 @@ pub fn expand_auto_encode(
do vec::flat_map(in_items) |item| { do vec::flat_map(in_items) |item| {
if item.attrs.any(is_auto_encode) { if item.attrs.any(is_auto_encode) {
match item.node { match item.node {
ast::item_struct(ref struct_def, ref tps) => { ast::item_struct(ref struct_def, ref generics) => {
let ser_impl = mk_struct_ser_impl( let ser_impl = mk_struct_ser_impl(
cx, cx,
item.span, item.span,
item.ident, item.ident,
struct_def.fields, struct_def.fields,
*tps generics
); );
~[filter_attrs(*item), ser_impl] ~[filter_attrs(*item), ser_impl]
}, },
ast::item_enum(ref enum_def, ref tps) => { ast::item_enum(ref enum_def, ref generics) => {
let ser_impl = mk_enum_ser_impl( let ser_impl = mk_enum_ser_impl(
cx, cx,
item.span, item.span,
item.ident, item.ident,
copy *enum_def, copy *enum_def,
copy *tps generics
); );
~[filter_attrs(*item), ser_impl] ~[filter_attrs(*item), ser_impl]
@ -182,24 +185,24 @@ pub fn expand_auto_decode(
do vec::flat_map(in_items) |item| { do vec::flat_map(in_items) |item| {
if item.attrs.any(is_auto_decode) { if item.attrs.any(is_auto_decode) {
match item.node { match item.node {
ast::item_struct(ref struct_def, ref tps) => { ast::item_struct(ref struct_def, ref generics) => {
let deser_impl = mk_struct_deser_impl( let deser_impl = mk_struct_deser_impl(
cx, cx,
item.span, item.span,
item.ident, item.ident,
struct_def.fields, struct_def.fields,
copy *tps generics
); );
~[filter_attrs(*item), deser_impl] ~[filter_attrs(*item), deser_impl]
}, },
ast::item_enum(ref enum_def, ref tps) => { ast::item_enum(ref enum_def, ref generics) => {
let deser_impl = mk_enum_deser_impl( let deser_impl = mk_enum_deser_impl(
cx, cx,
item.span, item.span,
item.ident, item.ident,
copy *enum_def, copy *enum_def,
copy *tps generics
); );
~[filter_attrs(*item), deser_impl] ~[filter_attrs(*item), deser_impl]
@ -222,18 +225,18 @@ priv impl ext_ctxt {
span: span, span: span,
ident: ast::ident, ident: ast::ident,
path: @ast::path, path: @ast::path,
bounds: @~[ast::ty_param_bound] bounds: @OptVec<ast::TyParamBound>
) -> ast::ty_param { ) -> ast::TyParam {
let bound = ast::TraitTyParamBound(@ast::Ty { let bound = ast::TraitTyParamBound(@ast::Ty {
id: self.next_id(), id: self.next_id(),
node: ast::ty_path(path, self.next_id()), node: ast::ty_path(path, self.next_id()),
span: span, span: span,
}); });
ast::ty_param { ast::TyParam {
ident: ident, ident: ident,
id: self.next_id(), id: self.next_id(),
bounds: @vec::append(~[bound], *bounds) bounds: @bounds.prepend(bound)
} }
} }
@ -417,28 +420,45 @@ fn mk_impl(
cx: ext_ctxt, cx: ext_ctxt,
span: span, span: span,
ident: ast::ident, ident: ast::ident,
ty_param: ast::ty_param, ty_param: ast::TyParam,
path: @ast::path, path: @ast::path,
tps: &[ast::ty_param], generics: &ast::Generics,
f: fn(@ast::Ty) -> @ast::method f: fn(@ast::Ty) -> @ast::method
) -> @ast::item { ) -> @ast::item {
// All the type parameters need to bound to the trait. /*!
let mut trait_tps = vec::append( *
~[ty_param], * Given that we are deriving auto-encode a type `T<'a, ...,
do tps.map |tp| { * 'z, A, ..., Z>`, creates an impl like:
let t_bound = ast::TraitTyParamBound(@ast::Ty { *
id: cx.next_id(), * impl<'a, ..., 'z, A:Tr, ..., Z:Tr> Tr for T<A, ..., Z> { ... }
node: ast::ty_path(path, cx.next_id()), *
span: span, * where Tr is either Serializable and Deserialize.
}); *
* FIXME(#5090): Remove code duplication between this and the code
* in deriving.rs
*/
ast::ty_param {
ident: tp.ident, // Copy the lifetimes
id: cx.next_id(), let impl_lifetimes = generics.lifetimes.map(|l| {
bounds: @vec::append(~[t_bound], *tp.bounds) build::mk_lifetime(cx, l.span, l.ident)
} });
}
); // All the type parameters need to bound to the trait.
let mut impl_tps = opt_vec::with(ty_param);
for generics.ty_params.each |tp| {
let t_bound = ast::TraitTyParamBound(@ast::Ty {
id: cx.next_id(),
node: ast::ty_path(path, cx.next_id()),
span: span,
});
impl_tps.push(ast::TyParam {
ident: tp.ident,
id: cx.next_id(),
bounds: @tp.bounds.prepend(t_bound)
})
}
let opt_trait = Some(@ast::trait_ref { let opt_trait = Some(@ast::trait_ref {
path: path, path: path,
@ -448,16 +468,22 @@ fn mk_impl(
let ty = cx.ty_path( let ty = cx.ty_path(
span, span,
~[ident], ~[ident],
tps.map(|tp| cx.ty_path(span, ~[tp.ident], ~[])) generics.ty_params.map(
|tp| cx.ty_path(span, ~[tp.ident], ~[])).to_vec()
); );
let generics = ast::Generics {
lifetimes: impl_lifetimes,
ty_params: impl_tps
};
@ast::item { @ast::item {
// This is a new-style impl declaration. // This is a new-style impl declaration.
// XXX: clownshoes // XXX: clownshoes
ident: parse::token::special_idents::clownshoes_extensions, ident: parse::token::special_idents::clownshoes_extensions,
attrs: ~[], attrs: ~[],
id: cx.next_id(), id: cx.next_id(),
node: ast::item_impl(trait_tps, opt_trait, ty, ~[f(ty)]), node: ast::item_impl(generics, opt_trait, ty, ~[f(ty)]),
vis: ast::public, vis: ast::public,
span: span, span: span,
} }
@ -467,7 +493,7 @@ fn mk_ser_impl(
cx: ext_ctxt, cx: ext_ctxt,
span: span, span: span,
ident: ast::ident, ident: ast::ident,
tps: &[ast::ty_param], generics: &ast::Generics,
body: @ast::expr body: @ast::expr
) -> @ast::item { ) -> @ast::item {
// Make a path to the std::serialize::Encodable typaram. // Make a path to the std::serialize::Encodable typaram.
@ -482,7 +508,7 @@ fn mk_ser_impl(
cx.ident_of(~"Encoder"), cx.ident_of(~"Encoder"),
] ]
), ),
@~[] @opt_vec::Empty
); );
// Make a path to the std::serialize::Encodable trait. // Make a path to the std::serialize::Encodable trait.
@ -502,7 +528,7 @@ fn mk_ser_impl(
ident, ident,
ty_param, ty_param,
path, path,
tps, generics,
|_ty| mk_ser_method(cx, span, cx.expr_blk(body)) |_ty| mk_ser_method(cx, span, cx.expr_blk(body))
) )
} }
@ -511,7 +537,7 @@ fn mk_deser_impl(
cx: ext_ctxt, cx: ext_ctxt,
span: span, span: span,
ident: ast::ident, ident: ast::ident,
tps: ~[ast::ty_param], generics: &ast::Generics,
body: @ast::expr body: @ast::expr
) -> @ast::item { ) -> @ast::item {
// Make a path to the std::serialize::Decodable typaram. // Make a path to the std::serialize::Decodable typaram.
@ -526,7 +552,7 @@ fn mk_deser_impl(
cx.ident_of(~"Decoder"), cx.ident_of(~"Decoder"),
] ]
), ),
@~[] @opt_vec::Empty
); );
// Make a path to the std::serialize::Decodable trait. // Make a path to the std::serialize::Decodable trait.
@ -546,7 +572,7 @@ fn mk_deser_impl(
ident, ident,
ty_param, ty_param,
path, path,
tps, generics,
|ty| mk_deser_method(cx, span, ty, cx.expr_blk(body)) |ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
) )
} }
@ -601,7 +627,7 @@ fn mk_ser_method(
@ast::method { @ast::method {
ident: cx.ident_of(~"encode"), ident: cx.ident_of(~"encode"),
attrs: ~[], attrs: ~[],
tps: ~[], generics: ast_util::empty_generics(),
self_ty: codemap::spanned { node: ast::sty_region(ast::m_imm), self_ty: codemap::spanned { node: ast::sty_region(ast::m_imm),
span: span }, span: span },
purity: ast::impure_fn, purity: ast::impure_fn,
@ -659,7 +685,7 @@ fn mk_deser_method(
@ast::method { @ast::method {
ident: cx.ident_of(~"decode"), ident: cx.ident_of(~"decode"),
attrs: ~[], attrs: ~[],
tps: ~[], generics: ast_util::empty_generics(),
self_ty: codemap::spanned { node: ast::sty_static, span: span }, self_ty: codemap::spanned { node: ast::sty_static, span: span },
purity: ast::impure_fn, purity: ast::impure_fn,
decl: deser_decl, decl: deser_decl,
@ -676,7 +702,7 @@ fn mk_struct_ser_impl(
span: span, span: span,
ident: ast::ident, ident: ast::ident,
fields: &[@ast::struct_field], fields: &[@ast::struct_field],
tps: &[ast::ty_param] generics: &ast::Generics
) -> @ast::item { ) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| { let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| self.$(name).encode(__s)` // ast for `|| self.$(name).encode(__s)`
@ -729,7 +755,7 @@ fn mk_struct_ser_impl(
] ]
); );
mk_ser_impl(cx, span, ident, tps, ser_body) mk_ser_impl(cx, span, ident, generics, ser_body)
} }
fn mk_struct_deser_impl( fn mk_struct_deser_impl(
@ -737,7 +763,7 @@ fn mk_struct_deser_impl(
span: span, span: span,
ident: ast::ident, ident: ast::ident,
fields: ~[@ast::struct_field], fields: ~[@ast::struct_field],
tps: ~[ast::ty_param] generics: &ast::Generics
) -> @ast::item { ) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| { let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| std::serialize::decode(__d)` // ast for `|| std::serialize::decode(__d)`
@ -805,7 +831,7 @@ fn mk_struct_deser_impl(
] ]
); );
mk_deser_impl(cx, span, ident, tps, body) mk_deser_impl(cx, span, ident, generics, body)
} }
// Records and structs don't have the same fields types, but they share enough // Records and structs don't have the same fields types, but they share enough
@ -841,7 +867,7 @@ fn mk_enum_ser_impl(
span: span, span: span,
ident: ast::ident, ident: ast::ident,
+enum_def: ast::enum_def, +enum_def: ast::enum_def,
tps: ~[ast::ty_param] generics: &ast::Generics
) -> @ast::item { ) -> @ast::item {
let body = mk_enum_ser_body( let body = mk_enum_ser_body(
cx, cx,
@ -850,7 +876,7 @@ fn mk_enum_ser_impl(
copy enum_def.variants copy enum_def.variants
); );
mk_ser_impl(cx, span, ident, tps, body) mk_ser_impl(cx, span, ident, generics, body)
} }
fn mk_enum_deser_impl( fn mk_enum_deser_impl(
@ -858,7 +884,7 @@ fn mk_enum_deser_impl(
span: span, span: span,
ident: ast::ident, ident: ast::ident,
+enum_def: ast::enum_def, +enum_def: ast::enum_def,
tps: ~[ast::ty_param] generics: &ast::Generics
) -> @ast::item { ) -> @ast::item {
let body = mk_enum_deser_body( let body = mk_enum_deser_body(
cx, cx,
@ -867,7 +893,7 @@ fn mk_enum_deser_impl(
enum_def.variants enum_def.variants
); );
mk_deser_impl(cx, span, ident, tps, body) mk_deser_impl(cx, span, ident, generics, body)
} }
fn ser_variant( fn ser_variant(

View file

@ -16,6 +16,9 @@ use codemap::span;
use ext::base::ext_ctxt; use ext::base::ext_ctxt;
use ext::build; use ext::build;
use opt_vec;
use opt_vec::OptVec;
use core::dvec; use core::dvec;
use core::option; use core::option;
@ -362,8 +365,14 @@ pub fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl {
} }
pub fn mk_ty_param(cx: ext_ctxt, pub fn mk_ty_param(cx: ext_ctxt,
ident: ast::ident, ident: ast::ident,
bounds: @~[ast::ty_param_bound]) bounds: @OptVec<ast::TyParamBound>)
-> ast::ty_param { -> ast::TyParam {
ast::ty_param { ident: ident, id: cx.next_id(), bounds: bounds } ast::TyParam { ident: ident, id: cx.next_id(), bounds: bounds }
}
pub fn mk_lifetime(cx: ext_ctxt,
span: span,
ident: ast::ident) -> ast::Lifetime
{
ast::Lifetime { id: cx.next_id(), span: span, ident: ident }
} }

View file

@ -16,15 +16,19 @@ use core::prelude::*;
use ast; use ast;
use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def}; use ast::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
use ast::{enum_variant_kind, expr, expr_match, ident, item, item_}; use ast::{enum_variant_kind, expr, expr_match, ident, item, item_};
use ast::{item_enum, item_impl, item_struct, m_imm, meta_item, method}; use ast::{item_enum, item_impl, item_struct, Generics};
use ast::{m_imm, meta_item, method};
use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn}; use ast::{named_field, or, pat, pat_ident, pat_wild, public, pure_fn};
use ast::{re_anon, stmt, struct_def, struct_variant_kind}; use ast::{re_anon, stmt, struct_def, struct_variant_kind};
use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, ty_param}; use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
use ast::{ty_param_bound, ty_path, ty_rptr, unnamed_field, variant}; use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
use ext::base::ext_ctxt; use ext::base::ext_ctxt;
use ext::build; use ext::build;
use codemap::{span, spanned}; use codemap::{span, spanned};
use parse::token::special_idents::clownshoes_extensions; use parse::token::special_idents::clownshoes_extensions;
use ast_util;
use opt_vec;
use opt_vec::OptVec;
use core::dvec; use core::dvec;
use core::uint; use core::uint;
@ -47,13 +51,13 @@ type ExpandDerivingStructDefFn = &fn(ext_ctxt,
span, span,
x: &struct_def, x: &struct_def,
ident, ident,
+y: ~[ty_param]) y: &Generics)
-> @item; -> @item;
type ExpandDerivingEnumDefFn = &fn(ext_ctxt, type ExpandDerivingEnumDefFn = &fn(ext_ctxt,
span, span,
x: &enum_def, x: &enum_def,
ident, ident,
+y: ~[ty_param]) y: &Generics)
-> @item; -> @item;
pub fn expand_deriving_eq(cx: ext_ctxt, pub fn expand_deriving_eq(cx: ext_ctxt,
@ -90,19 +94,19 @@ fn expand_deriving(cx: ext_ctxt,
for in_items.each |item| { for in_items.each |item| {
result.push(copy *item); result.push(copy *item);
match item.node { match item.node {
item_struct(struct_def, copy ty_params) => { item_struct(struct_def, ref generics) => {
result.push(expand_deriving_struct_def(cx, result.push(expand_deriving_struct_def(cx,
span, span,
struct_def, struct_def,
item.ident, item.ident,
ty_params)); generics));
} }
item_enum(ref enum_definition, copy ty_params) => { item_enum(ref enum_definition, ref generics) => {
result.push(expand_deriving_enum_def(cx, result.push(expand_deriving_enum_def(cx,
span, span,
enum_definition, enum_definition,
item.ident, item.ident,
ty_params)); generics));
} }
_ => () _ => ()
} }
@ -127,14 +131,14 @@ fn create_eq_method(cx: ext_ctxt,
span: span, span: span,
method_ident: ident, method_ident: ident,
type_ident: ident, type_ident: ident,
ty_params: &[ty_param], generics: &Generics,
body: @expr) body: @expr)
-> @method { -> @method {
// Create the type of the `other` parameter. // Create the type of the `other` parameter.
let arg_path_type = create_self_type_with_params(cx, let arg_path_type = create_self_type_with_params(cx,
span, span,
type_ident, type_ident,
ty_params); generics);
let arg_region = @ast::region { id: cx.next_id(), node: re_anon }; let arg_region = @ast::region { id: cx.next_id(), node: re_anon };
let arg_type = ty_rptr( let arg_type = ty_rptr(
arg_region, arg_region,
@ -171,7 +175,7 @@ fn create_eq_method(cx: ext_ctxt,
@ast::method { @ast::method {
ident: method_ident, ident: method_ident,
attrs: ~[], attrs: ~[],
tps: ~[], generics: ast_util::empty_generics(),
self_ty: self_ty, self_ty: self_ty,
purity: pure_fn, purity: pure_fn,
decl: fn_decl, decl: fn_decl,
@ -186,11 +190,11 @@ fn create_eq_method(cx: ext_ctxt,
fn create_self_type_with_params(cx: ext_ctxt, fn create_self_type_with_params(cx: ext_ctxt,
span: span, span: span,
type_ident: ident, type_ident: ident,
ty_params: &[ty_param]) generics: &Generics)
-> @Ty { -> @Ty {
// Create the type parameters on the `self` path. // Create the type parameters on the `self` path.
let self_ty_params = dvec::DVec(); let self_ty_params = dvec::DVec();
for ty_params.each |ty_param| { for generics.ty_params.each |ty_param| {
let self_ty_param = build::mk_simple_ty_path(cx, let self_ty_param = build::mk_simple_ty_path(cx,
span, span,
ty_param.ident); ty_param.ident);
@ -209,21 +213,34 @@ fn create_self_type_with_params(cx: ext_ctxt,
fn create_derived_impl(cx: ext_ctxt, fn create_derived_impl(cx: ext_ctxt,
span: span, span: span,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param], generics: &Generics,
methods: &[@method], methods: &[@method],
trait_path: &[ident]) trait_path: &[ident])
-> @item { -> @item {
/*!
*
* Given that we are deriving a trait `Tr` for a type `T<'a, ...,
* 'z, A, ..., Z>`, creates an impl like:
*
* impl<'a, ..., 'z, A:Tr, ..., Z: Tr> Tr for T<A, ..., Z> { ... }
*
* FIXME(#5090): Remove code duplication between this and the
* code in auto_encode.rs
*/
// Copy the lifetimes
let impl_lifetimes = generics.lifetimes.map(|l| {
build::mk_lifetime(cx, l.span, l.ident)
});
// Create the type parameters. // Create the type parameters.
let impl_ty_params = dvec::DVec(); let impl_ty_params = generics.ty_params.map(|ty_param| {
for ty_params.each |ty_param| {
let bound = build::mk_ty_path_global(cx, let bound = build::mk_ty_path_global(cx,
span, span,
trait_path.map(|x| *x)); trait_path.map(|x| *x));
let bounds = @~[ TraitTyParamBound(bound) ]; let bounds = @opt_vec::with(TraitTyParamBound(bound));
let impl_ty_param = build::mk_ty_param(cx, ty_param.ident, bounds); build::mk_ty_param(cx, ty_param.ident, bounds)
impl_ty_params.push(impl_ty_param); });
}
let impl_ty_params = dvec::unwrap(impl_ty_params);
// Create the reference to the trait. // Create the reference to the trait.
let trait_path = ast::path { let trait_path = ast::path {
@ -244,10 +261,11 @@ fn create_derived_impl(cx: ext_ctxt,
let self_type = create_self_type_with_params(cx, let self_type = create_self_type_with_params(cx,
span, span,
type_ident, type_ident,
ty_params); generics);
// Create the impl item. // Create the impl item.
let impl_item = item_impl(impl_ty_params, let impl_item = item_impl(Generics {lifetimes: impl_lifetimes,
ty_params: impl_ty_params},
Some(trait_ref), Some(trait_ref),
self_type, self_type,
methods.map(|x| *x)); methods.map(|x| *x));
@ -257,7 +275,7 @@ fn create_derived_impl(cx: ext_ctxt,
fn create_derived_eq_impl(cx: ext_ctxt, fn create_derived_eq_impl(cx: ext_ctxt,
span: span, span: span,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param], generics: &Generics,
eq_method: @method, eq_method: @method,
ne_method: @method) ne_method: @method)
-> @item { -> @item {
@ -267,13 +285,13 @@ fn create_derived_eq_impl(cx: ext_ctxt,
cx.ident_of(~"cmp"), cx.ident_of(~"cmp"),
cx.ident_of(~"Eq") cx.ident_of(~"Eq")
]; ];
create_derived_impl(cx, span, type_ident, ty_params, methods, trait_path) create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
} }
fn create_derived_iter_bytes_impl(cx: ext_ctxt, fn create_derived_iter_bytes_impl(cx: ext_ctxt,
span: span, span: span,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param], generics: &Generics,
method: @method) method: @method)
-> @item { -> @item {
let methods = [ method ]; let methods = [ method ];
@ -282,7 +300,7 @@ fn create_derived_iter_bytes_impl(cx: ext_ctxt,
cx.ident_of(~"to_bytes"), cx.ident_of(~"to_bytes"),
cx.ident_of(~"IterBytes") cx.ident_of(~"IterBytes")
]; ];
create_derived_impl(cx, span, type_ident, ty_params, methods, trait_path) create_derived_impl(cx, span, type_ident, generics, methods, trait_path)
} }
// Creates a method from the given set of statements conforming to the // Creates a method from the given set of statements conforming to the
@ -322,7 +340,7 @@ fn create_iter_bytes_method(cx: ext_ctxt,
@ast::method { @ast::method {
ident: method_ident, ident: method_ident,
attrs: ~[], attrs: ~[],
tps: ~[], generics: ast_util::empty_generics(),
self_ty: self_ty, self_ty: self_ty,
purity: pure_fn, purity: pure_fn,
decl: fn_decl, decl: fn_decl,
@ -484,7 +502,7 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
span: span, span: span,
struct_def: &struct_def, struct_def: &struct_def,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param]) generics: &Generics)
-> @item { -> @item {
// Create the methods. // Create the methods.
let eq_ident = cx.ident_of(~"eq"); let eq_ident = cx.ident_of(~"eq");
@ -510,21 +528,21 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
struct_def, struct_def,
eq_ident, eq_ident,
type_ident, type_ident,
ty_params, generics,
Conjunction); Conjunction);
let ne_method = derive_struct_fn(cx, let ne_method = derive_struct_fn(cx,
span, span,
struct_def, struct_def,
ne_ident, ne_ident,
type_ident, type_ident,
ty_params, generics,
Disjunction); Disjunction);
// Create the implementation. // Create the implementation.
return create_derived_eq_impl(cx, return create_derived_eq_impl(cx,
span, span,
type_ident, type_ident,
ty_params, generics,
eq_method, eq_method,
ne_method); ne_method);
} }
@ -533,7 +551,7 @@ fn expand_deriving_eq_enum_def(cx: ext_ctxt,
span: span, span: span,
enum_definition: &enum_def, enum_definition: &enum_def,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param]) generics: &Generics)
-> @item { -> @item {
// Create the methods. // Create the methods.
let eq_ident = cx.ident_of(~"eq"); let eq_ident = cx.ident_of(~"eq");
@ -543,21 +561,21 @@ fn expand_deriving_eq_enum_def(cx: ext_ctxt,
enum_definition, enum_definition,
eq_ident, eq_ident,
type_ident, type_ident,
ty_params, generics,
Conjunction); Conjunction);
let ne_method = expand_deriving_eq_enum_method(cx, let ne_method = expand_deriving_eq_enum_method(cx,
span, span,
enum_definition, enum_definition,
ne_ident, ne_ident,
type_ident, type_ident,
ty_params, generics,
Disjunction); Disjunction);
// Create the implementation. // Create the implementation.
return create_derived_eq_impl(cx, return create_derived_eq_impl(cx,
span, span,
type_ident, type_ident,
ty_params, generics,
eq_method, eq_method,
ne_method); ne_method);
} }
@ -566,7 +584,7 @@ fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
span: span, span: span,
struct_def: &struct_def, struct_def: &struct_def,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param]) generics: &Generics)
-> @item { -> @item {
// Create the method. // Create the method.
let method = expand_deriving_iter_bytes_struct_method(cx, let method = expand_deriving_iter_bytes_struct_method(cx,
@ -577,7 +595,7 @@ fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
return create_derived_iter_bytes_impl(cx, return create_derived_iter_bytes_impl(cx,
span, span,
type_ident, type_ident,
ty_params, generics,
method); method);
} }
@ -585,7 +603,7 @@ fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
span: span, span: span,
enum_definition: &enum_def, enum_definition: &enum_def,
type_ident: ident, type_ident: ident,
+ty_params: ~[ty_param]) generics: &Generics)
-> @item { -> @item {
// Create the method. // Create the method.
let method = expand_deriving_iter_bytes_enum_method(cx, let method = expand_deriving_iter_bytes_enum_method(cx,
@ -596,7 +614,7 @@ fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
return create_derived_iter_bytes_impl(cx, return create_derived_iter_bytes_impl(cx,
span, span,
type_ident, type_ident,
ty_params, generics,
method); method);
} }
@ -605,7 +623,7 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
struct_def: &struct_def, struct_def: &struct_def,
method_ident: ident, method_ident: ident,
type_ident: ident, type_ident: ident,
ty_params: &[ty_param], generics: &Generics,
junction: Junction) junction: Junction)
-> @method { -> @method {
let self_ident = cx.ident_of(~"self"); let self_ident = cx.ident_of(~"self");
@ -652,7 +670,7 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
span, span,
method_ident, method_ident,
type_ident, type_ident,
ty_params, generics,
body); body);
} }
@ -696,7 +714,7 @@ fn expand_deriving_eq_enum_method(cx: ext_ctxt,
enum_definition: &enum_def, enum_definition: &enum_def,
method_ident: ident, method_ident: ident,
type_ident: ident, type_ident: ident,
ty_params: &[ty_param], generics: &Generics,
junction: Junction) junction: Junction)
-> @method { -> @method {
let self_ident = cx.ident_of(~"self"); let self_ident = cx.ident_of(~"self");
@ -823,7 +841,7 @@ fn expand_deriving_eq_enum_method(cx: ext_ctxt,
span, span,
method_ident, method_ident,
type_ident, type_ident,
ty_params, generics,
self_match_expr); self_match_expr);
} }
@ -832,7 +850,7 @@ fn expand_deriving_eq_struct_tuple_method(cx: ext_ctxt,
struct_def: &struct_def, struct_def: &struct_def,
method_ident: ident, method_ident: ident,
type_ident: ident, type_ident: ident,
ty_params: &[ty_param], generics: &Generics,
junction: Junction) junction: Junction)
-> @method { -> @method {
let self_str = ~"self"; let self_str = ~"self";
@ -883,7 +901,7 @@ fn expand_deriving_eq_struct_tuple_method(cx: ext_ctxt,
let self_match_expr = build::mk_expr(cx, span, self_match_expr); let self_match_expr = build::mk_expr(cx, span, self_match_expr);
create_eq_method(cx, span, method_ident, create_eq_method(cx, span, method_ident,
type_ident, ty_params, self_match_expr) type_ident, generics, self_match_expr)
} }
fn expand_deriving_iter_bytes_enum_method(cx: ext_ctxt, fn expand_deriving_iter_bytes_enum_method(cx: ext_ctxt,

View file

@ -583,13 +583,17 @@ mod test {
// make a "meta_word" outer attribute with the given name // make a "meta_word" outer attribute with the given name
fn make_dummy_attr(s: @~str) -> ast::attribute { fn make_dummy_attr(s: @~str) -> ast::attribute {
spanned {span:codemap::dummy_sp(), spanned {
node: attribute_ span:codemap::dummy_sp(),
{style:attr_outer, node: attribute_ {
value:spanned style: attr_outer,
{node:meta_word(s), value: @spanned {
span:codemap::dummy_sp()}, node: meta_word(s),
is_sugared_doc:false}} span: codemap::dummy_sp(),
},
is_sugared_doc: false,
}
}
} }
} }

View file

@ -24,6 +24,8 @@ use codemap::{span, respan, dummy_sp};
use codemap; use codemap;
use ext::base::{ext_ctxt, mk_ctxt}; use ext::base::{ext_ctxt, mk_ctxt};
use ext::quote::rt::*; use ext::quote::rt::*;
use opt_vec;
use opt_vec::OptVec;
use core::vec; use core::vec;
@ -71,50 +73,61 @@ impl append_types for @ast::path {
} }
pub trait ext_ctxt_ast_builder { pub trait ext_ctxt_ast_builder {
fn ty_param(&self, id: ast::ident, +bounds: ~[ast::ty_param_bound]) fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-> ast::ty_param; -> ast::TyParam;
fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg; fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg;
fn expr_block(&self, e: @ast::expr) -> ast::blk; fn expr_block(&self, e: @ast::expr) -> ast::blk;
fn fn_decl(&self, +inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; fn fn_decl(&self, +inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
fn item(&self, name: ident, span: span, +node: ast::item_) -> @ast::item; fn item(&self, name: ident, span: span, +node: ast::item_) -> @ast::item;
fn item_fn_poly(&self, fn item_fn_poly(&self,
name: ident, ame: ident,
+inputs: ~[ast::arg], +inputs: ~[ast::arg],
output: @ast::Ty, output: @ast::Ty,
+ty_params: ~[ast::ty_param], +generics: Generics,
+body: ast::blk) -> @ast::item; +body: ast::blk) -> @ast::item;
fn item_fn(&self, fn item_fn(&self,
name: ident, name: ident,
+inputs: ~[ast::arg], +inputs: ~[ast::arg],
output: @ast::Ty, output: @ast::Ty,
+body: ast::blk) -> @ast::item; +body: ast::blk) -> @ast::item;
fn item_enum_poly(&self, fn item_enum_poly(&self,
name: ident, name: ident,
span: span, span: span,
+enum_definition: ast::enum_def, +enum_definition: ast::enum_def,
+ty_params: ~[ast::ty_param]) -> @ast::item; +generics: Generics) -> @ast::item;
fn item_enum(&self, name: ident, span: span, fn item_enum(&self,
name: ident,
span: span,
+enum_definition: ast::enum_def) -> @ast::item; +enum_definition: ast::enum_def) -> @ast::item;
fn item_struct_poly(&self, fn item_struct_poly(&self,
name: ident, span: span, name: ident,
+struct_def: ast::struct_def, span: span,
+ty_params: ~[ast::ty_param]) -> @ast::item; +struct_def: ast::struct_def,
fn item_struct(&self, name: ident, span: span, +generics: Generics) -> @ast::item;
fn item_struct(&self,
name: ident,
span: span,
+struct_def: ast::struct_def) -> @ast::item; +struct_def: ast::struct_def) -> @ast::item;
fn struct_expr(&self, path: @ast::path, fn struct_expr(&self,
path: @ast::path,
+fields: ~[ast::field]) -> @ast::expr; +fields: ~[ast::field]) -> @ast::expr;
fn variant(&self, name: ident, span: span, fn variant(&self,
name: ident,
span: span,
+tys: ~[@ast::Ty]) -> ast::variant; +tys: ~[@ast::Ty]) -> ast::variant;
fn item_mod(&self, name: ident, span: span, fn item_mod(&self,
name: ident,
span: span,
+items: ~[@ast::item]) -> @ast::item; +items: ~[@ast::item]) -> @ast::item;
fn ty_path_ast_builder(&self, path: @ast::path) -> @ast::Ty; fn ty_path_ast_builder(&self, path: @ast::path) -> @ast::Ty;
fn item_ty_poly(&self, name: ident, fn item_ty_poly(&self,
name: ident,
span: span, span: span,
ty: @ast::Ty, ty: @ast::Ty,
+params: ~[ast::ty_param]) -> @ast::item; +generics: Generics) -> @ast::item;
fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item; fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item;
fn ty_vars(&self, ty_params: &[ast::ty_param]) -> ~[@ast::Ty]; fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
fn ty_vars_global(&self, ty_params: &[ast::ty_param]) -> ~[@ast::Ty]; fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field; fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field;
fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field; fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field;
fn block(&self, +stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; fn block(&self, +stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
@ -124,7 +137,7 @@ pub trait ext_ctxt_ast_builder {
fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty; fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty;
fn ty_infer(&self) -> @ast::Ty; fn ty_infer(&self) -> @ast::Ty;
fn ty_nil_ast_builder(&self) -> @ast::Ty; fn ty_nil_ast_builder(&self) -> @ast::Ty;
fn strip_bounds(&self, bounds: &[ast::ty_param]) -> ~[ast::ty_param]; fn strip_bounds(&self, bounds: &Generics) -> Generics;
} }
impl ext_ctxt_ast_builder for ext_ctxt { impl ext_ctxt_ast_builder for ext_ctxt {
@ -180,10 +193,10 @@ impl ext_ctxt_ast_builder for ext_ctxt {
} }
} }
fn ty_param(&self, id: ast::ident, +bounds: ~[ast::ty_param_bound]) fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-> ast::ty_param -> ast::TyParam
{ {
ast::ty_param { ident: id, id: self.next_id(), bounds: @bounds } ast::TyParam { ident: id, id: self.next_id(), bounds: bounds }
} }
fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg { fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg {
@ -255,43 +268,64 @@ impl ext_ctxt_ast_builder for ext_ctxt {
fn item_fn_poly(&self, name: ident, fn item_fn_poly(&self, name: ident,
+inputs: ~[ast::arg], +inputs: ~[ast::arg],
output: @ast::Ty, output: @ast::Ty,
+ty_params: ~[ast::ty_param], +generics: Generics,
+body: ast::blk) -> @ast::item { +body: ast::blk) -> @ast::item {
self.item(name, self.item(name,
dummy_sp(), dummy_sp(),
ast::item_fn(self.fn_decl(inputs, output), ast::item_fn(self.fn_decl(inputs, output),
ast::impure_fn, ast::impure_fn,
ty_params, generics,
body)) body))
} }
fn item_fn(&self, name: ident, fn item_fn(&self,
name: ident,
+inputs: ~[ast::arg], +inputs: ~[ast::arg],
output: @ast::Ty, output: @ast::Ty,
+body: ast::blk) -> @ast::item { +body: ast::blk
self.item_fn_poly(name, inputs, output, ~[], body) ) -> @ast::item {
self.item_fn_poly(
name,
inputs,
output,
ast_util::empty_generics(),
body
)
} }
fn item_enum_poly(&self, name: ident, span: span, fn item_enum_poly(&self, name: ident, span: span,
+enum_definition: ast::enum_def, +enum_definition: ast::enum_def,
+ty_params: ~[ast::ty_param]) -> @ast::item { +generics: Generics) -> @ast::item {
self.item(name, span, ast::item_enum(enum_definition, ty_params)) self.item(name, span, ast::item_enum(enum_definition, generics))
} }
fn item_enum(&self, name: ident, span: span, fn item_enum(&self, name: ident, span: span,
+enum_definition: ast::enum_def) -> @ast::item { +enum_definition: ast::enum_def) -> @ast::item {
self.item_enum_poly(name, span, enum_definition, ~[]) self.item_enum_poly(name, span, enum_definition,
ast_util::empty_generics())
} }
fn item_struct(&self, name: ident, span: span, fn item_struct(
+struct_def: ast::struct_def) -> @ast::item { &self, name: ident,
self.item_struct_poly(name, span, struct_def, ~[]) span: span,
+struct_def: ast::struct_def
) -> @ast::item {
self.item_struct_poly(
name,
span,
struct_def,
ast_util::empty_generics()
)
} }
fn item_struct_poly(&self, name: ident, span: span, fn item_struct_poly(
+struct_def: ast::struct_def, &self,
+ty_params: ~[ast::ty_param]) -> @ast::item { name: ident,
self.item(name, span, ast::item_struct(@struct_def, ty_params)) span: span,
+struct_def: ast::struct_def,
+generics: Generics
) -> @ast::item {
self.item(name, span, ast::item_struct(@struct_def, generics))
} }
fn struct_expr(&self, path: @ast::path, fn struct_expr(&self, path: @ast::path,
@ -379,28 +413,34 @@ impl ext_ctxt_ast_builder for ext_ctxt {
} }
} }
fn strip_bounds(&self, bounds: &[ast::ty_param]) -> ~[ast::ty_param] { fn strip_bounds(&self, generics: &Generics) -> Generics {
do bounds.map |ty_param| { let no_bounds = @opt_vec::Empty;
ast::ty_param { bounds: @~[], ..copy *ty_param } let new_params = do generics.ty_params.map |ty_param| {
ast::TyParam { bounds: no_bounds, ..copy *ty_param }
};
Generics {
ty_params: new_params,
.. copy *generics
} }
} }
fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty, fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty,
+params: ~[ast::ty_param]) -> @ast::item { +generics: Generics) -> @ast::item {
self.item(name, span, ast::item_ty(ty, params)) self.item(name, span, ast::item_ty(ty, generics))
} }
fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item { fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item {
self.item_ty_poly(name, span, ty, ~[]) self.item_ty_poly(name, span, ty, ast_util::empty_generics())
} }
fn ty_vars(&self, +ty_params: &[ast::ty_param]) -> ~[@ast::Ty] { fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
ty_params.map(|p| self.ty_path_ast_builder( ty_params.map(|p| self.ty_path_ast_builder(
path(~[p.ident], dummy_sp()))) path(~[p.ident], dummy_sp()))).to_vec()
} }
fn ty_vars_global(&self, ty_params: &[ast::ty_param]) -> ~[@ast::Ty] { fn ty_vars_global(&self,
ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
ty_params.map(|p| self.ty_path_ast_builder( ty_params.map(|p| self.ty_path_ast_builder(
path(~[p.ident], dummy_sp()))) path(~[p.ident], dummy_sp()))).to_vec()
} }
} }

View file

@ -67,13 +67,13 @@ impl proto::visitor<(), (), ()> for ext_ctxt {
else { else {
let next = proto.get_state(next_state.state); let next = proto.get_state(next_state.state);
if next.ty_params.len() != next_state.tys.len() { if next.generics.ty_params.len() != next_state.tys.len() {
self.span_err( self.span_err(
next.span, // use a real span next.span, // use a real span
fmt!("message %s target (%s) \ fmt!("message %s target (%s) \
needs %u type parameters, but got %u", needs %u type parameters, but got %u",
name, next.name, name, next.name,
next.ty_params.len(), next.generics.ty_params.len(),
next_state.tys.len())); next_state.tys.len()));
} }
} }

View file

@ -55,13 +55,13 @@ impl proto_parser for parser::Parser {
_ => fail!() _ => fail!()
}; };
let typarms = if *self.token == token::LT { let generics = if *self.token == token::LT {
self.parse_ty_params() self.parse_generics()
} else { } else {
~[] ast_util::empty_generics()
}; };
let state = proto.add_state_poly(name, id, dir, typarms); let state = proto.add_state_poly(name, id, dir, generics);
// parse the messages // parse the messages
self.parse_unspanned_seq( self.parse_unspanned_seq(

View file

@ -19,6 +19,8 @@ use ext::pipes::proto::*;
use ext::quote::rt::*; use ext::quote::rt::*;
use parse::*; use parse::*;
use util::interner; use util::interner;
use opt_vec;
use opt_vec::OptVec;
use core::dvec::DVec; use core::dvec::DVec;
use core::prelude::*; use core::prelude::*;
@ -50,19 +52,18 @@ impl gen_send for message {
fn gen_send(&mut self, cx: ext_ctxt, try: bool) -> @ast::item { fn gen_send(&mut self, cx: ext_ctxt, try: bool) -> @ast::item {
debug!("pipec: gen_send"); debug!("pipec: gen_send");
let name = self.name(); let name = self.name();
let params = self.get_params();
match *self { match *self {
message(ref _id, span, ref tys, this, Some(ref next_state)) => { message(ref _id, span, ref tys, this, Some(ref next_state)) => {
debug!("pipec: next state exists"); debug!("pipec: next state exists");
let next = this.proto.get_state(next_state.state); let next = this.proto.get_state(next_state.state);
assert next_state.tys.len() == next.ty_params.len(); assert next_state.tys.len() == next.generics.ty_params.len();
let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str())); let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
let args_ast = vec::map2(arg_names, *tys, |n, t| cx.arg(*n, *t)); let args_ast = vec::map2(arg_names, *tys, |n, t| cx.arg(*n, *t));
let pipe_ty = cx.ty_path_ast_builder( let pipe_ty = cx.ty_path_ast_builder(
path(~[this.data_name()], span) path(~[this.data_name()], span)
.add_tys(cx.ty_vars_global(this.ty_params))); .add_tys(cx.ty_vars_global(&this.generics.ty_params)));
let args_ast = vec::append( let args_ast = vec::append(
~[cx.arg(cx.ident_of(~"pipe"), ~[cx.arg(cx.ident_of(~"pipe"),
pipe_ty)], pipe_ty)],
@ -128,7 +129,7 @@ impl gen_send for message {
cx.item_fn_poly(name, cx.item_fn_poly(name,
args_ast, args_ast,
rty, rty,
params, self.get_generics(),
cx.expr_block(body)) cx.expr_block(body))
} }
@ -142,10 +143,10 @@ impl gen_send for message {
let args_ast = vec::append( let args_ast = vec::append(
~[cx.arg(cx.ident_of(~"pipe"), ~[cx.arg(cx.ident_of(~"pipe"),
cx.ty_path_ast_builder( cx.ty_path_ast_builder(
path(~[this.data_name()], span) path(~[this.data_name()], span)
.add_tys(cx.ty_vars_global( .add_tys(cx.ty_vars_global(
this.ty_params))))], &this.generics.ty_params))))],
args_ast); args_ast);
let message_args = if arg_names.len() == 0 { let message_args = if arg_names.len() == 0 {
@ -183,7 +184,7 @@ impl gen_send for message {
} else { } else {
cx.ty_nil_ast_builder() cx.ty_nil_ast_builder()
}, },
params, self.get_generics(),
cx.expr_block(body)) cx.expr_block(body))
} }
} }
@ -191,7 +192,7 @@ impl gen_send for message {
fn to_ty(&mut self, cx: ext_ctxt) -> @ast::Ty { fn to_ty(&mut self, cx: ext_ctxt) -> @ast::Ty {
cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span()) cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
.add_tys(cx.ty_vars_global(self.get_params()))) .add_tys(cx.ty_vars_global(&self.get_generics().ty_params)))
} }
} }
@ -242,7 +243,7 @@ impl to_type_decls for state {
ast::enum_def(enum_def_ { ast::enum_def(enum_def_ {
variants: items_msg, variants: items_msg,
common: None }), common: None }),
cx.strip_bounds(self.ty_params) cx.strip_bounds(&self.generics)
) )
] ]
} }
@ -280,8 +281,9 @@ impl to_type_decls for state {
path(~[cx.ident_of(~"super"), path(~[cx.ident_of(~"super"),
self.data_name()], self.data_name()],
dummy_sp()) dummy_sp())
.add_tys(cx.ty_vars_global(self.ty_params))))), .add_tys(cx.ty_vars_global(
cx.strip_bounds(self.ty_params))); &self.generics.ty_params))))),
cx.strip_bounds(&self.generics)));
} }
else { else {
items.push( items.push(
@ -298,9 +300,10 @@ impl to_type_decls for state {
path(~[cx.ident_of(~"super"), path(~[cx.ident_of(~"super"),
self.data_name()], self.data_name()],
dummy_sp()) dummy_sp())
.add_tys(cx.ty_vars_global(self.ty_params))), .add_tys(cx.ty_vars_global(
&self.generics.ty_params))),
self.proto.buffer_ty_path(cx)])), self.proto.buffer_ty_path(cx)])),
cx.strip_bounds(self.ty_params))); cx.strip_bounds(&self.generics)));
}; };
items items
} }
@ -339,7 +342,7 @@ impl gen_init for protocol {
cx.parse_item(fmt!("pub fn init%s() -> (client::%s, server::%s)\ cx.parse_item(fmt!("pub fn init%s() -> (client::%s, server::%s)\
{ use core::pipes::HasBuffer; %s }", { use core::pipes::HasBuffer; %s }",
start_state.ty_params.to_source(cx), start_state.generics.to_source(cx),
start_state.to_ty(cx).to_source(cx), start_state.to_ty(cx).to_source(cx),
start_state.to_ty(cx).to_source(cx), start_state.to_ty(cx).to_source(cx),
body.to_source(cx))) body.to_source(cx)))
@ -384,9 +387,9 @@ impl gen_init for protocol {
} }
fn buffer_ty_path(&self, cx: ext_ctxt) -> @ast::Ty { fn buffer_ty_path(&self, cx: ext_ctxt) -> @ast::Ty {
let mut params: ~[ast::ty_param] = ~[]; let mut params: OptVec<ast::TyParam> = opt_vec::Empty;
for (copy self.states).each |s| { for (copy self.states).each |s| {
for s.ty_params.each |tp| { for s.generics.ty_params.each |tp| {
match params.find(|tpp| tp.ident == tpp.ident) { match params.find(|tpp| tp.ident == tpp.ident) {
None => params.push(*tp), None => params.push(*tp),
_ => () _ => ()
@ -397,19 +400,20 @@ impl gen_init for protocol {
cx.ty_path_ast_builder(path(~[cx.ident_of(~"super"), cx.ty_path_ast_builder(path(~[cx.ident_of(~"super"),
cx.ident_of(~"__Buffer")], cx.ident_of(~"__Buffer")],
copy self.span) copy self.span)
.add_tys(cx.ty_vars_global(params))) .add_tys(cx.ty_vars_global(&params)))
} }
fn gen_buffer_type(&self, cx: ext_ctxt) -> @ast::item { fn gen_buffer_type(&self, cx: ext_ctxt) -> @ast::item {
let ext_cx = cx; let ext_cx = cx;
let mut params: ~[ast::ty_param] = ~[]; let mut params: OptVec<ast::TyParam> = opt_vec::Empty;
let fields = do (copy self.states).map_to_vec |s| { let fields = do (copy self.states).map_to_vec |s| {
for s.ty_params.each |tp| { for s.generics.ty_params.each |tp| {
match params.find(|tpp| tp.ident == tpp.ident) { match params.find(|tpp| tp.ident == tpp.ident) {
None => params.push(*tp), None => params.push(*tp),
_ => () _ => ()
} }
} }
let ty = s.to_ty(cx); let ty = s.to_ty(cx);
let fty = quote_ty!( ::core::pipes::Packet<$ty> ); let fty = quote_ty!( ::core::pipes::Packet<$ty> );
@ -426,6 +430,11 @@ impl gen_init for protocol {
} }
}; };
let generics = Generics {
lifetimes: opt_vec::Empty,
ty_params: params
};
cx.item_struct_poly( cx.item_struct_poly(
cx.ident_of(~"__Buffer"), cx.ident_of(~"__Buffer"),
dummy_sp(), dummy_sp(),
@ -434,7 +443,7 @@ impl gen_init for protocol {
dtor: None, dtor: None,
ctor_id: None ctor_id: None
}, },
cx.strip_bounds(params)) cx.strip_bounds(&generics))
} }
fn compile(&self, cx: ext_ctxt) -> @ast::item { fn compile(&self, cx: ext_ctxt) -> @ast::item {

View file

@ -61,9 +61,9 @@ pub impl message {
} }
/// Return the type parameters actually used by this message /// Return the type parameters actually used by this message
fn get_params(&mut self) -> ~[ast::ty_param] { fn get_generics(&self) -> ast::Generics {
match *self { match *self {
message(_, _, _, this, _) => copy this.ty_params message(_, _, _, this, _) => copy this.generics
} }
} }
} }
@ -76,7 +76,7 @@ pub struct state_ {
ident: ast::ident, ident: ast::ident,
span: span, span: span,
dir: direction, dir: direction,
ty_params: ~[ast::ty_param], generics: ast::Generics,
messages: @mut ~[message], messages: @mut ~[message],
proto: protocol proto: protocol
} }
@ -100,7 +100,7 @@ pub impl state_ {
fn to_ty(&self, cx: ext_ctxt) -> @ast::Ty { fn to_ty(&self, cx: ext_ctxt) -> @ast::Ty {
cx.ty_path_ast_builder cx.ty_path_ast_builder
(path(~[cx.ident_of(self.name)],self.span).add_tys( (path(~[cx.ident_of(self.name)],self.span).add_tys(
cx.ty_vars(self.ty_params))) cx.ty_vars(&self.generics.ty_params)))
} }
/// Iterate over the states that can be reached in one message /// Iterate over the states that can be reached in one message
@ -161,7 +161,7 @@ pub impl protocol_ {
fn has_ty_params(&mut self) -> bool { fn has_ty_params(&mut self) -> bool {
for self.states.each |s| { for self.states.each |s| {
if s.ty_params.len() > 0 { if s.generics.ty_params.len() > 0 {
return true; return true;
} }
} }
@ -175,7 +175,7 @@ pub impl protocol_ {
pub impl protocol { pub impl protocol {
fn add_state_poly(&self, +name: ~str, ident: ast::ident, dir: direction, fn add_state_poly(&self, +name: ~str, ident: ast::ident, dir: direction,
+ty_params: ~[ast::ty_param]) -> state { +generics: ast::Generics) -> state {
let messages = @mut ~[]; let messages = @mut ~[];
let state = @state_ { let state = @state_ {
@ -184,7 +184,7 @@ pub impl protocol {
ident: ident, ident: ident,
span: self.span, span: self.span,
dir: dir, dir: dir,
ty_params: ty_params, generics: generics,
messages: messages, messages: messages,
proto: *self proto: *self
}; };

View file

@ -50,12 +50,12 @@ pub mod rt {
use print::pprust::{item_to_str, ty_to_str}; use print::pprust::{item_to_str, ty_to_str};
trait ToTokens { trait ToTokens {
pub fn to_tokens(_cx: ext_ctxt) -> ~[token_tree]; pub fn to_tokens(&self, _cx: ext_ctxt) -> ~[token_tree];
} }
impl ToTokens for ~[token_tree] { impl ToTokens for ~[token_tree] {
pub fn to_tokens(_cx: ext_ctxt) -> ~[token_tree] { pub fn to_tokens(&self, _cx: ext_ctxt) -> ~[token_tree] {
copy self copy *self
} }
} }
@ -75,91 +75,91 @@ pub mod rt {
trait ToSource { trait ToSource {
// Takes a thing and generates a string containing rust code for it. // Takes a thing and generates a string containing rust code for it.
pub fn to_source(cx: ext_ctxt) -> ~str; pub fn to_source(&self, cx: ext_ctxt) -> ~str;
} }
impl ToSource for ast::ident { impl ToSource for ast::ident {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
copy *cx.parse_sess().interner.get(self) copy *cx.parse_sess().interner.get(*self)
} }
} }
impl ToSource for @ast::item { impl ToSource for @ast::item {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
item_to_str(self, cx.parse_sess().interner) item_to_str(*self, cx.parse_sess().interner)
} }
} }
impl ToSource for ~[@ast::item] { impl ToSource for ~[@ast::item] {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
str::connect(self.map(|i| i.to_source(cx)), ~"\n\n") str::connect(self.map(|i| i.to_source(cx)), ~"\n\n")
} }
} }
impl ToSource for @ast::Ty { impl ToSource for @ast::Ty {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
ty_to_str(self, cx.parse_sess().interner) ty_to_str(*self, cx.parse_sess().interner)
} }
} }
impl ToSource for ~[@ast::Ty] { impl ToSource for ~[@ast::Ty] {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
str::connect(self.map(|i| i.to_source(cx)), ~", ") str::connect(self.map(|i| i.to_source(cx)), ~", ")
} }
} }
impl ToSource for ~[ast::ty_param] { impl ToSource for Generics {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
pprust::typarams_to_str(self, cx.parse_sess().interner) pprust::generics_to_str(self, cx.parse_sess().interner)
} }
} }
impl ToSource for @ast::expr { impl ToSource for @ast::expr {
fn to_source(cx: ext_ctxt) -> ~str { fn to_source(&self, cx: ext_ctxt) -> ~str {
pprust::expr_to_str(self, cx.parse_sess().interner) pprust::expr_to_str(*self, cx.parse_sess().interner)
} }
} }
// Alas ... we write these out instead. All redundant. // Alas ... we write these out instead. All redundant.
impl ToTokens for ast::ident { impl ToTokens for ast::ident {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for @ast::item { impl ToTokens for @ast::item {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for ~[@ast::item] { impl ToTokens for ~[@ast::item] {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for @ast::Ty { impl ToTokens for @ast::Ty {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for ~[@ast::Ty] { impl ToTokens for ~[@ast::Ty] {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for ~[ast::ty_param] { impl ToTokens for Generics {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }
impl ToTokens for @ast::expr { impl ToTokens for @ast::expr {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] { fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx)) cx.parse_tts(self.to_source(cx))
} }
} }

View file

@ -119,19 +119,27 @@ pub fn expand_include_bin(cx: ext_ctxt, sp: span, tts: &[ast::token_tree])
// recur along an ExpnInfo chain to find the original expression // recur along an ExpnInfo chain to find the original expression
fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo { fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo {
let ExpandedFrom(CallInfo { call_site, _ }) = *expn_info; match *expn_info {
match call_site.expn_info { ExpandedFrom(CallInfo { call_site: ref call_site, _ }) => {
Some(next_expn_info) => { match call_site.expn_info {
let ExpandedFrom(CallInfo { Some(next_expn_info) => {
callee: NameAndSpan {name, _}, match *next_expn_info {
_ ExpandedFrom(CallInfo {
}) = *next_expn_info; callee: NameAndSpan { name: ref name, _ },
// Don't recurse into file using "include!" _
if name == ~"include" { return expn_info; } }) => {
// Don't recurse into file using "include!"
topmost_expn_info(next_expn_info) if *name == ~"include" {
}, expn_info
None => expn_info } else {
topmost_expn_info(next_expn_info)
}
}
}
},
None => expn_info
}
}
} }
} }

View file

@ -132,26 +132,38 @@ pub fn fold_fn_decl(decl: &ast::fn_decl, fld: ast_fold) -> ast::fn_decl {
} }
} }
fn fold_ty_param_bound( fn fold_ty_param_bound(tpb: &TyParamBound, fld: ast_fold) -> TyParamBound {
tpb: &ty_param_bound,
fld: ast_fold
) -> ty_param_bound {
match *tpb { match *tpb {
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)), TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)),
RegionTyParamBound => RegionTyParamBound RegionTyParamBound => RegionTyParamBound
} }
} }
pub fn fold_ty_param(tp: &ty_param, fld: ast_fold) -> ty_param { pub fn fold_ty_param(tp: TyParam, fld: ast_fold) -> TyParam {
ast::ty_param { TyParam {ident: tp.ident,
ident: /* FIXME (#2543) */ copy tp.ident, id: fld.new_id(tp.id),
id: fld.new_id(tp.id), bounds: @tp.bounds.map(|x| fold_ty_param_bound(x, fld))}
bounds: @tp.bounds.map(|x| fold_ty_param_bound(x, fld)),
}
} }
pub fn fold_ty_params(tps: &[ty_param], fld: ast_fold) -> ~[ty_param] { pub fn fold_ty_params(tps: &OptVec<TyParam>,
tps.map(|x| fold_ty_param(x, fld)) fld: ast_fold) -> OptVec<TyParam> {
tps.map(|tp| fold_ty_param(*tp, fld))
}
pub fn fold_lifetime(l: &Lifetime, fld: ast_fold) -> Lifetime {
Lifetime {id: fld.new_id(l.id),
span: fld.new_span(l.span),
ident: l.ident}
}
pub fn fold_lifetimes(lts: &OptVec<Lifetime>,
fld: ast_fold) -> OptVec<Lifetime> {
lts.map(|l| fold_lifetime(l, fld))
}
pub fn fold_generics(generics: &Generics, fld: ast_fold) -> Generics {
Generics {ty_params: fold_ty_params(&generics.ty_params, fld),
lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
} }
pub fn noop_fold_crate(c: &crate_, fld: ast_fold) -> crate_ { pub fn noop_fold_crate(c: &crate_, fld: ast_fold) -> crate_ {
@ -180,7 +192,7 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: ast_fold)
attrs: ni.attrs.map(|x| fold_attribute(*x)), attrs: ni.attrs.map(|x| fold_attribute(*x)),
node: node:
match ni.node { match ni.node {
foreign_item_fn(ref fdec, purity, ref tps) => { foreign_item_fn(ref fdec, purity, ref generics) => {
foreign_item_fn( foreign_item_fn(
ast::fn_decl { ast::fn_decl {
inputs: fdec.inputs.map(|a| fold_arg(*a)), inputs: fdec.inputs.map(|a| fold_arg(*a)),
@ -188,7 +200,7 @@ fn noop_fold_foreign_item(ni: @foreign_item, fld: ast_fold)
cf: fdec.cf, cf: fdec.cf,
}, },
purity, purity,
fold_ty_params(*tps, fld)) fold_generics(generics, fld))
} }
foreign_item_const(t) => { foreign_item_const(t) => {
foreign_item_const(fld.fold_ty(t)) foreign_item_const(fld.fold_ty(t))
@ -221,14 +233,12 @@ fn noop_fold_struct_field(sf: @struct_field, fld: ast_fold)
pub fn noop_fold_item_underscore(i: &item_, fld: ast_fold) -> item_ { pub fn noop_fold_item_underscore(i: &item_, fld: ast_fold) -> item_ {
match *i { match *i {
item_const(t, e) => { item_const(t, e) => item_const(fld.fold_ty(t), fld.fold_expr(e)),
item_const(fld.fold_ty(t), fld.fold_expr(e)) item_fn(ref decl, purity, ref generics, ref body) => {
}
item_fn(ref decl, purity, ref tps, ref body) => {
item_fn( item_fn(
fold_fn_decl(decl, fld), fold_fn_decl(decl, fld),
purity, purity,
fold_ty_params(*tps, fld), fold_generics(generics, fld),
fld.fold_block(body) fld.fold_block(body)
) )
} }
@ -236,10 +246,10 @@ pub fn noop_fold_item_underscore(i: &item_, fld: ast_fold) -> item_ {
item_foreign_mod(ref nm) => { item_foreign_mod(ref nm) => {
item_foreign_mod(fld.fold_foreign_mod(nm)) item_foreign_mod(fld.fold_foreign_mod(nm))
} }
item_ty(t, ref tps) => { item_ty(t, ref generics) => {
item_ty(fld.fold_ty(t), fold_ty_params(*tps, fld)) item_ty(fld.fold_ty(t), fold_generics(generics, fld))
} }
item_enum(ref enum_definition, ref tps) => { item_enum(ref enum_definition, ref generics) => {
item_enum( item_enum(
ast::enum_def( ast::enum_def(
ast::enum_def_ { ast::enum_def_ {
@ -251,21 +261,21 @@ pub fn noop_fold_item_underscore(i: &item_, fld: ast_fold) -> item_ {
} }
} }
), ),
fold_ty_params(*tps, fld)) fold_generics(generics, fld))
} }
item_struct(ref struct_def, ref tps) => { item_struct(ref struct_def, ref generics) => {
let struct_def = fold_struct_def(*struct_def, fld); let struct_def = fold_struct_def(*struct_def, fld);
item_struct(struct_def, /* FIXME (#2543) */ copy *tps) item_struct(struct_def, /* FIXME (#2543) */ copy *generics)
} }
item_impl(ref tps, ifce, ty, ref methods) => { item_impl(ref generics, ifce, ty, ref methods) => {
item_impl( item_impl(
fold_ty_params(*tps, fld), fold_generics(generics, fld),
ifce.map(|p| fold_trait_ref(*p, fld)), ifce.map(|p| fold_trait_ref(*p, fld)),
fld.fold_ty(ty), fld.fold_ty(ty),
methods.map(|x| fld.fold_method(*x)) methods.map(|x| fld.fold_method(*x))
) )
} }
item_trait(ref tps, ref traits, ref methods) => { item_trait(ref generics, ref traits, ref methods) => {
let methods = do methods.map |method| { let methods = do methods.map |method| {
match *method { match *method {
required(*) => copy *method, required(*) => copy *method,
@ -273,7 +283,7 @@ pub fn noop_fold_item_underscore(i: &item_, fld: ast_fold) -> item_ {
} }
}; };
item_trait( item_trait(
fold_ty_params(*tps, fld), fold_generics(generics, fld),
traits.map(|p| fold_trait_ref(*p, fld)), traits.map(|p| fold_trait_ref(*p, fld)),
methods methods
) )
@ -328,7 +338,7 @@ fn noop_fold_method(m: @method, fld: ast_fold) -> @method {
@ast::method { @ast::method {
ident: fld.fold_ident(m.ident), ident: fld.fold_ident(m.ident),
attrs: /* FIXME (#2543) */ copy m.attrs, attrs: /* FIXME (#2543) */ copy m.attrs,
tps: fold_ty_params(m.tps, fld), generics: fold_generics(&m.generics, fld),
self_ty: m.self_ty, self_ty: m.self_ty,
purity: m.purity, purity: m.purity,
decl: fold_fn_decl(&m.decl, fld), decl: fold_fn_decl(&m.decl, fld),

187
src/libsyntax/opt_vec.rs Normal file
View file

@ -0,0 +1,187 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
*
* Defines a type OptVec<T> that can be used in place of ~[T].
* OptVec avoids the need for allocation for empty vectors.
* OptVec implements the iterable interface as well as
* other useful things like `push()` and `len()`.
*/
use core::prelude::*;
use core::iter;
use core::iter::BaseIter;
#[auto_encode]
#[auto_decode]
pub enum OptVec<T> {
Empty,
Vec(~[T])
}
pub fn with<T>(+t: T) -> OptVec<T> {
Vec(~[t])
}
impl<T> OptVec<T> {
fn push(&mut self, +t: T) {
match *self {
Vec(ref mut v) => {
v.push(t);
return;
}
Empty => {}
}
// FIXME(#5074): flow insensitive means we can't move
// assignment inside `match`
*self = Vec(~[t]);
}
fn map<U>(&self, op: &fn(&T) -> U) -> OptVec<U> {
match *self {
Empty => Empty,
Vec(ref v) => Vec(v.map(op))
}
}
pure fn get(&self, i: uint) -> &self/T {
match *self {
Empty => fail!(fmt!("Invalid index %u", i)),
Vec(ref v) => &v[i]
}
}
pure fn is_empty(&self) -> bool {
self.len() == 0
}
pure fn len(&self) -> uint {
match *self {
Empty => 0,
Vec(ref v) => v.len()
}
}
pure fn to_vec(self) -> ~[T] {
match self {
Empty => ~[],
Vec(v) => v
}
}
}
impl<T:Copy> OptVec<T> {
fn prepend(&self, +t: T) -> OptVec<T> {
let mut v0 = ~[t];
match *self {
Empty => {}
Vec(ref v1) => { v0.push_all(*v1); }
}
return Vec(v0);
}
fn push_all<I: BaseIter<T>>(&mut self, from: &I) {
for from.each |e| {
self.push(copy *e);
}
}
}
impl<A:Eq> Eq for OptVec<A> {
pure fn eq(&self, other: &OptVec<A>) -> bool {
// Note: cannot use #[deriving_eq] here because
// (Empty, Vec(~[])) ought to be equal.
match (self, other) {
(&Empty, &Empty) => true,
(&Empty, &Vec(ref v)) => v.is_empty(),
(&Vec(ref v), &Empty) => v.is_empty(),
(&Vec(ref v1), &Vec(ref v2)) => *v1 == *v2
}
}
pure fn ne(&self, other: &OptVec<A>) -> bool {
!self.eq(other)
}
}
impl<A> BaseIter<A> for OptVec<A> {
pure fn each(&self, blk: fn(v: &A) -> bool) {
match *self {
Empty => {}
Vec(ref v) => v.each(blk)
}
}
pure fn size_hint(&self) -> Option<uint> {
Some(self.len())
}
}
impl<A> iter::ExtendedIter<A> for OptVec<A> {
#[inline(always)]
pure fn eachi(&self, blk: fn(+v: uint, v: &A) -> bool) {
iter::eachi(self, blk)
}
#[inline(always)]
pure fn all(&self, blk: fn(&A) -> bool) -> bool {
iter::all(self, blk)
}
#[inline(always)]
pure fn any(&self, blk: fn(&A) -> bool) -> bool {
iter::any(self, blk)
}
#[inline(always)]
pure fn foldl<B>(&self, +b0: B, blk: fn(&B, &A) -> B) -> B {
iter::foldl(self, b0, blk)
}
#[inline(always)]
pure fn position(&self, f: fn(&A) -> bool) -> Option<uint> {
iter::position(self, f)
}
#[inline(always)]
pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B] {
iter::map_to_vec(self, op)
}
#[inline(always)]
pure fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: fn(&A) -> IB)
-> ~[B] {
iter::flat_map_to_vec(self, op)
}
}
impl<A: Eq> iter::EqIter<A> for OptVec<A> {
#[inline(always)]
pure fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
#[inline(always)]
pure fn count(&self, x: &A) -> uint { iter::count(self, x) }
}
impl<A: Copy> iter::CopyableIter<A> for OptVec<A> {
#[inline(always)]
pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A] {
iter::filter_to_vec(self, pred)
}
#[inline(always)]
pure fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
#[inline(always)]
pure fn find(&self, f: fn(&A) -> bool) -> Option<A> {
iter::find(self, f)
}
}
impl<A: Copy+Ord> iter::CopyableOrderedIter<A> for OptVec<A> {
#[inline(always)]
pure fn min(&self) -> A { iter::min(self) }
#[inline(always)]
pure fn max(&self) -> A { iter::max(self) }
}

View file

@ -20,6 +20,9 @@ use core::option::{None, Option, Some};
use core::option; use core::option;
use std::oldmap::HashMap; use std::oldmap::HashMap;
use opt_vec;
use opt_vec::OptVec;
// SeqSep : a sequence separator (token) // SeqSep : a sequence separator (token)
// and whether a trailing separator is allowed. // and whether a trailing separator is allowed.
pub struct SeqSep { pub struct SeqSep {
@ -251,9 +254,9 @@ pub impl Parser {
fn parse_seq_to_before_gt<T: Copy>( fn parse_seq_to_before_gt<T: Copy>(
sep: Option<token::Token>, sep: Option<token::Token>,
f: fn(&Parser) -> T f: fn(&Parser) -> T
) -> ~[T] { ) -> OptVec<T> {
let mut first = true; let mut first = true;
let mut v = ~[]; let mut v = opt_vec::Empty;
while *self.token != token::GT while *self.token != token::GT
&& *self.token != token::BINOP(token::SHR) { && *self.token != token::BINOP(token::SHR) {
match sep { match sep {
@ -265,33 +268,18 @@ pub impl Parser {
} }
v.push(f(&self)); v.push(f(&self));
} }
return v; return v;
} }
fn parse_seq_to_gt<T: Copy>( fn parse_seq_to_gt<T: Copy>(
sep: Option<token::Token>, sep: Option<token::Token>,
f: fn(&Parser) -> T f: fn(&Parser) -> T
) -> ~[T] { ) -> OptVec<T> {
let v = self.parse_seq_to_before_gt(sep, f); let v = self.parse_seq_to_before_gt(sep, f);
self.expect_gt(); self.expect_gt();
return v; return v;
} }
// parse a sequence bracketed by '<' and '>'
fn parse_seq_lt_gt<T: Copy>(
sep: Option<token::Token>,
f: fn(&Parser) -> T
) -> spanned<~[T]> {
let lo = self.span.lo;
self.expect(&token::LT);
let result = self.parse_seq_to_before_gt::<T>(sep, f);
let hi = self.span.hi;
self.expect_gt();
return spanned(lo, hi, result);
}
// parse a sequence, including the closing delimiter. The function // parse a sequence, including the closing delimiter. The function
// f must consume tokens until reaching the next separator or // f must consume tokens until reaching the next separator or
// closing bracket. // closing bracket.

View file

@ -51,7 +51,7 @@ use ast::{token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok};
use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box}; use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box};
use ast::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn}; use ast::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn};
use ast::{ty_infer, ty_mac, ty_method}; use ast::{ty_infer, ty_mac, ty_method};
use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr}; use ast::{ty_nil, TyParam, TyParamBound, ty_path, ty_ptr, ty_rec, ty_rptr};
use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq}; use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq};
use ast::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item}; use ast::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item};
use ast::{view_item_, view_item_extern_mod, view_item_use}; use ast::{view_item_, view_item_extern_mod, view_item_use};
@ -84,6 +84,8 @@ use parse::token;
use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
use print::pprust::expr_to_str; use print::pprust::expr_to_str;
use util::interner::Interner; use util::interner::Interner;
use opt_vec;
use opt_vec::OptVec;
use core::cmp; use core::cmp;
use core::either::{Either, Left, Right}; use core::either::{Either, Left, Right};
@ -458,7 +460,7 @@ pub impl Parser {
// could change. // could change.
let ident = p.parse_method_name(); let ident = p.parse_method_name();
let tps = p.parse_ty_params(); let generics = p.parse_generics();
let (self_ty, d) = do self.parse_fn_decl_with_self() |p| { let (self_ty, d) = do self.parse_fn_decl_with_self() |p| {
// This is somewhat dubious; We don't want to allow argument // This is somewhat dubious; We don't want to allow argument
@ -483,7 +485,7 @@ pub impl Parser {
attrs: attrs, attrs: attrs,
purity: pur, purity: pur,
decl: d, decl: d,
tps: tps, generics: generics,
self_ty: self_ty, self_ty: self_ty,
id: p.get_id(), id: p.get_id(),
span: mk_sp(lo, hi) span: mk_sp(lo, hi)
@ -497,7 +499,7 @@ pub impl Parser {
provided(@ast::method { provided(@ast::method {
ident: ident, ident: ident,
attrs: attrs, attrs: attrs,
tps: tps, generics: generics,
self_ty: self_ty, self_ty: self_ty,
purity: pur, purity: pur,
decl: d, decl: d,
@ -958,19 +960,7 @@ pub impl Parser {
}; };
// Parse any lifetime or type parameters which may appear: // Parse any lifetime or type parameters which may appear:
let tps = { let tps = self.parse_generic_values();
if !self.eat(&token::LT) {
~[]
} else {
// First consume lifetimes.
let _lifetimes = self.parse_lifetimes();
let result = self.parse_seq_to_gt(
Some(token::COMMA),
|p| p.parse_ty(false));
result
}
};
let hi = self.span.lo; let hi = self.span.lo;
@ast::path { span: mk_sp(lo, hi), @ast::path { span: mk_sp(lo, hi),
@ -1016,7 +1006,7 @@ pub impl Parser {
} }
} }
fn parse_lifetimes() -> ~[ast::Lifetime] { fn parse_lifetimes() -> OptVec<ast::Lifetime> {
/*! /*!
* *
* Parses zero or more comma separated lifetimes. * Parses zero or more comma separated lifetimes.
@ -1025,7 +1015,7 @@ pub impl Parser {
* lists, where we expect something like `<'a, 'b, T>`. * lists, where we expect something like `<'a, 'b, T>`.
*/ */
let mut res = ~[]; let mut res = opt_vec::Empty;
loop { loop {
match *self.token { match *self.token {
token::LIFETIME(_) => { token::LIFETIME(_) => {
@ -1201,7 +1191,7 @@ pub impl Parser {
&token::RBRACKET, &token::RBRACKET,
seq_sep_trailing_allowed(token::COMMA), seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_expr() |p| p.parse_expr()
); ).to_vec();
ex = expr_vec(~[first_expr] + remaining_exprs, mutbl); ex = expr_vec(~[first_expr] + remaining_exprs, mutbl);
} else { } else {
// Vector with one element. // Vector with one element.
@ -1335,10 +1325,7 @@ pub impl Parser {
self.bump(); self.bump();
let tys = if self.eat(&token::MOD_SEP) { let tys = if self.eat(&token::MOD_SEP) {
self.expect(&token::LT); self.expect(&token::LT);
self.parse_seq_to_gt( self.parse_generic_values_after_lt()
Some(token::COMMA),
|p| p.parse_ty(false)
)
} else { } else {
~[] ~[]
}; };
@ -1487,7 +1474,7 @@ pub impl Parser {
&ket, &ket,
seq_sep_none(), seq_sep_none(),
|p| p.parse_token_tree() |p| p.parse_token_tree()
), ).to_vec(),
// the close delimiter: // the close delimiter:
~[parse_any_tt_tok(&self)] ~[parse_any_tt_tok(&self)]
) )
@ -2719,82 +2706,103 @@ pub impl Parser {
if self.eat_keyword(&~"once") { ast::Once } else { ast::Many } if self.eat_keyword(&~"once") { ast::Once } else { ast::Many }
} }
fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] { fn parse_optional_ty_param_bounds() -> @OptVec<TyParamBound> {
let mut bounds = ~[]; if !self.eat(&token::COLON) {
if self.eat(&token::COLON) { return @opt_vec::Empty;
loop { }
if self.eat(&token::BINOP(token::AND)) {
if self.eat_keyword(&~"static") {
bounds.push(RegionTyParamBound);
} else {
self.span_err(*self.span,
~"`&static` is the only permissible \
region bound here");
}
} else if is_ident(&*self.token) {
let maybe_bound = match *self.token {
token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) {
~"send" let mut result = opt_vec::Empty;
| ~"copy" loop {
| ~"const" if self.eat(&token::BINOP(token::AND)) {
| ~"owned" => { if self.eat_keyword(&~"static") {
self.obsolete(*self.span, result.push(RegionTyParamBound);
ObsoleteLowerCaseKindBounds);
// Bogus value, but doesn't matter, since
// is an error
Some(TraitTyParamBound(self.mk_ty_path(sid)))
}
_ => None
}
}
_ => self.bug(
~"is_ident() said this would be an identifier")
};
match maybe_bound {
Some(bound) => {
self.bump();
bounds.push(bound);
}
None => {
let ty = self.parse_ty(false);
bounds.push(TraitTyParamBound(ty));
}
}
} else { } else {
break; self.span_err(*self.span,
~"`&static` is the only permissible \
region bound here");
} }
} else if is_ident(&*self.token) {
let maybe_bound = match *self.token {
token::IDENT(copy sid, _) => {
match *self.id_to_str(sid) {
~"send" |
~"copy" |
~"const" |
~"owned" => {
self.obsolete(
*self.span,
ObsoleteLowerCaseKindBounds);
if self.eat(&token::BINOP(token::PLUS)) { // Bogus value, but doesn't matter, since
loop; // is an error
} Some(TraitTyParamBound(
self.mk_ty_path(sid)))
}
_ => None
}
}
_ => fail!()
};
if is_ident_or_path(&*self.token) { match maybe_bound {
self.obsolete(*self.span, Some(bound) => {
ObsoleteTraitBoundSeparator); self.bump();
result.push(bound);
}
None => {
let ty = self.parse_ty(false);
result.push(TraitTyParamBound(ty));
}
} }
} else {
break;
}
if self.eat(&token::BINOP(token::PLUS)) {
loop;
}
if is_ident_or_path(&*self.token) {
self.obsolete(*self.span,
ObsoleteTraitBoundSeparator);
} }
} }
return @bounds;
return @result;
} }
fn parse_ty_param() -> ty_param { fn parse_ty_param() -> TyParam {
let ident = self.parse_ident(); let ident = self.parse_ident();
let bounds = self.parse_optional_ty_param_bounds(); let bounds = self.parse_optional_ty_param_bounds();
ast::ty_param { ident: ident, id: self.get_id(), bounds: bounds } ast::TyParam { ident: ident, id: self.get_id(), bounds: bounds }
} }
fn parse_ty_params() -> ~[ty_param] { fn parse_generics() -> ast::Generics {
if self.eat(&token::LT) { if self.eat(&token::LT) {
let _lifetimes = self.parse_lifetimes(); let lifetimes = self.parse_lifetimes();
self.parse_seq_to_gt( let ty_params = self.parse_seq_to_gt(
Some(token::COMMA), Some(token::COMMA),
|p| p.parse_ty_param() |p| p.parse_ty_param());
) ast::Generics { lifetimes: lifetimes, ty_params: ty_params }
} else { ~[] } } else {
ast_util::empty_generics()
}
}
fn parse_generic_values() -> ~[@Ty] {
if !self.eat(&token::LT) {
~[]
} else {
self.parse_generic_values_after_lt()
}
}
fn parse_generic_values_after_lt() -> ~[@Ty] {
let _lifetimes = self.parse_lifetimes();
let result = self.parse_seq_to_gt(
Some(token::COMMA),
|p| p.parse_ty(false));
result.to_vec()
} }
fn parse_fn_decl(parse_arg_fn: fn(&Parser) -> arg_or_capture_item) fn parse_fn_decl(parse_arg_fn: fn(&Parser) -> arg_or_capture_item)
@ -2896,7 +2904,7 @@ pub impl Parser {
&token::RPAREN, &token::RPAREN,
sep, sep,
parse_arg_fn parse_arg_fn
); ).to_vec();
} }
token::RPAREN => { token::RPAREN => {
args_or_capture_items = ~[]; args_or_capture_items = ~[];
@ -2916,7 +2924,7 @@ pub impl Parser {
&token::RPAREN, &token::RPAREN,
sep, sep,
parse_arg_fn parse_arg_fn
); ).to_vec();
} }
self.expect(&token::RPAREN); self.expect(&token::RPAREN);
@ -2961,10 +2969,10 @@ pub impl Parser {
} }
} }
fn parse_fn_header() -> (ident, ~[ty_param]) { fn parse_fn_header() -> (ident, ast::Generics) {
let id = self.parse_value_ident(); let id = self.parse_value_ident();
let ty_params = self.parse_ty_params(); let generics = self.parse_generics();
(id, ty_params) (id, generics)
} }
fn mk_item(+lo: BytePos, +hi: BytePos, +ident: ident, fn mk_item(+lo: BytePos, +hi: BytePos, +ident: ident,
@ -2979,10 +2987,10 @@ pub impl Parser {
} }
fn parse_item_fn(purity: purity) -> item_info { fn parse_item_fn(purity: purity) -> item_info {
let (ident, tps) = self.parse_fn_header(); let (ident, generics) = self.parse_fn_header();
let decl = self.parse_fn_decl(|p| p.parse_arg()); let decl = self.parse_fn_decl(|p| p.parse_arg());
let (inner_attrs, body) = self.parse_inner_attrs_and_block(true); let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
(ident, item_fn(decl, purity, tps, body), Some(inner_attrs)) (ident, item_fn(decl, purity, generics, body), Some(inner_attrs))
} }
fn parse_method_name() -> ident { fn parse_method_name() -> ident {
@ -2999,7 +3007,7 @@ pub impl Parser {
let visa = self.parse_visibility(); let visa = self.parse_visibility();
let pur = self.parse_fn_purity(); let pur = self.parse_fn_purity();
let ident = self.parse_method_name(); let ident = self.parse_method_name();
let tps = self.parse_ty_params(); let generics = self.parse_generics();
let (self_ty, decl) = do self.parse_fn_decl_with_self() |p| { let (self_ty, decl) = do self.parse_fn_decl_with_self() |p| {
p.parse_arg() p.parse_arg()
}; };
@ -3012,7 +3020,7 @@ pub impl Parser {
@ast::method { @ast::method {
ident: ident, ident: ident,
attrs: attrs, attrs: attrs,
tps: tps, generics: generics,
self_ty: self_ty, self_ty: self_ty,
purity: pur, purity: pur,
decl: decl, decl: decl,
@ -3027,7 +3035,7 @@ pub impl Parser {
fn parse_item_trait() -> item_info { fn parse_item_trait() -> item_info {
let ident = self.parse_ident(); let ident = self.parse_ident();
self.parse_region_param(); self.parse_region_param();
let tps = self.parse_ty_params(); let tps = self.parse_generics();
// Parse traits, if necessary. // Parse traits, if necessary.
let traits; let traits;
@ -3055,12 +3063,7 @@ pub impl Parser {
} }
// First, parse type parameters if necessary. // First, parse type parameters if necessary.
let mut tps; let generics = self.parse_generics();
if *self.token == token::LT {
tps = self.parse_ty_params();
} else {
tps = ~[];
}
// This is a new-style impl declaration. // This is a new-style impl declaration.
// XXX: clownshoes // XXX: clownshoes
@ -3108,37 +3111,7 @@ pub impl Parser {
} }
} }
(ident, item_impl(tps, opt_trait, ty, meths), None) (ident, item_impl(generics, opt_trait, ty, meths), None)
}
// Instantiates ident <i> with references to <typarams> as arguments.
// Used to create a path that refers to a class which will be defined as
// the return type of the ctor function.
fn ident_to_path_tys(i: ident,
typarams: ~[ty_param]) -> @path {
let s = *self.last_span;
@ast::path {
span: s,
global: false,
idents: ~[i],
rp: None,
types: do typarams.map |tp| {
@Ty {
id: self.get_id(),
node: ty_path(ident_to_path(s, tp.ident), self.get_id()),
span: s
}
}
}
}
fn ident_to_path(i: ident) -> @path {
@ast::path { span: *self.last_span,
global: false,
idents: ~[i],
rp: None,
types: ~[] }
} }
fn parse_trait_ref() -> @trait_ref { fn parse_trait_ref() -> @trait_ref {
@ -3153,13 +3126,13 @@ pub impl Parser {
ket, ket,
seq_sep_none(), seq_sep_none(),
|p| p.parse_trait_ref() |p| p.parse_trait_ref()
) ).to_vec()
} }
fn parse_item_struct() -> item_info { fn parse_item_struct() -> item_info {
let class_name = self.parse_value_ident(); let class_name = self.parse_value_ident();
self.parse_region_param(); self.parse_region_param();
let ty_params = self.parse_ty_params(); let generics = self.parse_generics();
if self.eat(&token::COLON) { if self.eat(&token::COLON) {
self.obsolete(copy *self.span, ObsoleteClassTraits); self.obsolete(copy *self.span, ObsoleteClassTraits);
let _ = self.parse_trait_ref_list(&token::LBRACE); let _ = self.parse_trait_ref_list(&token::LBRACE);
@ -3242,7 +3215,7 @@ pub impl Parser {
fields: fields, fields: fields,
dtor: actual_dtor, dtor: actual_dtor,
ctor_id: if is_tuple_like { Some(new_id) } else { None } ctor_id: if is_tuple_like { Some(new_id) } else { None }
}, ty_params), }, generics),
None) None)
} }
@ -3520,13 +3493,13 @@ pub impl Parser {
let lo = self.span.lo; let lo = self.span.lo;
let vis = self.parse_visibility(); let vis = self.parse_visibility();
let purity = self.parse_fn_purity(); let purity = self.parse_fn_purity();
let (ident, tps) = self.parse_fn_header(); let (ident, generics) = self.parse_fn_header();
let decl = self.parse_fn_decl(|p| p.parse_arg()); let decl = self.parse_fn_decl(|p| p.parse_arg());
let mut hi = self.span.hi; let mut hi = self.span.hi;
self.expect(&token::SEMI); self.expect(&token::SEMI);
@ast::foreign_item { ident: ident, @ast::foreign_item { ident: ident,
attrs: attrs, attrs: attrs,
node: foreign_item_fn(decl, purity, tps), node: foreign_item_fn(decl, purity, generics),
id: self.get_id(), id: self.get_id(),
span: mk_sp(lo, hi), span: mk_sp(lo, hi),
vis: vis } vis: vis }
@ -3696,7 +3669,7 @@ pub impl Parser {
fn parse_item_type() -> item_info { fn parse_item_type() -> item_info {
let (_, ident) = self.parse_type_decl(); let (_, ident) = self.parse_type_decl();
self.parse_region_param(); self.parse_region_param();
let tps = self.parse_ty_params(); let tps = self.parse_generics();
self.expect(&token::EQ); self.expect(&token::EQ);
let ty = self.parse_ty(false); let ty = self.parse_ty(false);
self.expect(&token::SEMI); self.expect(&token::SEMI);
@ -3752,9 +3725,8 @@ pub impl Parser {
}; };
} }
fn parse_enum_def(ty_params: ~[ast::ty_param]) fn parse_enum_def(generics: &ast::Generics) -> enum_def {
-> enum_def { let mut variants = ~[];
let mut variants: ~[variant] = ~[];
let mut all_nullary = true, have_disr = false; let mut all_nullary = true, have_disr = false;
let mut common_fields = None; let mut common_fields = None;
@ -3780,7 +3752,7 @@ pub impl Parser {
if self.eat_keyword(&~"enum") { if self.eat_keyword(&~"enum") {
ident = self.parse_ident(); ident = self.parse_ident();
self.expect(&token::LBRACE); self.expect(&token::LBRACE);
let nested_enum_def = self.parse_enum_def(ty_params); let nested_enum_def = self.parse_enum_def(generics);
kind = enum_variant_kind(nested_enum_def); kind = enum_variant_kind(nested_enum_def);
needs_comma = false; needs_comma = false;
} else { } else {
@ -3838,7 +3810,7 @@ pub impl Parser {
fn parse_item_enum() -> item_info { fn parse_item_enum() -> item_info {
let id = self.parse_ident(); let id = self.parse_ident();
self.parse_region_param(); self.parse_region_param();
let ty_params = self.parse_ty_params(); let generics = self.parse_generics();
// Newtype syntax // Newtype syntax
if *self.token == token::EQ { if *self.token == token::EQ {
self.bump(); self.bump();
@ -3861,14 +3833,14 @@ pub impl Parser {
enum_def( enum_def(
ast::enum_def_ { variants: ~[variant], common: None } ast::enum_def_ { variants: ~[variant], common: None }
), ),
ty_params), generics),
None None
); );
} }
self.expect(&token::LBRACE); self.expect(&token::LBRACE);
let enum_definition = self.parse_enum_def(ty_params); let enum_definition = self.parse_enum_def(&generics);
(id, item_enum(enum_definition, ty_params), None) (id, item_enum(enum_definition, generics), None)
} }
fn parse_fn_ty_sigil() -> Option<Sigil> { fn parse_fn_ty_sigil() -> Option<Sigil> {

View file

@ -14,6 +14,8 @@ use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
use ast; use ast;
use ast_util; use ast_util;
use ast_util::{operator_prec}; use ast_util::{operator_prec};
use opt_vec;
use opt_vec::OptVec;
use attr; use attr;
use codemap::{CodeMap, BytePos}; use codemap::{CodeMap, BytePos};
use codemap; use codemap;
@ -166,19 +168,20 @@ pub fn item_to_str(i: @ast::item, intr: @ident_interner) -> ~str {
to_str(i, print_item, intr) to_str(i, print_item, intr)
} }
pub fn typarams_to_str(tps: ~[ast::ty_param], intr: @ident_interner) -> ~str { pub fn generics_to_str(generics: &ast::Generics,
to_str(tps, print_type_params, intr) intr: @ident_interner) -> ~str {
to_str(generics, print_generics, intr)
} }
pub fn path_to_str(&&p: @ast::path, intr: @ident_interner) -> ~str { pub fn path_to_str(&&p: @ast::path, intr: @ident_interner) -> ~str {
to_str(p, |a,b| print_path(a, b, false), intr) to_str(p, |a,b| print_path(a, b, false), intr)
} }
pub fn fun_to_str(decl: ast::fn_decl, name: ast::ident, pub fn fun_to_str(decl: &ast::fn_decl, name: ast::ident,
params: ~[ast::ty_param], intr: @ident_interner) -> ~str { generics: &ast::Generics, intr: @ident_interner) -> ~str {
do io::with_str_writer |wr| { do io::with_str_writer |wr| {
let s = rust_printer(wr, intr); let s = rust_printer(wr, intr);
print_fn(s, decl, None, name, params, None, ast::inherited); print_fn(s, decl, None, name, generics, None, ast::inherited);
end(s); // Close the head box end(s); // Close the head box
end(s); // Close the outer box end(s); // Close the outer box
eof(s.s); eof(s.s);
@ -302,7 +305,7 @@ pub fn synth_comment(s: @ps, text: ~str) {
word(s.s, ~"*/"); word(s.s, ~"*/");
} }
pub fn commasep<IN>(s: @ps, b: breaks, elts: ~[IN], op: fn(@ps, IN)) { pub fn commasep<IN>(s: @ps, b: breaks, elts: ~[IN], op: &fn(@ps, IN)) {
box(s, 0u, b); box(s, 0u, b);
let mut first = true; let mut first = true;
for elts.each |elt| { for elts.each |elt| {
@ -424,12 +427,12 @@ pub fn print_type_ex(s: @ps, &&ty: @ast::Ty, print_colons: bool) {
} }
ast::ty_bare_fn(f) => { ast::ty_bare_fn(f) => {
print_ty_fn(s, Some(f.abi), None, None, print_ty_fn(s, Some(f.abi), None, None,
f.purity, ast::Many, f.decl, None, f.purity, ast::Many, &f.decl, None,
None, None); None, None);
} }
ast::ty_closure(f) => { ast::ty_closure(f) => {
print_ty_fn(s, None, Some(f.sigil), f.region, print_ty_fn(s, None, Some(f.sigil), f.region,
f.purity, f.onceness, f.decl, None, f.purity, f.onceness, &f.decl, None,
None, None); None, None);
} }
ast::ty_path(path, _) => print_path(s, path, print_colons), ast::ty_path(path, _) => print_path(s, path, print_colons),
@ -461,8 +464,8 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) {
maybe_print_comment(s, item.span.lo); maybe_print_comment(s, item.span.lo);
print_outer_attributes(s, item.attrs); print_outer_attributes(s, item.attrs);
match /*bad*/ copy item.node { match /*bad*/ copy item.node {
ast::foreign_item_fn(decl, purity, typarams) => { ast::foreign_item_fn(ref decl, purity, ref generics) => {
print_fn(s, decl, Some(purity), item.ident, typarams, None, print_fn(s, decl, Some(purity), item.ident, generics, None,
ast::inherited); ast::inherited);
end(s); // end head-ibox end(s); // end head-ibox
word(s.s, ~";"); word(s.s, ~";");
@ -504,10 +507,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
ast::item_fn(ref decl, purity, ref typarams, ref body) => { ast::item_fn(ref decl, purity, ref typarams, ref body) => {
print_fn( print_fn(
s, s,
/* FIXME (#2543) */ copy *decl, decl,
Some(purity), Some(purity),
item.ident, item.ident,
/* FIXME (#2543) */ copy *typarams, typarams,
None, None,
item.vis item.vis
); );
@ -538,12 +541,12 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
print_foreign_mod(s, nmod, item.attrs); print_foreign_mod(s, nmod, item.attrs);
bclose(s, item.span); bclose(s, item.span);
} }
ast::item_ty(ty, params) => { ast::item_ty(ty, ref params) => {
ibox(s, indent_unit); ibox(s, indent_unit);
ibox(s, 0u); ibox(s, 0u);
word_nbsp(s, visibility_qualified(item.vis, ~"type")); word_nbsp(s, visibility_qualified(item.vis, ~"type"));
print_ident(s, item.ident); print_ident(s, item.ident);
print_type_params(s, params); print_generics(s, params);
end(s); // end the inner ibox end(s); // end the inner ibox
space(s.s); space(s.s);
@ -556,21 +559,21 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
print_enum_def( print_enum_def(
s, s,
*enum_definition, *enum_definition,
/* FIXME (#2543) */ copy *params, params,
item.ident, item.ident,
item.span, item.span,
item.vis item.vis
); );
} }
ast::item_struct(struct_def, tps) => { ast::item_struct(struct_def, ref generics) => {
head(s, visibility_qualified(item.vis, ~"struct")); head(s, visibility_qualified(item.vis, ~"struct"));
print_struct(s, struct_def, tps, item.ident, item.span); print_struct(s, struct_def, generics, item.ident, item.span);
} }
ast::item_impl(tps, opt_trait, ty, methods) => { ast::item_impl(ref generics, opt_trait, ty, ref methods) => {
head(s, visibility_qualified(item.vis, ~"impl")); head(s, visibility_qualified(item.vis, ~"impl"));
if !tps.is_empty() { if !generics.is_empty() {
print_type_params(s, tps); print_generics(s, generics);
space(s.s); space(s.s);
} }
@ -596,10 +599,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
bclose(s, item.span); bclose(s, item.span);
} }
} }
ast::item_trait(ref tps, ref traits, ref methods) => { ast::item_trait(ref generics, ref traits, ref methods) => {
head(s, visibility_qualified(item.vis, ~"trait")); head(s, visibility_qualified(item.vis, ~"trait"));
print_ident(s, item.ident); print_ident(s, item.ident);
print_type_params(s, /* FIXME (#2543) */ copy *tps); print_generics(s, generics);
if traits.len() != 0u { if traits.len() != 0u {
word(s.s, ~":"); word(s.s, ~":");
for traits.each |trait_| { for traits.each |trait_| {
@ -631,7 +634,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
} }
pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def, pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
params: ~[ast::ty_param], ident: ast::ident, generics: &ast::Generics, ident: ast::ident,
span: codemap::span, visibility: ast::visibility) { span: codemap::span, visibility: ast::visibility) {
let mut newtype = let mut newtype =
vec::len(enum_definition.variants) == 1u && vec::len(enum_definition.variants) == 1u &&
@ -650,7 +653,7 @@ pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
} }
print_ident(s, ident); print_ident(s, ident);
print_type_params(s, params); print_generics(s, generics);
space(s.s); space(s.s);
if newtype { if newtype {
word_space(s, ~"="); word_space(s, ~"=");
@ -707,12 +710,12 @@ pub fn print_visibility(s: @ps, vis: ast::visibility) {
pub fn print_struct(s: @ps, pub fn print_struct(s: @ps,
struct_def: @ast::struct_def, struct_def: @ast::struct_def,
tps: ~[ast::ty_param], generics: &ast::Generics,
ident: ast::ident, ident: ast::ident,
span: codemap::span) { span: codemap::span) {
print_ident(s, ident); print_ident(s, ident);
nbsp(s); nbsp(s);
print_type_params(s, tps); print_generics(s, generics);
if ast_util::struct_def_is_tuple_like(struct_def) { if ast_util::struct_def_is_tuple_like(struct_def) {
popen(s); popen(s);
let mut first = true; let mut first = true;
@ -824,7 +827,8 @@ pub fn print_variant(s: @ps, v: ast::variant) {
} }
ast::struct_variant_kind(struct_def) => { ast::struct_variant_kind(struct_def) => {
head(s, ~""); head(s, ~"");
print_struct(s, struct_def, ~[], v.node.name, v.span); let generics = ast_util::empty_generics();
print_struct(s, struct_def, &generics, v.node.name, v.span);
} }
ast::enum_variant_kind(ref enum_definition) => { ast::enum_variant_kind(ref enum_definition) => {
print_variants(s, (*enum_definition).variants, v.span); print_variants(s, (*enum_definition).variants, v.span);
@ -845,7 +849,7 @@ pub fn print_ty_method(s: @ps, m: &ast::ty_method) {
maybe_print_comment(s, m.span.lo); maybe_print_comment(s, m.span.lo);
print_outer_attributes(s, m.attrs); print_outer_attributes(s, m.attrs);
print_ty_fn(s, None, None, None, m.purity, ast::Many, print_ty_fn(s, None, None, None, m.purity, ast::Many,
m.decl, Some(m.ident), Some(/*bad*/ copy m.tps), &m.decl, Some(m.ident), Some(&m.generics),
Some(/*bad*/ copy m.self_ty.node)); Some(/*bad*/ copy m.self_ty.node));
word(s.s, ~";"); word(s.s, ~";");
} }
@ -861,8 +865,8 @@ pub fn print_method(s: @ps, meth: @ast::method) {
hardbreak_if_not_bol(s); hardbreak_if_not_bol(s);
maybe_print_comment(s, meth.span.lo); maybe_print_comment(s, meth.span.lo);
print_outer_attributes(s, meth.attrs); print_outer_attributes(s, meth.attrs);
print_fn(s, meth.decl, Some(meth.purity), print_fn(s, &meth.decl, Some(meth.purity),
meth.ident, meth.tps, Some(meth.self_ty.node), meth.ident, &meth.generics, Some(meth.self_ty.node),
meth.vis); meth.vis);
word(s.s, ~" "); word(s.s, ~" ");
print_block_with_attrs(s, &meth.body, meth.attrs); print_block_with_attrs(s, &meth.body, meth.attrs);
@ -1353,7 +1357,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
ibox(s, 0u); ibox(s, 0u);
print_fn_header_info(s, None, None, ast::Many, print_fn_header_info(s, None, None, ast::Many,
Some(sigil), ast::inherited); Some(sigil), ast::inherited);
print_fn_args_and_ret(s, /* FIXME (#2543) */ copy *decl, None); print_fn_args_and_ret(s, decl, None);
space(s.s); space(s.s);
print_block(s, body); print_block(s, body);
} }
@ -1363,7 +1367,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
// we are inside. // we are inside.
// //
// if !decl.inputs.is_empty() { // if !decl.inputs.is_empty() {
print_fn_block_args(s, /* FIXME (#2543) */ copy *decl); print_fn_block_args(s, decl);
space(s.s); space(s.s);
// } // }
assert body.node.stmts.is_empty(); assert body.node.stmts.is_empty();
@ -1712,21 +1716,21 @@ pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool {
} }
pub fn print_fn(s: @ps, pub fn print_fn(s: @ps,
decl: ast::fn_decl, decl: &ast::fn_decl,
purity: Option<ast::purity>, purity: Option<ast::purity>,
name: ast::ident, name: ast::ident,
typarams: ~[ast::ty_param], generics: &ast::Generics,
opt_self_ty: Option<ast::self_ty_>, opt_self_ty: Option<ast::self_ty_>,
vis: ast::visibility) { vis: ast::visibility) {
head(s, ~""); head(s, ~"");
print_fn_header_info(s, opt_self_ty, purity, ast::Many, None, vis); print_fn_header_info(s, opt_self_ty, purity, ast::Many, None, vis);
nbsp(s); nbsp(s);
print_ident(s, name); print_ident(s, name);
print_type_params(s, typarams); print_generics(s, generics);
print_fn_args_and_ret(s, decl, opt_self_ty); print_fn_args_and_ret(s, decl, opt_self_ty);
} }
pub fn print_fn_args(s: @ps, decl: ast::fn_decl, pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
opt_self_ty: Option<ast::self_ty_>) { opt_self_ty: Option<ast::self_ty_>) {
// It is unfortunate to duplicate the commasep logic, but we we want the // It is unfortunate to duplicate the commasep logic, but we we want the
// self type and the args all in the same box. // self type and the args all in the same box.
@ -1744,7 +1748,7 @@ pub fn print_fn_args(s: @ps, decl: ast::fn_decl,
end(s); end(s);
} }
pub fn print_fn_args_and_ret(s: @ps, decl: ast::fn_decl, pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
opt_self_ty: Option<ast::self_ty_>) { opt_self_ty: Option<ast::self_ty_>) {
popen(s); popen(s);
print_fn_args(s, decl, opt_self_ty); print_fn_args(s, decl, opt_self_ty);
@ -1761,7 +1765,7 @@ pub fn print_fn_args_and_ret(s: @ps, decl: ast::fn_decl,
} }
} }
pub fn print_fn_block_args(s: @ps, decl: ast::fn_decl) { pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
word(s.s, ~"|"); word(s.s, ~"|");
print_fn_args(s, decl, None); print_fn_args(s, decl, None);
word(s.s, ~"|"); word(s.s, ~"|");
@ -1792,11 +1796,11 @@ pub fn print_arg_mode(s: @ps, m: ast::mode) {
if ms != ~"" { word(s.s, ms); } if ms != ~"" { word(s.s, ms); }
} }
pub fn print_bounds(s: @ps, bounds: @~[ast::ty_param_bound]) { pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
if !bounds.is_empty() { if !bounds.is_empty() {
word(s.s, ~":"); word(s.s, ~":");
let mut first = true; let mut first = true;
for vec::each(*bounds) |&bound| { for bounds.each |bound| {
nbsp(s); nbsp(s);
if first { if first {
first = false; first = false;
@ -1804,7 +1808,7 @@ pub fn print_bounds(s: @ps, bounds: @~[ast::ty_param_bound]) {
word_space(s, ~"+"); word_space(s, ~"+");
} }
match bound { match *bound {
TraitTyParamBound(ty) => print_type(s, ty), TraitTyParamBound(ty) => print_type(s, ty),
RegionTyParamBound => word(s.s, ~"&static"), RegionTyParamBound => word(s.s, ~"&static"),
} }
@ -1812,14 +1816,33 @@ pub fn print_bounds(s: @ps, bounds: @~[ast::ty_param_bound]) {
} }
} }
pub fn print_type_params(s: @ps, &&params: ~[ast::ty_param]) { pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) {
if vec::len(params) > 0u { word(s.s, ~"'");
print_ident(s, lifetime.ident);
}
pub fn print_generics(s: @ps, &&generics: &ast::Generics) {
let total = generics.lifetimes.len() + generics.ty_params.len();
if total > 0 {
word(s.s, ~"<"); word(s.s, ~"<");
fn printParam(s: @ps, param: ast::ty_param) { fn print_item(s: @ps, generics: &ast::Generics, idx: uint) {
print_ident(s, param.ident); if idx < generics.lifetimes.len() {
print_bounds(s, param.bounds); let lifetime = generics.lifetimes.get(idx);
print_lifetime(s, lifetime);
} else {
let param = generics.ty_params.get(idx);
print_ident(s, param.ident);
print_bounds(s, param.bounds);
}
} }
commasep(s, inconsistent, params, printParam);
let mut ints = ~[];
for uint::range(0, total) |i| {
ints.push(i);
}
commasep(s, inconsistent, ints,
|s, i| print_item(s, generics, i));
word(s.s, ~">"); word(s.s, ~">");
} }
} }
@ -1954,8 +1977,8 @@ pub fn print_ty_fn(s: @ps,
opt_region: Option<@ast::region>, opt_region: Option<@ast::region>,
purity: ast::purity, purity: ast::purity,
onceness: ast::Onceness, onceness: ast::Onceness,
decl: ast::fn_decl, id: Option<ast::ident>, decl: &ast::fn_decl, id: Option<ast::ident>,
tps: Option<~[ast::ty_param]>, generics: Option<&ast::Generics>,
opt_self_ty: Option<ast::self_ty_>) { opt_self_ty: Option<ast::self_ty_>) {
ibox(s, indent_unit); ibox(s, indent_unit);
@ -1969,7 +1992,7 @@ pub fn print_ty_fn(s: @ps,
print_onceness(s, onceness); print_onceness(s, onceness);
word(s.s, ~"fn"); word(s.s, ~"fn");
match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () } match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () }
match /*bad*/ copy tps { Some(tps) => print_type_params(s, tps), _ => () } match /*bad*/ copy generics { Some(g) => print_generics(s, g), _ => () }
zerobreak(s.s); zerobreak(s.s);
popen(s); popen(s);
@ -2295,14 +2318,15 @@ pub mod test {
let mock_interner = parse::token::mk_fake_ident_interner(); let mock_interner = parse::token::mk_fake_ident_interner();
let abba_ident = mock_interner.intern(@~"abba"); let abba_ident = mock_interner.intern(@~"abba");
let decl: ast::fn_decl = ast::fn_decl { let decl = ast::fn_decl {
inputs: ~[], inputs: ~[],
output: @ast::Ty {id: 0, output: @ast::Ty {id: 0,
node: ast::ty_nil, node: ast::ty_nil,
span: codemap::dummy_sp()}, span: codemap::dummy_sp()},
cf: ast::return_val cf: ast::return_val
}; };
check_equal (&fun_to_str(decl, abba_ident, ~[],mock_interner), let generics = ast_util::empty_generics();
check_equal (&fun_to_str(&decl, abba_ident, &generics, mock_interner),
&~"fn abba()"); &~"fn abba()");
} }

View file

@ -35,6 +35,7 @@ pub mod syntax {
pub use parse; pub use parse;
} }
pub mod opt_vec;
pub mod attr; pub mod attr;
pub mod diagnostic; pub mod diagnostic;
pub mod codemap; pub mod codemap;

View file

@ -15,6 +15,7 @@ use ast;
use ast_util; use ast_util;
use codemap::span; use codemap::span;
use parse; use parse;
use opt_vec;
use core::option; use core::option;
use core::vec; use core::vec;
@ -30,17 +31,16 @@ use core::vec;
pub enum vt<E> { mk_vt(visitor<E>), } pub enum vt<E> { mk_vt(visitor<E>), }
pub enum fn_kind { pub enum fn_kind {
fk_item_fn(ident, &[ty_param], purity), // fn foo() fk_item_fn(ident, &Generics, purity), // fn foo()
fk_method(ident, &[ty_param], &method), // fn foo(&self) fk_method(ident, &Generics, &method), // fn foo(&self)
fk_anon(ast::Sigil), // fn@(x, y) { ... } fk_anon(ast::Sigil), // fn@(x, y) { ... }
fk_fn_block, // |x, y| ... fk_fn_block, // |x, y| ...
fk_dtor( // class destructor fk_dtor( // class destructor
&[ty_param], &Generics,
&[attribute], &[attribute],
node_id /* self id */, node_id /* self id */,
def_id /* parent class id */ def_id /* parent class id */
) )
} }
pub fn name_of_fn(fk: &fn_kind) -> ident { pub fn name_of_fn(fk: &fn_kind) -> ident {
@ -53,11 +53,19 @@ pub fn name_of_fn(fk: &fn_kind) -> ident {
} }
} }
pub fn tps_of_fn(fk: &fn_kind) -> ~[ty_param] { pub fn generics_of_fn(fk: &fn_kind) -> Generics {
match *fk { match *fk {
fk_item_fn(_, tps, _) | fk_method(_, tps, _) | fk_item_fn(_, generics, _) |
fk_dtor(tps, _, _, _) => /* FIXME (#2543) */ vec::from_slice(tps), fk_method(_, generics, _) |
fk_anon(*) | fk_fn_block(*) => ~[] fk_dtor(generics, _, _, _) => {
copy *generics
}
fk_anon(*) | fk_fn_block(*) => {
Generics {
lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty,
}
}
} }
} }
@ -75,11 +83,11 @@ pub struct Visitor<E> {
visit_expr: fn@(@expr, E, vt<E>), visit_expr: fn@(@expr, E, vt<E>),
visit_expr_post: fn@(@expr, E, vt<E>), visit_expr_post: fn@(@expr, E, vt<E>),
visit_ty: fn@(@Ty, E, vt<E>), visit_ty: fn@(@Ty, E, vt<E>),
visit_ty_params: fn@(&[ty_param], E, vt<E>), visit_generics: fn@(&Generics, E, vt<E>),
visit_fn: fn@(&fn_kind, &fn_decl, &blk, span, node_id, E, vt<E>), visit_fn: fn@(&fn_kind, &fn_decl, &blk, span, node_id, E, vt<E>),
visit_ty_method: fn@(&ty_method, E, vt<E>), visit_ty_method: fn@(&ty_method, E, vt<E>),
visit_trait_method: fn@(&trait_method, E, vt<E>), visit_trait_method: fn@(&trait_method, E, vt<E>),
visit_struct_def: fn@(@struct_def, ident, &[ty_param], node_id, E, visit_struct_def: fn@(@struct_def, ident, &Generics, node_id, E,
vt<E>), vt<E>),
visit_struct_field: fn@(@struct_field, E, vt<E>), visit_struct_field: fn@(@struct_field, E, vt<E>),
visit_struct_method: fn@(@method, E, vt<E>) visit_struct_method: fn@(@method, E, vt<E>)
@ -102,7 +110,7 @@ pub fn default_visitor<E>() -> visitor<E> {
visit_expr: |a,b,c|visit_expr::<E>(a, b, c), visit_expr: |a,b,c|visit_expr::<E>(a, b, c),
visit_expr_post: |_a,_b,_c| (), visit_expr_post: |_a,_b,_c| (),
visit_ty: |a,b,c|skip_ty::<E>(a, b, c), visit_ty: |a,b,c|skip_ty::<E>(a, b, c),
visit_ty_params: |a,b,c|visit_ty_params::<E>(a, b, c), visit_generics: |a,b,c|visit_generics::<E>(a, b, c),
visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g), visit_fn: |a,b,c,d,e,f,g|visit_fn::<E>(a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c), visit_ty_method: |a,b,c|visit_ty_method::<E>(a, b, c),
visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c), visit_trait_method: |a,b,c|visit_trait_method::<E>(a, b, c),
@ -139,11 +147,11 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
(v.visit_ty)(t, e, v); (v.visit_ty)(t, e, v);
(v.visit_expr)(ex, e, v); (v.visit_expr)(ex, e, v);
} }
item_fn(ref decl, purity, ref tps, ref body) => { item_fn(ref decl, purity, ref generics, ref body) => {
(v.visit_fn)( (v.visit_fn)(
&fk_item_fn( &fk_item_fn(
/* FIXME (#2543) */ copy i.ident, /* FIXME (#2543) */ copy i.ident,
*tps, generics,
purity purity
), ),
decl, decl,
@ -161,35 +169,35 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
} }
item_ty(t, ref tps) => { item_ty(t, ref tps) => {
(v.visit_ty)(t, e, v); (v.visit_ty)(t, e, v);
(v.visit_ty_params)(*tps, e, v); (v.visit_generics)(tps, e, v);
} }
item_enum(ref enum_definition, ref tps) => { item_enum(ref enum_definition, ref tps) => {
(v.visit_ty_params)(*tps, e, v); (v.visit_generics)(tps, e, v);
visit_enum_def( visit_enum_def(
*enum_definition, *enum_definition,
/* FIXME (#2543) */ copy *tps, tps,
e, e,
v v
); );
} }
item_impl(ref tps, ref traits, ty, ref methods) => { item_impl(ref tps, ref traits, ty, ref methods) => {
(v.visit_ty_params)(*tps, e, v); (v.visit_generics)(tps, e, v);
for traits.each |p| { for traits.each |p| {
visit_path(p.path, e, v); visit_path(p.path, e, v);
} }
(v.visit_ty)(ty, e, v); (v.visit_ty)(ty, e, v);
for methods.each |m| { for methods.each |m| {
visit_method_helper(*m, e, v) visit_method_helper(*m, e, v)
} }
} }
item_struct(struct_def, ref tps) => { item_struct(struct_def, ref generics) => {
(v.visit_ty_params)(*tps, e, v); (v.visit_generics)(generics, e, v);
(v.visit_struct_def)(struct_def, i.ident, *tps, i.id, e, v); (v.visit_struct_def)(struct_def, i.ident, generics, i.id, e, v);
} }
item_trait(ref tps, ref traits, ref methods) => { item_trait(ref generics, ref traits, ref methods) => {
(v.visit_ty_params)(*tps, e, v); (v.visit_generics)(generics, e, v);
for traits.each |p| { visit_path(p.path, e, v); } for traits.each |p| { visit_path(p.path, e, v); }
for (*methods).each |m| { for methods.each |m| {
(v.visit_trait_method)(m, e, v); (v.visit_trait_method)(m, e, v);
} }
} }
@ -198,7 +206,7 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
} }
pub fn visit_enum_def<E>(enum_definition: ast::enum_def, pub fn visit_enum_def<E>(enum_definition: ast::enum_def,
tps: &[ast::ty_param], tps: &Generics,
e: E, e: E,
v: vt<E>) { v: vt<E>) {
for enum_definition.variants.each |vr| { for enum_definition.variants.each |vr| {
@ -305,9 +313,9 @@ pub fn visit_pat<E>(p: @pat, e: E, v: vt<E>) {
pub fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) { pub fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
match ni.node { match ni.node {
foreign_item_fn(ref fd, _, ref tps) => { foreign_item_fn(ref fd, _, ref generics) => {
(v.visit_ty_params)(*tps, e, v);
visit_fn_decl(fd, e, v); visit_fn_decl(fd, e, v);
(v.visit_generics)(generics, e, v);
} }
foreign_item_const(t) => { foreign_item_const(t) => {
(v.visit_ty)(t, e, v); (v.visit_ty)(t, e, v);
@ -315,17 +323,18 @@ pub fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
} }
} }
pub fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) { pub fn visit_ty_param_bounds<E>(bounds: @OptVec<TyParamBound>,
for bounds.each |&bound| { e: E, v: vt<E>) {
match bound { for bounds.each |bound| {
match *bound {
TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v), TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v),
RegionTyParamBound => () RegionTyParamBound => ()
} }
} }
} }
pub fn visit_ty_params<E>(tps: &[ty_param], e: E, v: vt<E>) { pub fn visit_generics<E>(generics: &Generics, e: E, v: vt<E>) {
for tps.each |tp| { for generics.ty_params.each |tp| {
visit_ty_param_bounds(tp.bounds, e, v); visit_ty_param_bounds(tp.bounds, e, v);
} }
} }
@ -346,7 +355,7 @@ pub fn visit_method_helper<E>(m: &method, e: E, v: vt<E>) {
(v.visit_fn)( (v.visit_fn)(
&fk_method( &fk_method(
/* FIXME (#2543) */ copy m.ident, /* FIXME (#2543) */ copy m.ident,
m.tps, &m.generics,
m m
), ),
&m.decl, &m.decl,
@ -358,11 +367,11 @@ pub fn visit_method_helper<E>(m: &method, e: E, v: vt<E>) {
); );
} }
pub fn visit_struct_dtor_helper<E>(dtor: struct_dtor, tps: &[ty_param], pub fn visit_struct_dtor_helper<E>(dtor: struct_dtor, generics: &Generics,
parent_id: def_id, e: E, v: vt<E>) { parent_id: def_id, e: E, v: vt<E>) {
(v.visit_fn)( (v.visit_fn)(
&fk_dtor( &fk_dtor(
tps, generics,
dtor.node.attrs, dtor.node.attrs,
dtor.node.self_id, dtor.node.self_id,
parent_id parent_id
@ -380,13 +389,14 @@ pub fn visit_struct_dtor_helper<E>(dtor: struct_dtor, tps: &[ty_param],
pub fn visit_fn<E>(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span, pub fn visit_fn<E>(fk: &fn_kind, decl: &fn_decl, body: &blk, _sp: span,
_id: node_id, e: E, v: vt<E>) { _id: node_id, e: E, v: vt<E>) {
visit_fn_decl(decl, e, v); visit_fn_decl(decl, e, v);
(v.visit_ty_params)(tps_of_fn(fk), e, v); let generics = generics_of_fn(fk);
(v.visit_generics)(&generics, e, v);
(v.visit_block)(body, e, v); (v.visit_block)(body, e, v);
} }
pub fn visit_ty_method<E>(m: &ty_method, e: E, v: vt<E>) { pub fn visit_ty_method<E>(m: &ty_method, e: E, v: vt<E>) {
for m.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); } for m.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); }
(v.visit_ty_params)(m.tps, e, v); (v.visit_generics)(&m.generics, e, v);
(v.visit_ty)(m.decl.output, e, v); (v.visit_ty)(m.decl.output, e, v);
} }
@ -397,13 +407,25 @@ pub fn visit_trait_method<E>(m: &trait_method, e: E, v: vt<E>) {
} }
} }
pub fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: &[ty_param], pub fn visit_struct_def<E>(
id: node_id, e: E, v: vt<E>) { sd: @struct_def,
_nm: ast::ident,
generics: &Generics,
id: node_id,
e: E,
v: vt<E>
) {
for sd.fields.each |f| { for sd.fields.each |f| {
(v.visit_struct_field)(*f, e, v); (v.visit_struct_field)(*f, e, v);
} }
do sd.dtor.iter |dtor| { do sd.dtor.iter |dtor| {
visit_struct_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v) visit_struct_dtor_helper(
*dtor,
generics,
ast_util::local_def(id),
e,
v
)
}; };
} }
@ -593,11 +615,11 @@ pub struct SimpleVisitor {
visit_expr: fn@(@expr), visit_expr: fn@(@expr),
visit_expr_post: fn@(@expr), visit_expr_post: fn@(@expr),
visit_ty: fn@(@Ty), visit_ty: fn@(@Ty),
visit_ty_params: fn@(&[ty_param]), visit_generics: fn@(&Generics),
visit_fn: fn@(&fn_kind, &fn_decl, &blk, span, node_id), visit_fn: fn@(&fn_kind, &fn_decl, &blk, span, node_id),
visit_ty_method: fn@(&ty_method), visit_ty_method: fn@(&ty_method),
visit_trait_method: fn@(&trait_method), visit_trait_method: fn@(&trait_method),
visit_struct_def: fn@(@struct_def, ident, &[ty_param], node_id), visit_struct_def: fn@(@struct_def, ident, &Generics, node_id),
visit_struct_field: fn@(@struct_field), visit_struct_field: fn@(@struct_field),
visit_struct_method: fn@(@method) visit_struct_method: fn@(@method)
} }
@ -621,13 +643,13 @@ pub fn default_simple_visitor() -> @SimpleVisitor {
visit_expr: |_e| { }, visit_expr: |_e| { },
visit_expr_post: |_e| { }, visit_expr_post: |_e| { },
visit_ty: simple_ignore_ty, visit_ty: simple_ignore_ty,
visit_ty_params: fn@(_ps: &[ty_param]) { }, visit_generics: fn@(_ps: &Generics) { },
visit_fn: fn@(_fk: &fn_kind, _d: &fn_decl, _b: &blk, _sp: span, visit_fn: fn@(_fk: &fn_kind, _d: &fn_decl, _b: &blk, _sp: span,
_id: node_id) { }, _id: node_id) { },
visit_ty_method: fn@(_m: &ty_method) { }, visit_ty_method: fn@(_m: &ty_method) { },
visit_trait_method: fn@(_m: &trait_method) { }, visit_trait_method: fn@(_m: &trait_method) { },
visit_struct_def: fn@(_sd: @struct_def, _nm: ident, visit_struct_def: fn@(_sd: @struct_def, _nm: ident,
_tps: &[ty_param], _id: node_id) { }, _generics: &Generics, _id: node_id) { },
visit_struct_field: fn@(_f: @struct_field) { }, visit_struct_field: fn@(_f: @struct_field) { },
visit_struct_method: fn@(_m: @method) { } visit_struct_method: fn@(_m: @method) { }
} }
@ -702,18 +724,26 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
f(m); f(m);
visit_trait_method(m, e, v); visit_trait_method(m, e, v);
} }
fn v_struct_def(f: fn@(@struct_def, ident, &[ty_param], node_id), fn v_struct_def(
sd: @struct_def, nm: ident, tps: &[ty_param], id: node_id, f: fn@(@struct_def, ident, &Generics, node_id),
&&e: (), v: vt<()>) { sd: @struct_def,
f(sd, nm, tps, id); nm: ident,
visit_struct_def(sd, nm, tps, id, e, v); generics: &Generics,
id: node_id,
&&e: (),
v: vt<()>
) {
f(sd, nm, generics, id);
visit_struct_def(sd, nm, generics, id, e, v);
} }
fn v_ty_params(f: fn@(&[ty_param]), fn v_generics(
ps: &[ty_param], f: fn@(&Generics),
&&e: (), ps: &Generics,
v: vt<()>) { &&e: (),
v: vt<()>
) {
f(ps); f(ps);
visit_ty_params(ps, e, v); visit_generics(ps, e, v);
} }
fn v_fn( fn v_fn(
f: fn@(&fn_kind, &fn_decl, &blk, span, node_id), f: fn@(&fn_kind, &fn_decl, &blk, span, node_id),
@ -755,9 +785,12 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post, visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
a, b, c), a, b, c),
visit_ty: visit_ty, visit_ty: visit_ty,
visit_ty_params: |a,b,c| v_ty_params(v.visit_ty_params, a, b, c), visit_generics: |a,b,c|
visit_fn: |a,b,c,d,e,f,g| v_fn(v.visit_fn, a, b, c, d, e, f, g), v_generics(v.visit_generics, a, b, c),
visit_ty_method: |a,b,c| v_ty_method(v.visit_ty_method, a, b, c), visit_fn: |a,b,c,d,e,f,g|
v_fn(v.visit_fn, a, b, c, d, e, f, g),
visit_ty_method: |a,b,c|
v_ty_method(v.visit_ty_method, a, b, c),
visit_trait_method: |a,b,c| visit_trait_method: |a,b,c|
v_trait_method(v.visit_trait_method, a, b, c), v_trait_method(v.visit_trait_method, a, b, c),
visit_struct_def: |a,b,c,d,e,f| visit_struct_def: |a,b,c,d,e,f|

View file

@ -124,8 +124,7 @@ vec_reserve_shared_actual(type_desc* ty, rust_vec_box** vp,
extern "C" CDECL void extern "C" CDECL void
vec_reserve_shared(type_desc* ty, rust_vec_box** vp, vec_reserve_shared(type_desc* ty, rust_vec_box** vp,
size_t n_elts) { size_t n_elts) {
rust_task *task = rust_get_current_task(); reserve_vec_exact(vp, n_elts * ty->size);
reserve_vec_exact(task, vp, n_elts * ty->size);
} }
extern "C" CDECL size_t extern "C" CDECL size_t
@ -445,9 +444,8 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
out_tm->tm_nsec = nsec; out_tm->tm_nsec = nsec;
if (zone != NULL) { if (zone != NULL) {
rust_task *task = rust_get_current_task();
size_t size = strlen(zone); size_t size = strlen(zone);
reserve_vec_exact(task, &out_tm->tm_zone, size + 1); reserve_vec_exact(&out_tm->tm_zone, size + 1);
memcpy(out_tm->tm_zone->body.data, zone, size); memcpy(out_tm->tm_zone->body.data, zone, size);
out_tm->tm_zone->body.fill = size + 1; out_tm->tm_zone->body.fill = size + 1;
out_tm->tm_zone->body.data[size] = '\0'; out_tm->tm_zone->body.data[size] = '\0';

View file

@ -118,7 +118,12 @@ extern "C" CDECL void
upcall_fail(char const *expr, upcall_fail(char const *expr,
char const *file, char const *file,
size_t line) { size_t line) {
rust_task *task = rust_get_current_task(); rust_task *task = rust_try_get_current_task();
if (task == NULL) {
// NOTE: Need to think about what to do here
printf("failure outside of a task");
abort();
}
s_fail_args args = {task,expr,file,line}; s_fail_args args = {task,expr,file,line};
UPCALL_SWITCH_STACK(task, &args, upcall_s_fail); UPCALL_SWITCH_STACK(task, &args, upcall_s_fail);
} }

View file

@ -67,11 +67,12 @@ inline void reserve_vec_exact_shared(rust_task* task, rust_vec_box** vpp,
} }
} }
inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp, inline void reserve_vec_exact(rust_vec_box** vpp,
size_t size) { size_t size) {
if (size > (*vpp)->body.alloc) { if (size > (*vpp)->body.alloc) {
*vpp = (rust_vec_box*)task->kernel rust_exchange_alloc exchange_alloc;
->realloc(*vpp, size + sizeof(rust_vec_box)); *vpp = (rust_vec_box*)exchange_alloc
.realloc(*vpp, size + sizeof(rust_vec_box));
(*vpp)->body.alloc = size; (*vpp)->body.alloc = size;
} }
} }

View file

@ -0,0 +1,24 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub fn main() {
assert (~[0, 1]).to_str() == ~"[0, 1]";
assert (&[1, 2]).to_str() == ~"[1, 2]";
assert (@[2, 3]).to_str() == ~"[2, 3]";
let foo = ~[3, 4];
let bar = &[4, 5];
let baz = @[5, 6];
assert foo.to_str() == ~"[3, 4]";
assert bar.to_str() == ~"[4, 5]";
assert baz.to_str() == ~"[5, 6]";
}