auto merge of #5141 : nikomatsakis/rust/region-syntax-expl-lifetimes, r=nikomatsakis

Major changes are:
- replace ~[ty_param] with Generics structure, which includes
  both OptVec<TyParam> and OptVec<Lifetime>;
- the use of syntax::opt_vec to avoid allocation for empty lists;

cc #4846

r? @graydon
This commit is contained in:
bors 2013-02-27 17:36:41 -08:00
commit d0a12347de
34 changed files with 1070 additions and 722 deletions

View File

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

View File

@ -49,6 +49,8 @@ use syntax::diagnostic::span_handler;
use syntax::parse::token::special_idents;
use syntax::print::pprust;
use syntax::{ast_util, visit};
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax;
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,
params: &[ty_param]) {
fn encode_type_param_bounds(ebml_w: writer::Encoder,
ecx: @EncodeContext,
params: &OptVec<TyParam>) {
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);
}
@ -265,7 +268,7 @@ fn encode_enum_variant_info(ecx: @EncodeContext, ebml_w: writer::Encoder,
id: node_id, variants: &[variant],
path: &[ast_map::path_elt],
index: @mut ~[entry<int>],
ty_params: &[ty_param]) {
generics: &ast::Generics) {
let mut disr_val = 0;
let mut i = 0;
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));
match variant.node.kind {
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);
}
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);
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,
ast_map::path_name(variant.node.name));
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
fn encode_info_for_ctor(ecx: @EncodeContext, ebml_w: writer::Encoder,
id: node_id, ident: ident, path: &[ast_map::path_elt],
item: Option<inlined_item>, tps: &[ty_param]) {
fn encode_info_for_ctor(ecx: @EncodeContext,
ebml_w: writer::Encoder,
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);
encode_name(ecx, ebml_w, ident);
encode_def_id(ebml_w, local_def(id));
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);
debug!("fn name = %s ty = %s its node id = %d",
*ecx.tcx.sess.str_of(ident),
@ -518,9 +525,12 @@ fn encode_info_for_method(ecx: @EncodeContext,
should_inline: bool,
parent_id: node_id,
m: @method,
+all_tps: ~[ty_param]) {
debug!("encode_info_for_method: %d %s %u", m.id,
*ecx.tcx.sess.str_of(m.ident), all_tps.len());
owner_generics: &ast::Generics,
method_generics: &ast::Generics) {
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);
encode_def_id(ebml_w, local_def(m.id));
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))
}
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_name(ecx, ebml_w, 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));
ebml_w.end_tag();
}
item_fn(_, purity, tps, _) => {
item_fn(_, purity, ref generics, _) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, purity_fn_family(purity));
let tps_len = tps.len();
encode_type_param_bounds(ebml_w, ecx, tps);
let tps_len = generics.ty_params.len();
encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
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_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));
ebml_w.end_tag();
}
item_ty(_, tps) => {
item_ty(_, ref generics) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
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_name(ecx, ebml_w, item.ident);
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
encode_region_param(ecx, ebml_w, item);
ebml_w.end_tag();
}
item_enum(ref enum_definition, ref tps) => {
item_enum(ref enum_definition, ref generics) => {
add_to_index();
do ebml_w.wr_tag(tag_items_data_item) {
encode_def_id(ebml_w, local_def(item.id));
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_name(ecx, ebml_w, item.ident);
for (*enum_definition).variants.each |v| {
@ -667,9 +682,9 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
(*enum_definition).variants,
path,
index,
*tps);
generics);
}
item_struct(struct_def, tps) => {
item_struct(struct_def, ref generics) => {
/* First, encode the fields
These come first because we need to write them to make
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) +
~"_dtor"),
path,
if tps.len() > 0u {
if generics.ty_params.len() > 0u {
Some(ii_dtor(copy *dtor,
item.ident,
copy tps,
copy *generics,
local_def(item.id))) }
else {
None
},
tps);
generics);
}
/* Index the class*/
add_to_index();
/* Now, make an item for the class itself */
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
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));
// 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);
ebml_w.end_tag();
}
item_impl(tps, opt_trait, ty, methods) => {
item_impl(ref generics, opt_trait, ty, ref methods) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
encode_family(ebml_w, 'i');
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_name(ecx, ebml_w, item.ident);
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,
should_inline(m.attrs),
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();
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_family(ebml_w, 'I');
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_name(ecx, ebml_w, item.ident);
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_name(ecx, ebml_w, mty.ident);
encode_type_param_bounds(ebml_w, ecx,
(*ty_m).tps);
&ty_m.generics.ty_params);
encode_type(ecx, ebml_w,
ty::mk_bare_fn(tcx, copy mty.fty));
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);
encode_def_id(ebml_w, local_def(m.id));
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,
ty::mk_bare_fn(tcx, copy mty.fty));
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.
for provided_methods.each |m| {
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,
true, item.id, *m, /*bad*/copy m.tps);
true, item.id, *m,
&owner_generics, &m.generics);
}
}
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() });
ebml_w.start_tag(tag_items_data_item);
match /*bad*/copy nitem.node {
foreign_item_fn(_, purity, tps) => {
match nitem.node {
foreign_item_fn(_, purity, ref generics) => {
encode_def_id(ebml_w, local_def(nitem.id));
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));
if abi == foreign_abi_rust_intrinsic {
(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(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_attrs = fld.fold_attributes(/*bad*/copy (*dtor).node.attrs);
let new_params = fold::fold_ty_params(/*bad*/copy *tps, fld);
let dtor_attrs = fld.fold_attributes(copy dtor.node.attrs);
let new_generics = fold::fold_generics(generics, fld);
let dtor_id = fld.new_id((*dtor).node.id);
let new_parent = xcx.tr_def_id(parent_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 },
.. (/*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_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 );
for vec::each(vec::append_one(tys, decl.output)) |ty| {
match ty.node {
@ -786,9 +786,9 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
if attr::foreign_abi(it.attrs) !=
either::Right(ast::foreign_abi_rust_intrinsic) => {
for nmod.items.each |ni| {
match /*bad*/copy ni.node {
ast::foreign_item_fn(decl, _, _) => {
check_foreign_fn(cx, it.id, decl);
match ni.node {
ast::foreign_item_fn(ref decl, _, _) => {
check_foreign_fn(cx, it.id, *decl);
}
// FIXME #4622: Not implemented.
ast::foreign_item_const(*) => {}

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_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);
}
}

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_path, expr_struct, expr_unary, fn_decl};
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::{item_const, item_enum, item_fn, item_foreign_mod};
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::{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_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::{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::{view_item_use, view_path_glob, view_path_list};
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_foreign_item, visit_item, visit_method_helper};
use syntax::visit::{visit_mod, visit_ty, vt};
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
use managed::ptr_eq;
use dvec::DVec;
@ -216,9 +219,9 @@ pub impl<T> ResolveResult<T> {
}
pub enum TypeParameters/& {
NoTypeParameters, //< No type parameters.
HasTypeParameters(&~[ty_param], //< Type parameters.
node_id, //< ID of the enclosing item
NoTypeParameters, //< No type parameters.
HasTypeParameters(&Generics, //< Type parameters.
node_id, //< ID of the enclosing item
// The index to start numbering the type parameters at.
// 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
// outer T had index 0.
uint,
// The kind of the rib used for type parameters.
@ -1500,14 +1502,15 @@ pub impl Resolver {
self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span);
match /*bad*/copy foreign_item.node {
foreign_item_fn(_, _, type_parameters) => {
match foreign_item.node {
foreign_item_fn(_, _, ref generics) => {
let def = def_fn(local_def(foreign_item.id), unsafe_fn);
name_bindings.define_value(Public, def, foreign_item.span);
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, foreign_item.id,
0, NormalRibKind)) {
do self.with_type_parameter_rib(
HasTypeParameters(
generics, foreign_item.id, 0, NormalRibKind))
{
visit_foreign_item(foreign_item, new_parent, visitor);
}
}
@ -3582,8 +3585,7 @@ pub impl Resolver {
// enum item: resolve all the variants' discrs,
// 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| {
do variant.node.disr_expr.iter() |dis_expr| {
// resolve the discriminator expr
@ -3599,14 +3601,14 @@ pub impl Resolver {
// error if there is one? -- tjc
do self.with_type_parameter_rib(
HasTypeParameters(
type_parameters, item.id, 0, NormalRibKind)) {
generics, item.id, 0, NormalRibKind)) {
visit_item(item, (), visitor);
}
}
item_ty(_, type_parameters) => {
item_ty(_, ref generics) => {
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters, item.id, 0,
(HasTypeParameters(generics, item.id, 0,
NormalRibKind))
|| {
@ -3614,20 +3616,20 @@ pub impl Resolver {
}
}
item_impl(type_parameters,
item_impl(ref generics,
implemented_traits,
self_type,
methods) => {
ref methods) => {
self.resolve_implementation(item.id,
item.span,
type_parameters,
generics,
implemented_traits,
self_type,
methods,
*methods,
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.
let self_type_rib = @Rib(NormalRibKind);
(*self.type_ribs).push(self_type_rib);
@ -3636,10 +3638,10 @@ pub impl Resolver {
// Create a new rib for the trait-wide type parameters.
do self.with_type_parameter_rib
(HasTypeParameters(type_parameters, item.id, 0,
(HasTypeParameters(generics, item.id, 0,
NormalRibKind)) {
self.resolve_type_parameters(/*bad*/copy *type_parameters,
self.resolve_type_parameters(&generics.ty_params,
visitor);
// Resolve derived traits.
@ -3672,18 +3674,18 @@ pub impl Resolver {
match *method {
required(ref ty_m) => {
do self.with_type_parameter_rib
(HasTypeParameters(&(*ty_m).tps,
(HasTypeParameters(&ty_m.generics,
item.id,
type_parameters.len(),
generics.ty_params.len(),
MethodRibKind(item.id, Required))) {
// Resolve the method-specific type
// parameters.
self.resolve_type_parameters(
/*bad*/copy (*ty_m).tps,
&ty_m.generics.ty_params,
visitor);
for (*ty_m).decl.inputs.each |argument| {
for ty_m.decl.inputs.each |argument| {
self.resolve_type(argument.ty, visitor);
}
@ -3694,7 +3696,7 @@ pub impl Resolver {
self.resolve_method(MethodRibKind(item.id,
Provided(m.id)),
m,
type_parameters.len(),
generics.ty_params.len(),
visitor)
}
}
@ -3704,12 +3706,12 @@ pub impl Resolver {
(*self.type_ribs).pop();
}
item_struct(struct_def, ty_params) => {
item_struct(struct_def, ref generics) => {
self.resolve_struct(item.id,
@copy ty_params,
/*bad*/copy struct_def.fields,
struct_def.dtor,
visitor);
generics,
struct_def.fields,
struct_def.dtor,
visitor);
}
item_mod(module_) => {
@ -3722,18 +3724,14 @@ pub impl Resolver {
item_foreign_mod(foreign_module) => {
do self.with_scope(Some(item.ident)) {
for foreign_module.items.each |foreign_item| {
match /*bad*/copy foreign_item.node {
foreign_item_fn(_, _, type_parameters) => {
do self.with_type_parameter_rib
(HasTypeParameters(&type_parameters,
foreign_item.id,
0,
OpaqueFunctionRibKind))
|| {
visit_foreign_item(*foreign_item, (),
visitor);
}
match foreign_item.node {
foreign_item_fn(_, _, ref generics) => {
self.with_type_parameter_rib(
HasTypeParameters(
generics, foreign_item.id, 0,
NormalRibKind),
|| visit_foreign_item(*foreign_item, (),
visitor));
}
foreign_item_const(_) => {
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
// session.
// FIXME #4404 android JNI hacks
@ -3771,7 +3769,7 @@ pub impl Resolver {
self.resolve_function(OpaqueFunctionRibKind,
Some(@/*bad*/copy *fn_decl),
HasTypeParameters
(ty_params,
(generics,
item.id,
0,
OpaqueFunctionRibKind),
@ -3798,13 +3796,13 @@ pub impl Resolver {
type_parameters: TypeParameters,
f: fn()) {
match type_parameters {
HasTypeParameters(type_parameters, node_id, initial_index,
HasTypeParameters(generics, node_id, initial_index,
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;
debug!("with_type_parameter_rib: %d %d", node_id,
type_parameter.id);
@ -3815,7 +3813,7 @@ pub impl Resolver {
// the item that bound it
self.record_def(type_parameter.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 {
HasTypeParameters(*) => {
(*self.type_ribs).pop();
self.type_ribs.pop();
}
NoTypeParameters => {
@ -3871,8 +3869,8 @@ pub impl Resolver {
NoTypeParameters => {
// Continue.
}
HasTypeParameters(type_parameters, _, _, _) => {
self.resolve_type_parameters(/*bad*/copy *type_parameters,
HasTypeParameters(ref generics, _, _, _) => {
self.resolve_type_parameters(&generics.ty_params,
visitor);
}
}
@ -3927,7 +3925,7 @@ pub impl Resolver {
}
fn resolve_type_parameters(@mut self,
type_parameters: ~[ty_param],
type_parameters: &OptVec<TyParam>,
visitor: ResolveVisitor) {
for type_parameters.each |type_parameter| {
for type_parameter.bounds.each |&bound| {
@ -3941,19 +3939,17 @@ pub impl Resolver {
fn resolve_struct(@mut self,
id: node_id,
type_parameters: @~[ty_param],
fields: ~[@struct_field],
generics: &Generics,
fields: &[@struct_field],
optional_destructor: Option<struct_dtor>,
visitor: ResolveVisitor) {
// If applicable, create a rib for the type parameters.
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
do self.with_type_parameter_rib(HasTypeParameters
(borrowed_type_parameters, id, 0,
(generics, id, 0,
OpaqueFunctionRibKind)) {
// Resolve the type parameters.
self.resolve_type_parameters(/*bad*/copy *type_parameters,
visitor);
self.resolve_type_parameters(&generics.ty_params, visitor);
// Resolve fields.
for fields.each |field| {
@ -3986,9 +3982,9 @@ pub impl Resolver {
method: @method,
outer_type_parameter_count: uint,
visitor: ResolveVisitor) {
let borrowed_method_type_parameters = &method.tps;
let method_generics = &method.generics;
let type_parameters =
HasTypeParameters(borrowed_method_type_parameters,
HasTypeParameters(method_generics,
method.id,
outer_type_parameter_count,
rib_kind);
@ -4010,19 +4006,18 @@ pub impl Resolver {
fn resolve_implementation(@mut self,
id: node_id,
span: span,
type_parameters: ~[ty_param],
generics: &Generics,
opt_trait_reference: Option<@trait_ref>,
self_type: @Ty,
methods: ~[@method],
visitor: ResolveVisitor) {
// If applicable, create a rib for the type parameters.
let outer_type_parameter_count = type_parameters.len();
let borrowed_type_parameters: &~[ty_param] = &type_parameters;
let outer_type_parameter_count = generics.ty_params.len();
do self.with_type_parameter_rib(HasTypeParameters
(borrowed_type_parameters, id, 0,
(generics, id, 0,
NormalRibKind)) {
// Resolve the type parameters.
self.resolve_type_parameters(/*bad*/copy type_parameters,
self.resolve_type_parameters(&generics.ty_params,
visitor);
// 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) => {
meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None,
item.id);
ast::item_impl(ref generics, _, _, ref ms) => {
meth::trans_impl(ccx, /*bad*/copy *path, item.ident, *ms,
generics, None, item.id);
}
ast::item_mod(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: _,
ty: _
} = 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 path = vec::append(
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()`.
*/
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) {
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));
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 path = vec::append_one(/*bad*/copy sub_path,
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);
if m_id.crate == ast::local_crate {
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 => {
match ccx.tcx.provided_method_sources.find(&m_id) {
Some(source) => {
@ -420,9 +420,9 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id,
None => fail!()
}
}
Some(ast_map::node_trait_method(@ast::provided(@ref m), _, _))
=> {
m.tps.len()
Some(ast_map::node_trait_method(@ast::provided(@ref m),
_, _)) => {
m.generics.ty_params.len()
}
copy e => fail!(fmt!("method_ty_param_count %?", e))
}

View File

@ -97,38 +97,41 @@ fn traverse_public_mod(cx: ctx, mod_id: node_id, m: _mod) {
fn traverse_public_item(cx: ctx, item: @item) {
if cx.rmap.contains_key(&item.id) { return; }
cx.rmap.insert(item.id, ());
match /*bad*/copy item.node {
item_mod(m) => traverse_public_mod(cx, item.id, m),
item_foreign_mod(nm) => {
match item.node {
item_mod(ref m) => traverse_public_mod(cx, item.id, *m),
item_foreign_mod(ref nm) => {
if !traverse_exports(cx, item.id) {
for vec::each(nm.items) |item| {
cx.rmap.insert(item.id, ());
}
}
}
item_fn(_, _, ref tps, ref blk) => {
if tps.len() > 0u ||
item_fn(_, _, ref generics, ref blk) => {
if generics.ty_params.len() > 0u ||
attr::find_inline_attr(item.attrs) != attr::ia_none {
traverse_inline_body(cx, (*blk));
}
}
item_impl(tps, _, _, ms) => {
for vec::each(ms) |m| {
if tps.len() > 0u || m.tps.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none {
item_impl(ref generics, _, _, ref ms) => {
for ms.each |m| {
if generics.ty_params.len() > 0u ||
m.generics.ty_params.len() > 0u ||
attr::find_inline_attr(m.attrs) != attr::ia_none
{
cx.rmap.insert(m.id, ());
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| {
cx.rmap.insert(ctor_id, ());
}
do option::iter(&struct_def.dtor) |dtor| {
cx.rmap.insert(dtor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)
!= attr::ia_none {
if generics.ty_params.len() > 0u ||
attr::find_inline_attr(dtor.node.attrs) != attr::ia_none
{
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)];
}
pub fn ty_params_to_tys(tcx: ty::ctxt, tps: ~[ast::ty_param]) -> ~[t] {
vec::from_fn(tps.len(), |i| {
ty::mk_param(tcx, i, ast_util::local_def(tps[i].id))
})
pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
vec::from_fn(generics.ty_params.len(), |i| {
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.

View File

@ -127,6 +127,8 @@ use syntax::codemap;
use syntax::parse::token::special_idents;
use syntax::print::pprust;
use syntax::visit;
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
use syntax;
pub mod _match;
@ -593,9 +595,9 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
ast::item_struct(struct_def, _) => {
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);
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
match t.node {
ast::ty_rec(ref fields) => {
@ -1063,8 +1065,9 @@ pub fn impl_self_ty(vcx: &VtableContext,
node: ast::item_impl(ref ts, _, st, _),
_
}, _)) => {
(ts.len(), region_param,
vcx.ccx.to_ty(rscope::type_rscope(region_param), st))
(ts.ty_params.len(),
region_param,
vcx.ccx.to_ty(rscope::type_rscope(region_param), st))
}
Some(ast_map::node_item(@ast::item {
node: ast::item_struct(_, ref ts),
@ -1075,12 +1078,13 @@ pub fn impl_self_ty(vcx: &VtableContext,
(doing a no-op subst for the ty params; in the next step,
we substitute in fresh vars for them)
*/
(ts.len(), region_param,
ty::mk_struct(tcx, local_def(class_id),
(ts.ty_params.len(),
region_param,
ty::mk_struct(tcx, local_def(class_id),
substs {
self_r: rscope::bound_self_region(region_param),
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 \
@ -1863,11 +1867,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
tcx.region_paramd_items.find(&class_id.node);
match tcx.items.find(&class_id.node) {
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 =
bound_self_region(region_parameterized);
@ -1877,7 +1881,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
self_ty: None,
tps: ty::ty_params_to_tys(
tcx,
/*bad*/copy *type_parameters)
generics)
});
}
_ => {
@ -1947,11 +1951,11 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
tcx.region_paramd_items.find(&enum_id.node);
match tcx.items.find(&enum_id.node) {
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 =
bound_self_region(region_parameterized);
@ -1961,7 +1965,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
self_ty: None,
tps: ty::ty_params_to_tys(
tcx,
/*bad*/copy *type_parameters)
generics)
});
}
_ => {
@ -3127,7 +3131,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,
span: span,
tps: ~[ast::ty_param],
tps: &OptVec<ast::TyParam>,
ty: ty::t) {
debug!("check_bounds_are_used(n_tps=%u, ty=%s)",
tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
@ -3154,7 +3158,7 @@ pub fn check_bounds_are_used(ccx: @mut CrateCtxt,
if !*b {
ccx.tcx.sess.span_err(
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 {
@MethodInfo {
did: local_def(ast_method.id),
n_tps: ast_method.tps.len(),
n_tps: ast_method.generics.ty_params.len(),
ident: ast_method.ident,
self_type: ast_method.self_ty.node
}

View File

@ -60,6 +60,8 @@ use syntax::codemap::span;
use syntax::codemap;
use syntax::print::pprust::path_to_str;
use syntax::visit;
use syntax::opt_vec;
use syntax::opt_vec::OptVec;
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
== ::syntax::parse::token::special_idents::intrinsic {
match /*bad*/copy crate_item.node {
ast::item_mod(m) => {
match crate_item.node {
ast::item_mod(ref m) => {
for m.items.each |intrinsic_item| {
let def_id = ast::def_id { crate: ast::local_crate,
node: intrinsic_item.id };
@ -153,7 +155,7 @@ impl AstConv for CrateCtxt {
pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
enum_ty: ty::t,
variants: &[ast::variant],
+ty_params: ~[ast::ty_param],
generics: &ast::Generics,
rp: Option<ty::region_variance>) {
let tcx = ccx.tcx;
@ -175,7 +177,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
ast::struct_variant_kind(struct_def) => {
let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, ty_params),
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
ty: enum_ty
};
@ -183,7 +185,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
convert_struct(ccx,
rp,
struct_def,
ty_params.to_vec(),
generics,
tpt,
variant.node.id);
@ -196,7 +198,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
get_enum_variant_types(ccx,
enum_ty,
enum_definition.variants,
copy ty_params,
generics,
rp);
result_ty = None;
}
@ -206,7 +208,7 @@ pub fn get_enum_variant_types(ccx: @mut CrateCtxt,
None => {}
Some(result_ty) => {
let tpt = ty_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, ty_params),
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
ty: result_ty
};
@ -276,7 +278,7 @@ pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
let region_paramd = tcx.region_paramd_items.find(&id);
match tcx.items.get(&id) {
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| {
@ -288,7 +290,7 @@ pub fn ensure_trait_methods(ccx: @mut CrateCtxt,
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 method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
if ty_m.self_ty.node == ast::sty_static {
@ -488,7 +490,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
}
pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
tps: ~[ast::ty_param],
generics: &ast::Generics,
rp: Option<ty::region_variance>,
selfty: ty::t,
a_trait_ty: @ast::trait_ref,
@ -522,8 +524,9 @@ pub fn check_methods_against_trait(ccx: @mut CrateCtxt,
for impl_ms.each |impl_m| {
match trait_ms.find(|trait_m| trait_m.ident == impl_m.mty.ident) {
Some(ref trait_m) => {
let num_impl_tps = generics.ty_params.len();
compare_impl_method(
ccx.tcx, tps.len(), impl_m, trait_m,
ccx.tcx, num_impl_tps, impl_m, trait_m,
&tpt.substs, selfty);
}
None => {
@ -568,7 +571,7 @@ pub fn convert_methods(ccx: @mut CrateCtxt,
let tcx = ccx.tcx;
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 fty = ty::mk_bare_fn(tcx, copy mty.fty);
tcx.tcache.insert(
@ -589,9 +592,9 @@ pub fn convert_methods(ccx: @mut CrateCtxt,
pub fn ensure_no_ty_param_bounds(ccx: @mut CrateCtxt,
span: span,
ty_params: &[ast::ty_param],
generics: &ast::Generics,
thing: &static/str) {
for ty_params.each |ty_param| {
for generics.ty_params.each |ty_param| {
if ty_param.bounds.len() > 0 {
ccx.tcx.sess.span_err(
span,
@ -606,21 +609,21 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
let rp = tcx.region_paramd_items.find(&it.id);
debug!("convert: item %s with id %d rp %?",
*tcx.sess.str_of(it.ident), it.id, rp);
match /*bad*/copy it.node {
match it.node {
// These don't define types.
ast::item_foreign_mod(_) | ast::item_mod(_) => {}
ast::item_enum(ref enum_definition, ref ty_params) => {
ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration");
ast::item_enum(ref enum_definition, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
get_enum_variant_types(ccx,
tpt.ty,
enum_definition.variants,
copy *ty_params,
generics,
rp);
}
ast::item_impl(ref tps, trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, *tps);
ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
let i_bounds = ty_param_bounds(ccx, generics);
let selfty = ccx.to_ty(type_rscope(rp), selfty);
write_ty_to_tcx(tcx, it.id, selfty);
tcx.tcache.insert(local_def(it.id),
@ -632,11 +635,11 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
// XXX: Bad copy of `ms` below.
let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds);
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);
}
}
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);
debug!("item_trait(it.id=%d, tpt.ty=%s)",
it.id, ppaux::ty_to_str(tcx, tpt.ty));
@ -646,21 +649,21 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
let (_, provided_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);
}
ast::item_struct(struct_def, tps) => {
ensure_no_ty_param_bounds(ccx, it.span, tps, "structure");
ast::item_struct(struct_def, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
// Write the class type
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
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) => {
ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "type");
ast::item_ty(_, ref generics) => {
ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
let tpt = ty_of_item(ccx, it);
write_ty_to_tcx(tcx, it.id, tpt.ty);
}
@ -677,7 +680,7 @@ pub fn convert(ccx: @mut CrateCtxt, it: @ast::item) {
pub fn convert_struct(ccx: @mut CrateCtxt,
rp: Option<ty::region_variance>,
struct_def: @ast::struct_def,
+tps: ~[ast::ty_param],
generics: &ast::Generics,
tpt: ty::ty_param_bounds_and_ty,
id: ast::node_id) {
let tcx = ccx.tcx;
@ -702,7 +705,7 @@ pub fn convert_struct(ccx: @mut CrateCtxt,
for struct_def.fields.each |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);
// If this struct is enum-like or tuple-like, create the type of its
@ -746,7 +749,7 @@ pub fn ty_of_method(ccx: @mut CrateCtxt,
rp: Option<ty::region_variance>) -> ty::method {
ty::method {
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,
ast::RustAbi, m.decl),
self_ty: m.self_ty.node,
@ -761,7 +764,7 @@ pub fn ty_of_ty_method(self: @mut CrateCtxt,
id: ast::def_id) -> ty::method {
ty::method {
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,
ast::RustAbi, m.decl),
// assume public, because this is only invoked on trait methods
@ -809,17 +812,17 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
_ => {}
}
let rp = tcx.region_paramd_items.find(&it.id);
match /*bad*/copy it.node {
match it.node {
ast::item_const(t, _) => {
let typ = ccx.to_ty(empty_rscope, t);
let tpt = no_params(typ);
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_fn(decl, purity, tps, _) => {
let bounds = ty_param_bounds(ccx, tps);
ast::item_fn(ref decl, purity, ref generics, _) => {
let bounds = ty_param_bounds(ccx, generics);
let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity,
ast::RustAbi, decl);
ast::RustAbi, *decl);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
region_param: None,
@ -832,7 +835,7 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
ccx.tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_ty(t, tps) => {
ast::item_ty(t, ref generics) => {
match tcx.tcache.find(&local_def(it.id)) {
Some(tpt) => return tpt,
None => { }
@ -846,12 +849,12 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
// like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to
// 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_param_bounds_and_ty {
bounds: ty_param_bounds(ccx, tps),
bounds: ty_param_bounds(ccx, generics),
region_param: rp,
ty: ty
}
@ -860,9 +863,9 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_enum(_, tps) => {
ast::item_enum(_, ref generics) => {
// 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 tpt = ty_param_bounds_and_ty {
bounds: bounds,
@ -872,8 +875,8 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_trait(tps, _, _) => {
let (bounds, substs) = mk_substs(ccx, tps, rp);
ast::item_trait(ref generics, _, _) => {
let (bounds, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_trait(tcx, local_def(it.id), substs, ty::vstore_box);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
@ -883,8 +886,8 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
tcx.tcache.insert(local_def(it.id), tpt);
return tpt;
}
ast::item_struct(_, tps) => {
let (bounds, substs) = mk_substs(ccx, tps, rp);
ast::item_struct(_, ref generics) => {
let (bounds, substs) = mk_substs(ccx, generics, rp);
let t = ty::mk_struct(tcx, local_def(it.id), substs);
let tpt = ty_param_bounds_and_ty {
bounds: bounds,
@ -902,9 +905,10 @@ pub fn ty_of_item(ccx: @mut CrateCtxt, it: @ast::item)
pub fn ty_of_foreign_item(ccx: @mut CrateCtxt, it: @ast::foreign_item)
-> ty::ty_param_bounds_and_ty {
match /*bad*/copy it.node {
ast::foreign_item_fn(fn_decl, _, params) => {
return ty_of_foreign_fn_decl(ccx, fn_decl, params, local_def(it.id));
match it.node {
ast::foreign_item_fn(ref fn_decl, _, ref generics) => {
return ty_of_foreign_fn_decl(ccx, *fn_decl, local_def(it.id),
generics);
}
ast::foreign_item_const(t) => {
let rb = in_binding_rscope(empty_rscope);
@ -922,9 +926,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
// known as kinds): Const, Copy, Durable, and Send.
pub fn compute_bounds(ccx: @mut CrateCtxt,
ast_bounds: @~[ast::ty_param_bound])
ast_bounds: @OptVec<ast::TyParamBound>)
-> ty::param_bounds {
@do vec::flat_map(*ast_bounds) |b| {
@ast_bounds.flat_map_to_vec(|b| {
match b {
&TraitTyParamBound(b) => {
let li = &ccx.tcx.lang_items;
@ -954,13 +958,13 @@ pub fn compute_bounds(ccx: @mut CrateCtxt,
}
&RegionTyParamBound => ~[ty::bound_durable]
}
}
})
}
pub fn ty_param_bounds(ccx: @mut CrateCtxt,
params: ~[ast::ty_param])
generics: &ast::Generics)
-> @~[ty::param_bounds] {
@do params.map |param| {
@do generics.ty_params.map_to_vec |param| {
match ccx.tcx.ty_param_bounds.find(&param.id) {
Some(bs) => bs,
None => {
@ -974,10 +978,10 @@ pub fn ty_param_bounds(ccx: @mut CrateCtxt,
pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
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 {
let bounds = ty_param_bounds(ccx, ty_params);
let bounds = ty_param_bounds(ccx, generics);
let rb = in_binding_rscope(empty_rscope);
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);
@ -998,13 +1002,13 @@ pub fn ty_of_foreign_fn_decl(ccx: @mut CrateCtxt,
return tpt;
}
pub fn mk_ty_params(ccx: @mut CrateCtxt, atps: ~[ast::ty_param])
-> (@~[ty::param_bounds], ~[ty::t]) {
pub fn mk_generics(ccx: @mut CrateCtxt, generics: &ast::Generics)
-> (@~[ty::param_bounds], ~[ty::t])
{
let mut i = 0u;
let bounds = ty_param_bounds(ccx, atps);
let bounds = ty_param_bounds(ccx, generics);
(bounds,
vec::map(atps, |atp| {
generics.ty_params.map_to_vec(|atp| {
let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
i += 1u;
t
@ -1012,10 +1016,11 @@ pub fn mk_ty_params(ccx: @mut CrateCtxt, atps: ~[ast::ty_param])
}
pub fn mk_substs(ccx: @mut CrateCtxt,
+atps: ~[ast::ty_param],
generics: &ast::Generics,
rp: Option<ty::region_variance>)
-> (@~[ty::param_bounds], ty::substs) {
let (bounds, params) = mk_ty_params(ccx, atps);
-> (@~[ty::param_bounds], ty::substs)
{
let (bounds, params) = mk_generics(ccx, generics);
let self_r = rscope::bound_self_region(rp);
(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,
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()))
}
_ => fail!(~"get_fn_sig: fn_id not bound to a fn item")
@ -215,7 +215,7 @@ fn get_method_sig(
Some(pprust::fun_to_str(
ty_m.decl,
ty_m.ident,
copy ty_m.tps,
&ty_m.generics,
extract::interner()
))
}
@ -223,7 +223,7 @@ fn get_method_sig(
Some(pprust::fun_to_str(
m.decl,
m.ident,
copy m.tps,
&m.generics,
extract::interner()
))
}
@ -242,7 +242,7 @@ fn get_method_sig(
Some(pprust::fun_to_str(
method.decl,
method.ident,
copy method.tps,
&method.generics,
extract::interner()
))
}
@ -339,7 +339,7 @@ fn fold_type(
Some(fmt!(
"type %s%s = %s",
to_str(ident),
pprust::typarams_to_str(*params,
pprust::generics_to_str(params,
extract::interner()),
pprust::ty_to_str(ty,
extract::interner())

View File

@ -21,6 +21,8 @@ use core::to_bytes;
use core::to_str::ToStr;
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
* there. */
macro_rules! interner_key (
@ -96,6 +98,9 @@ impl to_bytes::IterBytes for ident {
// Functions may or may not have names.
pub type fn_ident = Option<ident>;
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub struct Lifetime {
id: node_id,
span: span,
@ -135,7 +140,7 @@ pub const crate_node_id: node_id = 0;
// typeck::collect::compute_bounds matches these against
// the "special" built-in traits (see middle::lang_items) and
// detects Copy, Send, Owned, and Const.
pub enum ty_param_bound {
pub enum TyParamBound {
TraitTyParamBound(@Ty),
RegionTyParamBound
}
@ -143,10 +148,24 @@ pub enum ty_param_bound {
#[auto_encode]
#[auto_decode]
#[deriving_eq]
pub struct ty_param {
pub struct TyParam {
ident: ident,
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]
@ -273,8 +292,8 @@ pub enum pat_ {
// records this pattern's node_id in an auxiliary
// set (of "pat_idents that refer to nullary enums")
pat_ident(binding_mode, @path, Option<@pat>),
pat_enum(@path, Option<~[@pat]>), // "none" means a * pattern where
// we don't bind the fields to names
pat_enum(@path, Option<~[@pat]>), /* "none" means a * pattern where
* we don't bind the fields to names */
pat_rec(~[field_pat], bool),
pat_struct(@path, ~[field_pat], bool),
pat_tup(~[@pat]),
@ -749,7 +768,7 @@ pub struct ty_method {
attrs: ~[attribute],
purity: purity,
decl: fn_decl,
tps: ~[ty_param],
generics: Generics,
self_ty: self_ty,
id: node_id,
span: span,
@ -1012,7 +1031,7 @@ pub type self_ty = spanned<self_ty_>;
pub struct method {
ident: ident,
attrs: ~[attribute],
tps: ~[ty_param],
generics: Generics,
self_ty: self_ty,
purity: purity,
decl: fn_decl,
@ -1248,14 +1267,14 @@ pub struct item {
#[deriving_eq]
pub enum item_ {
item_const(@Ty, @expr),
item_fn(fn_decl, purity, ~[ty_param], blk),
item_fn(fn_decl, purity, Generics, blk),
item_mod(_mod),
item_foreign_mod(foreign_mod),
item_ty(@Ty, ~[ty_param]),
item_enum(enum_def, ~[ty_param]),
item_struct(@struct_def, ~[ty_param]),
item_trait(~[ty_param], ~[@trait_ref], ~[trait_method]),
item_impl(~[ty_param],
item_ty(@Ty, Generics),
item_enum(enum_def, Generics),
item_struct(@struct_def, Generics),
item_trait(Generics, ~[@trait_ref], ~[trait_method]),
item_impl(Generics,
Option<@trait_ref>, // (optional) trait this impl implements
@Ty, // self
~[@method]),
@ -1302,7 +1321,7 @@ pub struct foreign_item {
#[auto_decode]
#[deriving_eq]
pub enum foreign_item_ {
foreign_item_fn(fn_decl, purity, ~[ty_param]),
foreign_item_fn(fn_decl, purity, Generics),
foreign_item_const(@Ty)
}
@ -1316,7 +1335,7 @@ pub enum inlined_item {
ii_item(@item),
ii_method(def_id /* impl id */, @method),
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)]

View File

@ -101,7 +101,7 @@ pub enum ast_node {
node_arg(arg, uint),
node_local(uint),
// 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_struct_ctor(@struct_def, @item, @path),
}

View File

@ -16,6 +16,7 @@ use ast_util;
use codemap::{span, BytePos, dummy_sp};
use parse::token;
use visit;
use opt_vec;
use core::cmp;
use core::int;
@ -263,13 +264,13 @@ pub fn public_methods(ms: ~[@method]) -> ~[@method] {
pub fn trait_method_to_ty_method(method: trait_method) -> ty_method {
match method {
required(ref m) => (*m),
provided(m) => {
provided(ref m) => {
ty_method {
ident: m.ident,
attrs: m.attrs,
purity: m.purity,
decl: m.decl,
tps: m.tps,
generics: copy m.generics,
self_ty: m.self_ty,
id: m.id,
span: m.span,
@ -327,8 +328,9 @@ impl inlined_item_utils for inlined_item {
ii_item(i) => (v.visit_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_dtor(/*bad*/ copy dtor, _, /*bad*/ copy tps, parent_id) => {
visit::visit_struct_dtor_helper(dtor, tps, parent_id, e, v);
ii_dtor(/*bad*/ copy dtor, _, ref generics, parent_id) => {
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
@ -390,6 +397,14 @@ pub fn empty(range: id_range) -> bool {
}
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_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]) {
for vec::each(ps) |p| {
vfn(p.id);
}
},
visit_generics: visit_generics,
visit_fn: fn@(fk: visit::fn_kind, d: ast::fn_decl,
_b: ast::blk, _sp: span, id: ast::node_id) {
vfn(id);
match fk {
visit::fk_dtor(tps, _, self_id, parent_id) => {
for vec::each(tps) |tp| { vfn(tp.id); }
visit::fk_dtor(ref generics, _, self_id, parent_id) => {
visit_generics(generics);
vfn(id);
vfn(self_id);
vfn(parent_id.node);
}
visit::fk_item_fn(_, tps, _) => {
for vec::each(tps) |tp| { vfn(tp.id); }
visit::fk_item_fn(_, ref generics, _) => {
visit_generics(generics);
}
visit::fk_method(_, tps, m) => {
visit::fk_method(_, ref generics, m) => {
vfn(m.self_id);
for vec::each(tps) |tp| { vfn(tp.id); }
visit_generics(generics);
}
visit::fk_anon(_) |
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_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) {
},

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*
/*!
The compiler code necessary to implement the #[auto_encode] and
#[auto_decode] extension. The idea here is that type-defining items may
@ -96,6 +96,9 @@ use attr;
use codemap::span;
use ext::base::*;
use parse;
use opt_vec;
use opt_vec::OptVec;
use ext::build;
use core::vec;
use std::oldmap;
@ -127,24 +130,24 @@ pub fn expand_auto_encode(
do vec::flat_map(in_items) |item| {
if item.attrs.any(is_auto_encode) {
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(
cx,
item.span,
item.ident,
struct_def.fields,
*tps
generics
);
~[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(
cx,
item.span,
item.ident,
*enum_def,
*tps
generics
);
~[filter_attrs(*item), ser_impl]
@ -182,24 +185,24 @@ pub fn expand_auto_decode(
do vec::flat_map(in_items) |item| {
if item.attrs.any(is_auto_decode) {
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(
cx,
item.span,
item.ident,
struct_def.fields,
*tps
generics
);
~[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(
cx,
item.span,
item.ident,
*enum_def,
*tps
generics
);
~[filter_attrs(*item), deser_impl]
@ -222,18 +225,18 @@ priv impl ext_ctxt {
span: span,
ident: ast::ident,
path: @ast::path,
bounds: @~[ast::ty_param_bound]
) -> ast::ty_param {
bounds: @OptVec<ast::TyParamBound>
) -> ast::TyParam {
let bound = ast::TraitTyParamBound(@ast::Ty {
id: self.next_id(),
node: ast::ty_path(path, self.next_id()),
span: span,
});
ast::ty_param {
ast::TyParam {
ident: ident,
id: self.next_id(),
bounds: @vec::append(~[bound], *bounds)
bounds: @bounds.prepend(bound)
}
}
@ -408,28 +411,45 @@ fn mk_impl(
cx: ext_ctxt,
span: span,
ident: ast::ident,
ty_param: ast::ty_param,
ty_param: ast::TyParam,
path: @ast::path,
tps: &[ast::ty_param],
generics: &ast::Generics,
f: fn(@ast::Ty) -> @ast::method
) -> @ast::item {
// All the type parameters need to bound to the trait.
let mut trait_tps = vec::append(
~[ty_param],
do tps.map |tp| {
let t_bound = ast::TraitTyParamBound(@ast::Ty {
id: cx.next_id(),
node: ast::ty_path(path, cx.next_id()),
span: span,
});
/*!
*
* Given that we are deriving auto-encode a type `T<'a, ...,
* 'z, A, ..., Z>`, creates an impl like:
*
* impl<'a, ..., 'z, A:Tr, ..., Z:Tr> Tr for T<A, ..., Z> { ... }
*
* 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,
id: cx.next_id(),
bounds: @vec::append(~[t_bound], *tp.bounds)
}
}
);
// Copy the lifetimes
let impl_lifetimes = generics.lifetimes.map(|l| {
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 {
path: path,
@ -439,16 +459,22 @@ fn mk_impl(
let ty = cx.ty_path(
span,
~[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 {
// This is a new-style impl declaration.
// XXX: clownshoes
ident: parse::token::special_idents::clownshoes_extensions,
attrs: ~[],
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,
span: span,
}
@ -458,7 +484,7 @@ fn mk_ser_impl(
cx: ext_ctxt,
span: span,
ident: ast::ident,
tps: &[ast::ty_param],
generics: &ast::Generics,
body: @ast::expr
) -> @ast::item {
// Make a path to the std::serialize::Encodable typaram.
@ -473,7 +499,7 @@ fn mk_ser_impl(
cx.ident_of(~"Encoder"),
]
),
@~[]
@opt_vec::Empty
);
// Make a path to the std::serialize::Encodable trait.
@ -493,7 +519,7 @@ fn mk_ser_impl(
ident,
ty_param,
path,
tps,
generics,
|_ty| mk_ser_method(cx, span, cx.expr_blk(body))
)
}
@ -502,7 +528,7 @@ fn mk_deser_impl(
cx: ext_ctxt,
span: span,
ident: ast::ident,
tps: ~[ast::ty_param],
generics: &ast::Generics,
body: @ast::expr
) -> @ast::item {
// Make a path to the std::serialize::Decodable typaram.
@ -517,7 +543,7 @@ fn mk_deser_impl(
cx.ident_of(~"Decoder"),
]
),
@~[]
@opt_vec::Empty
);
// Make a path to the std::serialize::Decodable trait.
@ -537,7 +563,7 @@ fn mk_deser_impl(
ident,
ty_param,
path,
tps,
generics,
|ty| mk_deser_method(cx, span, ty, cx.expr_blk(body))
)
}
@ -592,7 +618,7 @@ fn mk_ser_method(
@ast::method {
ident: cx.ident_of(~"encode"),
attrs: ~[],
tps: ~[],
generics: ast_util::empty_generics(),
self_ty: codemap::spanned { node: ast::sty_region(ast::m_imm),
span: span },
purity: ast::impure_fn,
@ -650,7 +676,7 @@ fn mk_deser_method(
@ast::method {
ident: cx.ident_of(~"decode"),
attrs: ~[],
tps: ~[],
generics: ast_util::empty_generics(),
self_ty: codemap::spanned { node: ast::sty_static, span: span },
purity: ast::impure_fn,
decl: deser_decl,
@ -667,7 +693,7 @@ fn mk_struct_ser_impl(
span: span,
ident: ast::ident,
fields: &[@ast::struct_field],
tps: &[ast::ty_param]
generics: &ast::Generics
) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| self.$(name).encode(__s)`
@ -720,7 +746,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(
@ -728,7 +754,7 @@ fn mk_struct_deser_impl(
span: span,
ident: ast::ident,
fields: ~[@ast::struct_field],
tps: ~[ast::ty_param]
generics: &ast::Generics
) -> @ast::item {
let fields = do mk_struct_fields(fields).mapi |idx, field| {
// ast for `|| std::serialize::decode(__d)`
@ -796,7 +822,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
@ -832,7 +858,7 @@ fn mk_enum_ser_impl(
span: span,
ident: ast::ident,
enum_def: ast::enum_def,
tps: ~[ast::ty_param]
generics: &ast::Generics
) -> @ast::item {
let body = mk_enum_ser_body(
cx,
@ -841,7 +867,7 @@ fn mk_enum_ser_impl(
enum_def.variants
);
mk_ser_impl(cx, span, ident, tps, body)
mk_ser_impl(cx, span, ident, generics, body)
}
fn mk_enum_deser_impl(
@ -849,7 +875,7 @@ fn mk_enum_deser_impl(
span: span,
ident: ast::ident,
enum_def: ast::enum_def,
tps: ~[ast::ty_param]
generics: &ast::Generics
) -> @ast::item {
let body = mk_enum_deser_body(
cx,
@ -858,7 +884,7 @@ fn mk_enum_deser_impl(
enum_def.variants
);
mk_deser_impl(cx, span, ident, tps, body)
mk_deser_impl(cx, span, ident, generics, body)
}
fn ser_variant(

View File

@ -16,6 +16,9 @@ use codemap::span;
use ext::base::ext_ctxt;
use ext::build;
use opt_vec;
use opt_vec::OptVec;
use core::dvec;
use core::option;
@ -354,8 +357,14 @@ pub fn mk_fn_decl(+inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl {
}
pub fn mk_ty_param(cx: ext_ctxt,
ident: ast::ident,
bounds: @~[ast::ty_param_bound])
-> ast::ty_param {
ast::ty_param { ident: ident, id: cx.next_id(), bounds: bounds }
bounds: @OptVec<ast::TyParamBound>)
-> ast::TyParam {
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::{TraitTyParamBound, Ty, and, bind_by_ref, binop, deref, enum_def};
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::{re_anon, stmt, struct_def, struct_variant_kind};
use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, ty_param};
use ast::{ty_param_bound, ty_path, ty_rptr, unnamed_field, variant};
use ast::{sty_by_ref, sty_region, tuple_variant_kind, ty_nil, TyParam};
use ast::{TyParamBound, ty_path, ty_rptr, unnamed_field, variant};
use ext::base::ext_ctxt;
use ext::build;
use codemap::{span, spanned};
use parse::token::special_idents::clownshoes_extensions;
use ast_util;
use opt_vec;
use opt_vec::OptVec;
use core::dvec;
use core::uint;
@ -47,13 +51,13 @@ type ExpandDerivingStructDefFn = &fn(ext_ctxt,
span,
x: &struct_def,
ident,
+y: ~[ty_param])
y: &Generics)
-> @item;
type ExpandDerivingEnumDefFn = &fn(ext_ctxt,
span,
x: &enum_def,
ident,
+y: ~[ty_param])
y: &Generics)
-> @item;
pub fn expand_deriving_eq(cx: ext_ctxt,
@ -90,19 +94,19 @@ fn expand_deriving(cx: ext_ctxt,
for in_items.each |item| {
result.push(copy *item);
match item.node {
item_struct(struct_def, copy ty_params) => {
item_struct(struct_def, ref generics) => {
result.push(expand_deriving_struct_def(cx,
span,
struct_def,
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,
span,
enum_definition,
item.ident,
ty_params));
generics));
}
_ => ()
}
@ -127,14 +131,14 @@ fn create_eq_method(cx: ext_ctxt,
span: span,
method_ident: ident,
type_ident: ident,
ty_params: &[ty_param],
generics: &Generics,
body: @expr)
-> @method {
// Create the type of the `other` parameter.
let arg_path_type = create_self_type_with_params(cx,
span,
type_ident,
ty_params);
generics);
let arg_region = @ast::region { id: cx.next_id(), node: re_anon };
let arg_type = ty_rptr(
arg_region,
@ -171,7 +175,7 @@ fn create_eq_method(cx: ext_ctxt,
@ast::method {
ident: method_ident,
attrs: ~[],
tps: ~[],
generics: ast_util::empty_generics(),
self_ty: self_ty,
purity: pure_fn,
decl: fn_decl,
@ -186,11 +190,11 @@ fn create_eq_method(cx: ext_ctxt,
fn create_self_type_with_params(cx: ext_ctxt,
span: span,
type_ident: ident,
ty_params: &[ty_param])
generics: &Generics)
-> @Ty {
// Create the type parameters on the `self` path.
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,
span,
ty_param.ident);
@ -209,21 +213,34 @@ fn create_self_type_with_params(cx: ext_ctxt,
fn create_derived_impl(cx: ext_ctxt,
span: span,
type_ident: ident,
+ty_params: ~[ty_param],
generics: &Generics,
methods: &[@method],
trait_path: &[ident])
-> @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.
let impl_ty_params = dvec::DVec();
for ty_params.each |ty_param| {
let impl_ty_params = generics.ty_params.map(|ty_param| {
let bound = build::mk_ty_path_global(cx,
span,
trait_path.map(|x| *x));
let bounds = @~[ TraitTyParamBound(bound) ];
let impl_ty_param = 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);
let bounds = @opt_vec::with(TraitTyParamBound(bound));
build::mk_ty_param(cx, ty_param.ident, bounds)
});
// Create the reference to the trait.
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,
span,
type_ident,
ty_params);
generics);
// 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),
self_type,
methods.map(|x| *x));
@ -257,7 +275,7 @@ fn create_derived_impl(cx: ext_ctxt,
fn create_derived_eq_impl(cx: ext_ctxt,
span: span,
type_ident: ident,
+ty_params: ~[ty_param],
generics: &Generics,
eq_method: @method,
ne_method: @method)
-> @item {
@ -267,13 +285,13 @@ fn create_derived_eq_impl(cx: ext_ctxt,
cx.ident_of(~"cmp"),
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,
span: span,
type_ident: ident,
+ty_params: ~[ty_param],
generics: &Generics,
method: @method)
-> @item {
let methods = [ method ];
@ -282,7 +300,7 @@ fn create_derived_iter_bytes_impl(cx: ext_ctxt,
cx.ident_of(~"to_bytes"),
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
@ -322,7 +340,7 @@ fn create_iter_bytes_method(cx: ext_ctxt,
@ast::method {
ident: method_ident,
attrs: ~[],
tps: ~[],
generics: ast_util::empty_generics(),
self_ty: self_ty,
purity: pure_fn,
decl: fn_decl,
@ -484,7 +502,7 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
span: span,
struct_def: &struct_def,
type_ident: ident,
+ty_params: ~[ty_param])
generics: &Generics)
-> @item {
// Create the methods.
let eq_ident = cx.ident_of(~"eq");
@ -510,21 +528,21 @@ fn expand_deriving_eq_struct_def(cx: ext_ctxt,
struct_def,
eq_ident,
type_ident,
ty_params,
generics,
Conjunction);
let ne_method = derive_struct_fn(cx,
span,
struct_def,
ne_ident,
type_ident,
ty_params,
generics,
Disjunction);
// Create the implementation.
return create_derived_eq_impl(cx,
span,
type_ident,
ty_params,
generics,
eq_method,
ne_method);
}
@ -533,7 +551,7 @@ fn expand_deriving_eq_enum_def(cx: ext_ctxt,
span: span,
enum_definition: &enum_def,
type_ident: ident,
+ty_params: ~[ty_param])
generics: &Generics)
-> @item {
// Create the methods.
let eq_ident = cx.ident_of(~"eq");
@ -543,21 +561,21 @@ fn expand_deriving_eq_enum_def(cx: ext_ctxt,
enum_definition,
eq_ident,
type_ident,
ty_params,
generics,
Conjunction);
let ne_method = expand_deriving_eq_enum_method(cx,
span,
enum_definition,
ne_ident,
type_ident,
ty_params,
generics,
Disjunction);
// Create the implementation.
return create_derived_eq_impl(cx,
span,
type_ident,
ty_params,
generics,
eq_method,
ne_method);
}
@ -566,7 +584,7 @@ fn expand_deriving_iter_bytes_struct_def(cx: ext_ctxt,
span: span,
struct_def: &struct_def,
type_ident: ident,
+ty_params: ~[ty_param])
generics: &Generics)
-> @item {
// Create the method.
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,
span,
type_ident,
ty_params,
generics,
method);
}
@ -585,7 +603,7 @@ fn expand_deriving_iter_bytes_enum_def(cx: ext_ctxt,
span: span,
enum_definition: &enum_def,
type_ident: ident,
+ty_params: ~[ty_param])
generics: &Generics)
-> @item {
// Create the method.
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,
span,
type_ident,
ty_params,
generics,
method);
}
@ -605,7 +623,7 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
struct_def: &struct_def,
method_ident: ident,
type_ident: ident,
ty_params: &[ty_param],
generics: &Generics,
junction: Junction)
-> @method {
let self_ident = cx.ident_of(~"self");
@ -652,7 +670,7 @@ fn expand_deriving_eq_struct_method(cx: ext_ctxt,
span,
method_ident,
type_ident,
ty_params,
generics,
body);
}
@ -696,7 +714,7 @@ fn expand_deriving_eq_enum_method(cx: ext_ctxt,
enum_definition: &enum_def,
method_ident: ident,
type_ident: ident,
ty_params: &[ty_param],
generics: &Generics,
junction: Junction)
-> @method {
let self_ident = cx.ident_of(~"self");
@ -823,7 +841,7 @@ fn expand_deriving_eq_enum_method(cx: ext_ctxt,
span,
method_ident,
type_ident,
ty_params,
generics,
self_match_expr);
}
@ -832,7 +850,7 @@ fn expand_deriving_eq_struct_tuple_method(cx: ext_ctxt,
struct_def: &struct_def,
method_ident: ident,
type_ident: ident,
ty_params: &[ty_param],
generics: &Generics,
junction: Junction)
-> @method {
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);
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,

View File

@ -24,6 +24,8 @@ use codemap::{span, respan, dummy_sp};
use codemap;
use ext::base::{ext_ctxt, mk_ctxt};
use ext::quote::rt::*;
use opt_vec;
use opt_vec::OptVec;
use core::vec;
@ -67,8 +69,8 @@ impl append_types for @ast::path {
}
pub trait ext_ctxt_ast_builder {
fn ty_param(&self, id: ast::ident, +bounds: ~[ast::ty_param_bound])
-> ast::ty_param;
fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-> ast::TyParam;
fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg;
fn expr_block(&self, e: @ast::expr) -> ast::blk;
fn fn_decl(&self, +inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
@ -76,7 +78,7 @@ pub trait ext_ctxt_ast_builder {
fn item_fn_poly(&self, name: ident,
+inputs: ~[ast::arg],
output: @ast::Ty,
+ty_params: ~[ast::ty_param],
+generics: Generics,
+body: ast::blk) -> @ast::item;
fn item_fn(&self, name: ident,
+inputs: ~[ast::arg],
@ -85,12 +87,12 @@ pub trait ext_ctxt_ast_builder {
fn item_enum_poly(&self, name: ident,
span: span,
+enum_definition: ast::enum_def,
+ty_params: ~[ast::ty_param]) -> @ast::item;
+generics: Generics) -> @ast::item;
fn item_enum(&self, name: ident, span: span,
+enum_definition: ast::enum_def) -> @ast::item;
fn item_struct_poly(&self, name: ident, span: span,
struct_def: ast::struct_def,
ty_params: ~[ast::ty_param]) -> @ast::item;
+generics: Generics) -> @ast::item;
fn item_struct(&self, name: ident, span: span,
struct_def: ast::struct_def) -> @ast::item;
fn struct_expr(&self, path: @ast::path,
@ -103,10 +105,10 @@ pub trait ext_ctxt_ast_builder {
fn item_ty_poly(&self, name: ident,
span: span,
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 ty_vars(&self, +ty_params: ~[ast::ty_param]) -> ~[@ast::Ty];
fn ty_vars_global(&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: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
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 block(&self, +stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
@ -116,7 +118,7 @@ pub trait ext_ctxt_ast_builder {
fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty;
fn ty_infer(&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 {
@ -172,10 +174,10 @@ impl ext_ctxt_ast_builder for ext_ctxt {
}
}
fn ty_param(&self, id: ast::ident, +bounds: ~[ast::ty_param_bound])
-> ast::ty_param
fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-> 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 {
@ -247,13 +249,13 @@ impl ext_ctxt_ast_builder for ext_ctxt {
fn item_fn_poly(&self, name: ident,
+inputs: ~[ast::arg],
output: @ast::Ty,
+ty_params: ~[ast::ty_param],
+generics: Generics,
+body: ast::blk) -> @ast::item {
self.item(name,
dummy_sp(),
ast::item_fn(self.fn_decl(inputs, output),
ast::impure_fn,
ty_params,
generics,
body))
}
@ -261,29 +263,32 @@ impl ext_ctxt_ast_builder for ext_ctxt {
+inputs: ~[ast::arg],
output: @ast::Ty,
+body: ast::blk) -> @ast::item {
self.item_fn_poly(name, inputs, output, ~[], body)
self.item_fn_poly(name, inputs, output,
ast_util::empty_generics(), body)
}
fn item_enum_poly(&self, name: ident, span: span,
+enum_definition: ast::enum_def,
+ty_params: ~[ast::ty_param]) -> @ast::item {
self.item(name, span, ast::item_enum(enum_definition, ty_params))
+generics: Generics) -> @ast::item {
self.item(name, span, ast::item_enum(enum_definition, generics))
}
fn item_enum(&self, name: ident, span: span,
+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,
struct_def: ast::struct_def) -> @ast::item {
self.item_struct_poly(name, span, struct_def, ~[])
self.item_struct_poly(name, span, struct_def,
ast_util::empty_generics())
}
fn item_struct_poly(&self, name: ident, span: span,
struct_def: ast::struct_def,
ty_params: ~[ast::ty_param]) -> @ast::item {
self.item(name, span, ast::item_struct(@struct_def, ty_params))
+generics: Generics) -> @ast::item {
self.item(name, span, ast::item_struct(@struct_def, generics))
}
fn struct_expr(&self, path: @ast::path,
@ -371,28 +376,31 @@ impl ext_ctxt_ast_builder for ext_ctxt {
}
}
fn strip_bounds(&self, bounds: &[ast::ty_param]) -> ~[ast::ty_param] {
do bounds.map |ty_param| {
ast::ty_param { bounds: @~[], ..copy *ty_param }
}
fn strip_bounds(&self, generics: &Generics) -> Generics {
let no_bounds = @opt_vec::Empty;
let new_params = do generics.ty_params.map |ty_param| {
ast::TyParam { bounds: no_bounds, ..copy *ty_param }
};
Generics { ty_params: new_params, ..*generics }
}
fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty,
+params: ~[ast::ty_param]) -> @ast::item {
self.item(name, span, ast::item_ty(ty, params))
+generics: Generics) -> @ast::item {
self.item(name, span, ast::item_ty(ty, generics))
}
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(
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(
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 {
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(
next.span, // use a real span
fmt!("message %s target (%s) \
needs %u type parameters, but got %u",
name, next.name,
next.ty_params.len(),
next.generics.ty_params.len(),
next_state.tys.len()));
}
}

View File

@ -51,13 +51,13 @@ impl proto_parser for parser::Parser {
_ => fail!()
};
let typarms = if *self.token == token::LT {
self.parse_ty_params()
let generics = if *self.token == token::LT {
self.parse_generics()
} 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
self.parse_unspanned_seq(

View File

@ -19,6 +19,8 @@ use ext::pipes::proto::*;
use ext::quote::rt::*;
use parse::*;
use util::interner;
use opt_vec;
use opt_vec::OptVec;
use core::dvec::DVec;
use core::prelude::*;
@ -50,20 +52,19 @@ impl gen_send for message {
fn gen_send(&mut self, cx: ext_ctxt, try: bool) -> @ast::item {
debug!("pipec: gen_send");
let name = self.name();
let params = self.get_params();
match *self {
message(ref _id, span, ref tys, this, Some(ref next_state)) => {
debug!("pipec: next state exists");
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 args_ast = (arg_names, *tys).map(|n, t| cx.arg(*n, *t));
let pipe_ty = cx.ty_path_ast_builder(
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(
~[cx.arg(cx.ident_of(~"pipe"),
pipe_ty)],
@ -129,7 +130,7 @@ impl gen_send for message {
cx.item_fn_poly(name,
args_ast,
rty,
params,
self.get_generics(),
cx.expr_block(body))
}
@ -143,10 +144,10 @@ impl gen_send for message {
let args_ast = vec::append(
~[cx.arg(cx.ident_of(~"pipe"),
cx.ty_path_ast_builder(
path(~[this.data_name()], span)
.add_tys(cx.ty_vars_global(
this.ty_params))))],
cx.ty_path_ast_builder(
path(~[this.data_name()], span)
.add_tys(cx.ty_vars_global(
&this.generics.ty_params))))],
args_ast);
let message_args = if arg_names.len() == 0 {
@ -184,7 +185,7 @@ impl gen_send for message {
} else {
cx.ty_nil_ast_builder()
},
params,
self.get_generics(),
cx.expr_block(body))
}
}
@ -192,7 +193,7 @@ impl gen_send for message {
fn to_ty(&mut self, cx: ext_ctxt) -> @ast::Ty {
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)))
}
}
@ -243,7 +244,7 @@ impl to_type_decls for state {
ast::enum_def(enum_def_ {
variants: items_msg,
common: None }),
cx.strip_bounds(self.ty_params)
cx.strip_bounds(&self.generics)
)
]
}
@ -281,8 +282,9 @@ impl to_type_decls for state {
path(~[cx.ident_of(~"super"),
self.data_name()],
dummy_sp())
.add_tys(cx.ty_vars_global(self.ty_params))))),
cx.strip_bounds(self.ty_params)));
.add_tys(cx.ty_vars_global(
&self.generics.ty_params))))),
cx.strip_bounds(&self.generics)));
}
else {
items.push(
@ -299,9 +301,10 @@ impl to_type_decls for state {
path(~[cx.ident_of(~"super"),
self.data_name()],
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)])),
cx.strip_bounds(self.ty_params)));
cx.strip_bounds(&self.generics)));
};
items
}
@ -340,7 +343,7 @@ impl gen_init for protocol {
cx.parse_item(fmt!("pub fn init%s() -> (client::%s, server::%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),
body.to_source(cx)))
@ -385,9 +388,9 @@ impl gen_init for protocol {
}
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 s.ty_params.each |tp| {
for s.generics.ty_params.each |tp| {
match params.find(|tpp| tp.ident == tpp.ident) {
None => params.push(*tp),
_ => ()
@ -398,19 +401,20 @@ impl gen_init for protocol {
cx.ty_path_ast_builder(path(~[cx.ident_of(~"super"),
cx.ident_of(~"__Buffer")],
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 {
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| {
for s.ty_params.each |tp| {
for s.generics.ty_params.each |tp| {
match params.find(|tpp| tp.ident == tpp.ident) {
None => params.push(*tp),
_ => ()
}
}
let ty = s.to_ty(cx);
let fty = quote_ty!( ::core::pipes::Packet<$ty> );
@ -427,6 +431,11 @@ impl gen_init for protocol {
}
};
let generics = Generics {
lifetimes: opt_vec::Empty,
ty_params: params
};
cx.item_struct_poly(
cx.ident_of(~"__Buffer"),
dummy_sp(),
@ -435,7 +444,7 @@ impl gen_init for protocol {
dtor: None,
ctor_id: None
},
cx.strip_bounds(params))
cx.strip_bounds(&generics))
}
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
fn get_params(&mut self) -> ~[ast::ty_param] {
fn get_generics(&self) -> ast::Generics {
match *self {
message(_, _, _, this, _) => this.ty_params
message(_, _, _, this, _) => this.generics
}
}
}
@ -76,7 +76,7 @@ pub struct state_ {
ident: ast::ident,
span: span,
dir: direction,
ty_params: ~[ast::ty_param],
generics: ast::Generics,
messages: @mut ~[message],
proto: protocol
}
@ -100,7 +100,7 @@ pub impl state_ {
fn to_ty(&self, cx: ext_ctxt) -> @ast::Ty {
cx.ty_path_ast_builder
(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
@ -161,7 +161,7 @@ pub impl protocol_ {
fn has_ty_params(&mut self) -> bool {
for self.states.each |s| {
if s.ty_params.len() > 0 {
if s.generics.ty_params.len() > 0 {
return true;
}
}
@ -175,7 +175,7 @@ pub impl protocol_ {
pub impl protocol {
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 state = @state_ {
@ -184,7 +184,7 @@ pub impl protocol {
ident: ident,
span: self.span,
dir: dir,
ty_params: ty_params,
generics: generics,
messages: messages,
proto: *self
};

View File

@ -50,12 +50,12 @@ pub mod rt {
use print::pprust::{item_to_str, ty_to_str};
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] {
pub fn to_tokens(_cx: ext_ctxt) -> ~[token_tree] {
copy self
pub fn to_tokens(&self, _cx: ext_ctxt) -> ~[token_tree] {
copy *self
}
}
@ -75,91 +75,91 @@ pub mod rt {
trait ToSource {
// 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 {
fn to_source(cx: ext_ctxt) -> ~str {
copy *cx.parse_sess().interner.get(self)
fn to_source(&self, cx: ext_ctxt) -> ~str {
copy *cx.parse_sess().interner.get(*self)
}
}
impl ToSource for @ast::item {
fn to_source(cx: ext_ctxt) -> ~str {
item_to_str(self, cx.parse_sess().interner)
fn to_source(&self, cx: ext_ctxt) -> ~str {
item_to_str(*self, cx.parse_sess().interner)
}
}
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")
}
}
impl ToSource for @ast::Ty {
fn to_source(cx: ext_ctxt) -> ~str {
ty_to_str(self, cx.parse_sess().interner)
fn to_source(&self, cx: ext_ctxt) -> ~str {
ty_to_str(*self, cx.parse_sess().interner)
}
}
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)), ~", ")
}
}
impl ToSource for ~[ast::ty_param] {
fn to_source(cx: ext_ctxt) -> ~str {
pprust::typarams_to_str(self, cx.parse_sess().interner)
impl ToSource for Generics {
fn to_source(&self, cx: ext_ctxt) -> ~str {
pprust::generics_to_str(self, cx.parse_sess().interner)
}
}
impl ToSource for @ast::expr {
fn to_source(cx: ext_ctxt) -> ~str {
pprust::expr_to_str(self, cx.parse_sess().interner)
fn to_source(&self, cx: ext_ctxt) -> ~str {
pprust::expr_to_str(*self, cx.parse_sess().interner)
}
}
// Alas ... we write these out instead. All redundant.
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))
}
}
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))
}
}
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))
}
}
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))
}
}
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))
}
}
impl ToTokens for ~[ast::ty_param] {
fn to_tokens(cx: ext_ctxt) -> ~[token_tree] {
impl ToTokens for Generics {
fn to_tokens(&self, cx: ext_ctxt) -> ~[token_tree] {
cx.parse_tts(self.to_source(cx))
}
}
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))
}
}

View File

@ -130,21 +130,38 @@ pub fn fold_fn_decl(decl: ast::fn_decl, fld: ast_fold) -> ast::fn_decl {
}
}
fn fold_ty_param_bound(tpb: ty_param_bound, fld: ast_fold) -> ty_param_bound {
fn fold_ty_param_bound(tpb: TyParamBound, fld: ast_fold) -> TyParamBound {
match tpb {
TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_ty(ty)),
RegionTyParamBound => RegionTyParamBound
}
}
pub fn fold_ty_param(tp: ty_param, fld: ast_fold) -> ty_param {
ast::ty_param { ident: /* FIXME (#2543) */ copy tp.ident,
id: fld.new_id(tp.id),
bounds: @tp.bounds.map(|x| fold_ty_param_bound(*x, fld) )}
pub fn fold_ty_param(tp: TyParam, fld: ast_fold) -> TyParam {
TyParam {ident: tp.ident,
id: fld.new_id(tp.id),
bounds: @tp.bounds.map(|x| fold_ty_param_bound(*x, fld))}
}
pub fn fold_ty_params(tps: ~[ty_param], fld: ast_fold) -> ~[ty_param] {
tps.map(|x| fold_ty_param(*x, fld))
pub fn fold_ty_params(tps: &OptVec<TyParam>,
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_ {
@ -173,7 +190,7 @@ fn noop_fold_foreign_item(&&ni: @foreign_item, fld: ast_fold)
attrs: vec::map(ni.attrs, |x| fold_attribute(*x)),
node:
match ni.node {
foreign_item_fn(fdec, purity, typms) => {
foreign_item_fn(fdec, purity, ref generics) => {
foreign_item_fn(
ast::fn_decl {
inputs: fdec.inputs.map(|a| fold_arg(*a)),
@ -181,7 +198,7 @@ fn noop_fold_foreign_item(&&ni: @foreign_item, fld: ast_fold)
cf: fdec.cf,
},
purity,
fold_ty_params(typms, fld))
fold_generics(generics, fld))
}
foreign_item_const(t) => {
foreign_item_const(fld.fold_ty(t))
@ -218,20 +235,20 @@ pub fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
item_fn(ref decl, purity, ref typms, ref body) => {
item_fn(fold_fn_decl(/* FIXME (#2543) */ copy *decl, fld),
purity,
fold_ty_params(/* FIXME (#2543) */ copy *typms, fld),
fold_generics(typms, fld),
fld.fold_block(*body))
}
item_mod(m) => item_mod(fld.fold_mod(m)),
item_foreign_mod(nm) => item_foreign_mod(fld.fold_foreign_mod(nm)),
item_ty(t, typms) => item_ty(fld.fold_ty(t),
fold_ty_params(typms, fld)),
item_ty(t, ref typms) => item_ty(fld.fold_ty(t),
fold_generics(typms, fld)),
item_enum(ref enum_definition, ref typms) => {
item_enum(ast::enum_def(ast::enum_def_ {
variants: enum_definition.variants.map(
|x| fld.fold_variant(*x)),
common: enum_definition.common.map(
|x| fold_struct_def(*x, fld)),
}), fold_ty_params(/* FIXME (#2543) */ copy *typms, fld))
}), fold_generics(typms, fld))
}
item_struct(ref struct_def, ref typms) => {
let struct_def = fold_struct_def(
@ -240,7 +257,7 @@ pub fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
item_struct(struct_def, /* FIXME (#2543) */ copy *typms)
}
item_impl(ref tps, ifce, ty, ref methods) => {
item_impl(fold_ty_params(/* FIXME (#2543) */ copy *tps, fld),
item_impl(fold_generics(tps, fld),
ifce.map(|p| fold_trait_ref(*p, fld)),
fld.fold_ty(ty),
methods.map(|x| fld.fold_method(*x)))
@ -252,7 +269,7 @@ pub fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
provided(method) => provided(fld.fold_method(method))
}
};
item_trait(fold_ty_params(/* FIXME (#2543) */ copy *tps, fld),
item_trait(fold_generics(tps, fld),
traits.map(|p| fold_trait_ref(*p, fld)),
methods)
}
@ -298,7 +315,7 @@ fn noop_fold_method(&&m: @method, fld: ast_fold) -> @method {
@ast::method {
ident: fld.fold_ident(m.ident),
attrs: /* FIXME (#2543) */ copy m.attrs,
tps: fold_ty_params(m.tps, fld),
generics: fold_generics(&m.generics, fld),
self_ty: m.self_ty,
purity: m.purity,
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(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 std::oldmap::HashMap;
use opt_vec;
use opt_vec::OptVec;
// SeqSep : a sequence separator (token)
// and whether a trailing separator is allowed.
pub struct SeqSep {
@ -221,10 +224,10 @@ pub impl Parser {
// parse a sequence bracketed by '<' and '>', stopping
// before the '>'.
fn parse_seq_to_before_gt<T:Copy>(sep: Option<token::Token>,
f: fn(Parser) -> T) -> ~[T] {
fn parse_seq_to_before_gt<T: Copy>(sep: Option<token::Token>,
f: fn(Parser) -> T) -> OptVec<T> {
let mut first = true;
let mut v = ~[];
let mut v = opt_vec::Empty;
while *self.token != token::GT
&& *self.token != token::BINOP(token::SHR) {
match sep {
@ -236,29 +239,16 @@ pub impl Parser {
}
v.push(f(self));
}
return v;
}
fn parse_seq_to_gt<T:Copy>(sep: Option<token::Token>,
f: fn(Parser) -> T) -> ~[T] {
fn parse_seq_to_gt<T: Copy>(sep: Option<token::Token>,
f: fn(Parser) -> T) -> OptVec<T> {
let v = self.parse_seq_to_before_gt(sep, f);
self.expect_gt();
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
// f must consume tokens until reaching the next separator or
// 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::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn};
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::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item};
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 print::pprust::expr_to_str;
use util::interner::Interner;
use opt_vec;
use opt_vec::OptVec;
use core::cmp;
use core::either::{Either, Left, Right};
@ -439,7 +441,7 @@ pub impl Parser {
// could change.
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| {
// This is somewhat dubious; We don't want to allow argument
@ -464,7 +466,7 @@ pub impl Parser {
attrs: attrs,
purity: pur,
decl: d,
tps: tps,
generics: generics,
self_ty: self_ty,
id: p.get_id(),
span: mk_sp(lo, hi)
@ -478,7 +480,7 @@ pub impl Parser {
provided(@ast::method {
ident: ident,
attrs: attrs,
tps: tps,
generics: generics,
self_ty: self_ty,
purity: pur,
decl: d,
@ -921,19 +923,7 @@ pub impl Parser {
};
// Parse any lifetime or type parameters which may appear:
let tps = {
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 tps = self.parse_generic_values();
let hi = self.span.lo;
@ast::path { span: mk_sp(lo, hi),
@ -979,7 +969,7 @@ pub impl Parser {
}
}
fn parse_lifetimes() -> ~[ast::Lifetime] {
fn parse_lifetimes() -> OptVec<ast::Lifetime> {
/*!
*
* Parses zero or more comma separated lifetimes.
@ -988,7 +978,7 @@ pub impl Parser {
* lists, where we expect something like `<'a, 'b, T>`.
*/
let mut res = ~[];
let mut res = opt_vec::Empty;
loop {
match *self.token {
token::LIFETIME(_) => {
@ -1163,7 +1153,7 @@ pub impl Parser {
let remaining_exprs =
self.parse_seq_to_end(token::RBRACKET,
seq_sep_trailing_allowed(token::COMMA),
|p| p.parse_expr());
|p| p.parse_expr()).to_vec();
ex = expr_vec(~[first_expr] + remaining_exprs, mutbl);
} else {
// Vector with one element.
@ -1295,8 +1285,7 @@ pub impl Parser {
self.bump();
let tys = if self.eat(token::MOD_SEP) {
self.expect(token::LT);
self.parse_seq_to_gt(Some(token::COMMA),
|p| p.parse_ty(false))
self.parse_generic_values_after_lt()
} else {
~[]
};
@ -1426,7 +1415,7 @@ pub impl Parser {
vec::append(
self.parse_seq_to_before_end(
ket, seq_sep_none(),
|p| p.parse_token_tree()),
|p| p.parse_token_tree()).to_vec(),
// the close delimiter:
~[parse_any_tt_tok(self)])))
}
@ -2636,81 +2625,105 @@ pub impl Parser {
if self.eat_keyword(~"once") { ast::Once } else { ast::Many }
}
fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
let mut bounds = ~[];
if self.eat(token::COLON) {
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) {
fn parse_optional_ty_param_bounds() -> @OptVec<TyParamBound> {
if !self.eat(token::COLON) {
return @opt_vec::Empty;
}
~"send"
| ~"copy"
| ~"const"
| ~"owned" => {
self.obsolete(*self.span,
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));
}
}
let mut result = opt_vec::Empty;
loop {
if self.eat(token::BINOP(token::AND)) {
if self.eat_keyword(~"static") {
result.push(RegionTyParamBound);
} 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(sid, _) => {
match *self.id_to_str(sid) {
~"send" |
~"copy" |
~"const" |
~"owned" => {
self.obsolete(
*self.span,
ObsoleteLowerCaseKindBounds);
if self.eat(token::BINOP(token::PLUS)) {
loop;
}
// Bogus value, but doesn't matter, since
// is an error
Some(TraitTyParamBound(
self.mk_ty_path(sid)))
}
if is_ident_or_path(*self.token) {
self.obsolete(*self.span,
ObsoleteTraitBoundSeparator);
_ => None
}
}
_ => fail!()
};
match maybe_bound {
Some(bound) => {
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 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) {
let _lifetimes = self.parse_lifetimes();
self.parse_seq_to_gt(
let lifetimes = self.parse_lifetimes();
let ty_params = self.parse_seq_to_gt(
Some(token::COMMA),
|p| p.parse_ty_param())
} else { ~[] }
|p| p.parse_ty_param());
return ast::Generics {lifetimes: lifetimes,
ty_params: ty_params};
} else {
return 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)
@ -2802,7 +2815,7 @@ pub impl Parser {
args_or_capture_items =
self.parse_seq_to_before_end(token::RPAREN,
sep,
parse_arg_fn);
parse_arg_fn).to_vec();
}
token::RPAREN => {
args_or_capture_items = ~[];
@ -2818,7 +2831,7 @@ pub impl Parser {
args_or_capture_items =
self.parse_seq_to_before_end(token::RPAREN,
sep,
parse_arg_fn);
parse_arg_fn).to_vec();
}
self.expect(token::RPAREN);
@ -2861,10 +2874,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 ty_params = self.parse_ty_params();
(id, ty_params)
let generics = self.parse_generics();
(id, generics)
}
fn mk_item(+lo: BytePos, +hi: BytePos, +ident: ident,
@ -2879,10 +2892,10 @@ pub impl Parser {
}
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 (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 {
@ -2899,7 +2912,7 @@ pub impl Parser {
let visa = self.parse_visibility();
let pur = self.parse_fn_purity();
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| {
p.parse_arg()
};
@ -2911,7 +2924,7 @@ pub impl Parser {
@ast::method {
ident: ident,
attrs: attrs,
tps: tps,
generics: generics,
self_ty: self_ty,
purity: pur,
decl: decl,
@ -2926,7 +2939,7 @@ pub impl Parser {
fn parse_item_trait() -> item_info {
let ident = self.parse_ident();
self.parse_region_param();
let tps = self.parse_ty_params();
let tps = self.parse_generics();
// Parse traits, if necessary.
let traits;
@ -2954,12 +2967,7 @@ pub impl Parser {
}
// First, parse type parameters if necessary.
let mut tps;
if *self.token == token::LT {
tps = self.parse_ty_params();
} else {
tps = ~[];
}
let generics = self.parse_generics();
// This is a new-style impl declaration.
// XXX: clownshoes
@ -3007,37 +3015,7 @@ pub impl Parser {
}
}
(ident, item_impl(tps, 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: ~[] }
(ident, item_impl(generics, opt_trait, ty, meths), None)
}
fn parse_trait_ref() -> @trait_ref {
@ -3050,13 +3028,13 @@ pub impl Parser {
fn parse_trait_ref_list(ket: token::Token) -> ~[@trait_ref] {
self.parse_seq_to_before_end(
ket, seq_sep_none(),
|p| p.parse_trait_ref())
|p| p.parse_trait_ref()).to_vec()
}
fn parse_item_struct() -> item_info {
let class_name = self.parse_value_ident();
self.parse_region_param();
let ty_params = self.parse_ty_params();
let generics = self.parse_generics();
if self.eat(token::COLON) {
self.obsolete(*self.span, ObsoleteClassTraits);
let _ = self.parse_trait_ref_list(token::LBRACE);
@ -3133,7 +3111,7 @@ pub impl Parser {
fields: fields,
dtor: actual_dtor,
ctor_id: if is_tuple_like { Some(new_id) } else { None }
}, ty_params),
}, generics),
None)
}
@ -3397,13 +3375,13 @@ pub impl Parser {
let lo = self.span.lo;
let vis = self.parse_visibility();
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 mut hi = self.span.hi;
self.expect(token::SEMI);
@ast::foreign_item { ident: ident,
attrs: attrs,
node: foreign_item_fn(decl, purity, tps),
node: foreign_item_fn(decl, purity, generics),
id: self.get_id(),
span: mk_sp(lo, hi),
vis: vis }
@ -3566,7 +3544,7 @@ pub impl Parser {
fn parse_item_type() -> item_info {
let (_, ident) = self.parse_type_decl();
self.parse_region_param();
let tps = self.parse_ty_params();
let tps = self.parse_generics();
self.expect(token::EQ);
let ty = self.parse_ty(false);
self.expect(token::SEMI);
@ -3622,8 +3600,7 @@ pub impl Parser {
};
}
fn parse_enum_def(ty_params: ~[ast::ty_param])
-> enum_def {
fn parse_enum_def(+generics: ast::Generics) -> enum_def {
let mut variants: ~[variant] = ~[];
let mut all_nullary = true, have_disr = false;
let mut common_fields = None;
@ -3650,7 +3627,7 @@ pub impl Parser {
if self.eat_keyword(~"enum") {
ident = self.parse_ident();
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);
needs_comma = false;
} else {
@ -3706,7 +3683,7 @@ pub impl Parser {
fn parse_item_enum() -> item_info {
let id = self.parse_ident();
self.parse_region_param();
let ty_params = self.parse_ty_params();
let generics = self.parse_generics();
// Newtype syntax
if *self.token == token::EQ {
self.bump();
@ -3729,14 +3706,14 @@ pub impl Parser {
enum_def(
ast::enum_def_ { variants: ~[variant], common: None }
),
ty_params),
generics),
None
);
}
self.expect(token::LBRACE);
let enum_definition = self.parse_enum_def(ty_params);
(id, item_enum(enum_definition, ty_params), None)
let enum_definition = self.parse_enum_def(generics);
(id, item_enum(enum_definition, generics), None)
}
fn parse_fn_ty_sigil() -> Option<Sigil> {

View File

@ -14,6 +14,8 @@ use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
use ast;
use ast_util;
use ast_util::{operator_prec};
use opt_vec;
use opt_vec::OptVec;
use attr;
use codemap::{CodeMap, BytePos};
use codemap;
@ -164,8 +166,9 @@ pub fn item_to_str(i: @ast::item, intr: @ident_interner) -> ~str {
to_str(i, print_item, intr)
}
pub fn typarams_to_str(tps: ~[ast::ty_param], intr: @ident_interner) -> ~str {
to_str(tps, print_type_params, intr)
pub fn generics_to_str(generics: &ast::Generics,
intr: @ident_interner) -> ~str {
to_str(generics, print_generics, intr)
}
pub fn path_to_str(&&p: @ast::path, intr: @ident_interner) -> ~str {
@ -173,10 +176,10 @@ pub fn path_to_str(&&p: @ast::path, intr: @ident_interner) -> ~str {
}
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| {
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 outer box
eof(s.s);
@ -300,7 +303,7 @@ pub fn synth_comment(s: @ps, text: ~str) {
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);
let mut first = true;
for elts.each |elt| {
@ -459,8 +462,8 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) {
maybe_print_comment(s, item.span.lo);
print_outer_attributes(s, item.attrs);
match item.node {
ast::foreign_item_fn(decl, purity, typarams) => {
print_fn(s, decl, Some(purity), item.ident, typarams, None,
ast::foreign_item_fn(decl, purity, ref generics) => {
print_fn(s, decl, Some(purity), item.ident, generics, None,
ast::inherited);
end(s); // end head-ibox
word(s.s, ~";");
@ -505,7 +508,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
/* FIXME (#2543) */ copy *decl,
Some(purity),
item.ident,
/* FIXME (#2543) */ copy *typarams,
typarams,
None,
item.vis
);
@ -536,12 +539,12 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
print_foreign_mod(s, nmod, item.attrs);
bclose(s, item.span);
}
ast::item_ty(ty, params) => {
ast::item_ty(ty, ref params) => {
ibox(s, indent_unit);
ibox(s, 0u);
word_nbsp(s, visibility_qualified(item.vis, ~"type"));
print_ident(s, item.ident);
print_type_params(s, params);
print_generics(s, params);
end(s); // end the inner ibox
space(s.s);
@ -554,21 +557,21 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
print_enum_def(
s,
*enum_definition,
/* FIXME (#2543) */ copy *params,
params,
item.ident,
item.span,
item.vis
);
}
ast::item_struct(struct_def, tps) => {
ast::item_struct(struct_def, ref generics) => {
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, methods) => {
head(s, visibility_qualified(item.vis, ~"impl"));
if !tps.is_empty() {
print_type_params(s, tps);
if !generics.is_empty() {
print_generics(s, generics);
space(s.s);
}
@ -594,10 +597,10 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
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"));
print_ident(s, item.ident);
print_type_params(s, /* FIXME (#2543) */ copy *tps);
print_generics(s, generics);
if traits.len() != 0u {
word(s.s, ~":");
for traits.each |trait_| {
@ -629,7 +632,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
}
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) {
let mut newtype =
vec::len(enum_definition.variants) == 1u &&
@ -648,7 +651,7 @@ pub fn print_enum_def(s: @ps, enum_definition: ast::enum_def,
}
print_ident(s, ident);
print_type_params(s, params);
print_generics(s, generics);
space(s.s);
if newtype {
word_space(s, ~"=");
@ -706,12 +709,12 @@ pub fn print_visibility(s: @ps, vis: ast::visibility) {
pub fn print_struct(s: @ps,
struct_def: @ast::struct_def,
tps: ~[ast::ty_param],
generics: &ast::Generics,
ident: ast::ident,
span: codemap::span) {
print_ident(s, ident);
nbsp(s);
print_type_params(s, tps);
print_generics(s, generics);
if ast_util::struct_def_is_tuple_like(struct_def) {
popen(s);
let mut first = true;
@ -823,7 +826,8 @@ pub fn print_variant(s: @ps, v: ast::variant) {
}
ast::struct_variant_kind(struct_def) => {
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) => {
print_variants(s, (*enum_definition).variants, v.span);
@ -844,7 +848,7 @@ pub fn print_ty_method(s: @ps, m: ast::ty_method) {
maybe_print_comment(s, m.span.lo);
print_outer_attributes(s, m.attrs);
print_ty_fn(s, None, None, None, m.purity, ast::Many,
m.decl, Some(m.ident), Some(m.tps),
m.decl, Some(m.ident), Some(&m.generics),
Some(m.self_ty.node));
word(s.s, ~";");
}
@ -861,7 +865,7 @@ pub fn print_method(s: @ps, meth: @ast::method) {
maybe_print_comment(s, meth.span.lo);
print_outer_attributes(s, meth.attrs);
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);
word(s.s, ~" ");
print_block_with_attrs(s, meth.body, meth.attrs);
@ -1714,14 +1718,14 @@ pub fn print_fn(s: @ps,
decl: ast::fn_decl,
purity: Option<ast::purity>,
name: ast::ident,
typarams: ~[ast::ty_param],
generics: &ast::Generics,
opt_self_ty: Option<ast::self_ty_>,
vis: ast::visibility) {
head(s, ~"");
print_fn_header_info(s, opt_self_ty, purity, ast::Many, None, vis);
nbsp(s);
print_ident(s, name);
print_type_params(s, typarams);
print_generics(s, generics);
print_fn_args_and_ret(s, decl, opt_self_ty);
}
@ -1791,11 +1795,11 @@ pub fn print_arg_mode(s: @ps, m: ast::mode) {
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() {
word(s.s, ~":");
let mut first = true;
for vec::each(*bounds) |&bound| {
for bounds.each |bound| {
nbsp(s);
if first {
first = false;
@ -1803,7 +1807,7 @@ pub fn print_bounds(s: @ps, bounds: @~[ast::ty_param_bound]) {
word_space(s, ~"+");
}
match bound {
match *bound {
TraitTyParamBound(ty) => print_type(s, ty),
RegionTyParamBound => word(s.s, ~"&static"),
}
@ -1811,14 +1815,33 @@ pub fn print_bounds(s: @ps, bounds: @~[ast::ty_param_bound]) {
}
}
pub fn print_type_params(s: @ps, &&params: ~[ast::ty_param]) {
if vec::len(params) > 0u {
pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) {
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, ~"<");
fn printParam(s: @ps, param: ast::ty_param) {
print_ident(s, param.ident);
print_bounds(s, param.bounds);
fn print_item(s: @ps, generics: &ast::Generics, idx: uint) {
if idx < generics.lifetimes.len() {
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, ~">");
}
}
@ -1954,7 +1977,7 @@ pub fn print_ty_fn(s: @ps,
purity: ast::purity,
onceness: ast::Onceness,
decl: ast::fn_decl, id: Option<ast::ident>,
tps: Option<~[ast::ty_param]>,
generics: Option<&ast::Generics>,
opt_self_ty: Option<ast::self_ty_>) {
ibox(s, indent_unit);
@ -1968,7 +1991,7 @@ pub fn print_ty_fn(s: @ps,
print_onceness(s, onceness);
word(s.s, ~"fn");
match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () }
match tps { Some(tps) => print_type_params(s, tps), _ => () }
match generics { Some(g) => print_generics(s, g), _ => () }
zerobreak(s.s);
popen(s);
@ -2301,7 +2324,8 @@ pub mod test {
span: codemap::dummy_sp()},
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()");
}

View File

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

View File

@ -15,6 +15,7 @@ use ast;
use ast_util;
use codemap::span;
use parse;
use opt_vec;
use core::option;
use core::vec;
@ -30,11 +31,11 @@ use core::vec;
pub enum vt<E> { mk_vt(visitor<E>), }
pub enum fn_kind {
fk_item_fn(ident, ~[ty_param], purity), // fn foo()
fk_method(ident, ~[ty_param], @method), // fn foo(&self)
fk_item_fn(ident, Generics, purity), // fn foo()
fk_method(ident, Generics, @method), // fn foo(&self)
fk_anon(ast::Sigil), // fn@(x, y) { ... }
fk_fn_block, // |x, y| ...
fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
fk_dtor(Generics, ~[attribute], node_id /* self id */,
def_id /* parent class id */) // class destructor
}
@ -49,13 +50,17 @@ 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 {
fk_item_fn(_, tps, _) | fk_method(_, tps, _) |
fk_item_fn(_, tps, _) |
fk_method(_, tps, _) |
fk_dtor(tps, _, _, _) => {
/* FIXME (#2543) */ copy tps
copy tps
}
fk_anon(*) | fk_fn_block(*) => {
Generics {lifetimes: opt_vec::Empty,
ty_params: opt_vec::Empty}
}
fk_anon(*) | fk_fn_block(*) => ~[]
}
}
@ -73,11 +78,11 @@ pub struct Visitor<E> {
visit_expr: fn@(@expr, E, vt<E>),
visit_expr_post: fn@(@expr, 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_ty_method: fn@(ty_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>),
visit_struct_field: fn@(@struct_field, E, vt<E>),
visit_struct_method: fn@(@method, E, vt<E>)
@ -100,7 +105,7 @@ pub fn default_visitor<E>() -> visitor<E> {
visit_expr: |a,b,c|visit_expr::<E>(a, b, c),
visit_expr_post: |_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_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),
@ -157,21 +162,21 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
for nm.view_items.each |vi| { (v.visit_view_item)(*vi, e, v); }
for nm.items.each |ni| { (v.visit_foreign_item)(*ni, e, v); }
}
item_ty(t, tps) => {
item_ty(t, ref tps) => {
(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) => {
(v.visit_ty_params)(/* FIXME (#2543) */ copy *tps, e, v);
(v.visit_generics)(tps, e, v);
visit_enum_def(
*enum_definition,
/* FIXME (#2543) */ copy *tps,
tps,
e,
v
);
}
item_impl(tps, traits, ty, methods) => {
(v.visit_ty_params)(tps, e, v);
item_impl(ref tps, traits, ty, methods) => {
(v.visit_generics)(tps, e, v);
for traits.each |p| {
visit_path(p.path, e, v);
}
@ -180,12 +185,12 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_method_helper(*m, e, v)
}
}
item_struct(struct_def, tps) => {
(v.visit_ty_params)(tps, e, v);
item_struct(struct_def, ref tps) => {
(v.visit_generics)(tps, e, v);
(v.visit_struct_def)(struct_def, i.ident, tps, i.id, e, v);
}
item_trait(ref tps, ref traits, ref methods) => {
(v.visit_ty_params)(/* FIXME (#2543) */ copy *tps, e, v);
(v.visit_generics)(tps, e, v);
for traits.each |p| { visit_path(p.path, e, v); }
for (*methods).each |m| {
(v.visit_trait_method)(*m, e, v);
@ -196,7 +201,7 @@ pub fn visit_item<E>(i: @item, e: E, v: vt<E>) {
}
pub fn visit_enum_def<E>(enum_definition: ast::enum_def,
tps: ~[ast::ty_param],
tps: &Generics,
e: E,
v: vt<E>) {
for enum_definition.variants.each |vr| {
@ -296,9 +301,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>) {
match ni.node {
foreign_item_fn(fd, _, tps) => {
(v.visit_ty_params)(tps, e, v);
foreign_item_fn(fd, _, ref generics) => {
visit_fn_decl(fd, e, v);
(v.visit_generics)(generics, e, v);
}
foreign_item_const(t) => {
(v.visit_ty)(t, e, v);
@ -306,17 +311,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>) {
for bounds.each |&bound| {
match bound {
pub fn visit_ty_param_bounds<E>(bounds: @OptVec<TyParamBound>,
e: E, v: vt<E>) {
for bounds.each |bound| {
match *bound {
TraitTyParamBound(ty) => (v.visit_ty)(ty, e, v),
RegionTyParamBound => ()
}
}
}
pub fn visit_ty_params<E>(tps: ~[ty_param], e: E, v: vt<E>) {
for tps.each |tp| {
pub fn visit_generics<E>(generics: &Generics, e: E, v: vt<E>) {
for generics.ty_params.each |tp| {
visit_ty_param_bounds(tp.bounds, e, v);
}
}
@ -334,29 +340,33 @@ pub fn visit_fn_decl<E>(fd: fn_decl, e: E, v: vt<E>) {
// because it is not a default impl of any method, though I doubt that really
// clarifies anything. - Niko
pub fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
(v.visit_fn)(fk_method(/* FIXME (#2543) */ copy m.ident,
/* FIXME (#2543) */ copy m.tps, m),
m.decl, m.body, m.span, m.id, e, v);
(v.visit_fn)(fk_method(m.ident, /* FIXME (#2543) */ copy m.generics, m),
m.decl, m.body, m.span, m.id, e, v);
}
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>) {
(v.visit_fn)(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
dtor.node.self_id, parent_id), ast_util::dtor_dec(),
dtor.node.body, dtor.span, dtor.node.id, e, v)
(v.visit_fn)(fk_dtor(copy *generics, dtor.node.attrs,
dtor.node.self_id, parent_id),
ast_util::dtor_dec(),
dtor.node.body,
dtor.span,
dtor.node.id,
e, v)
}
pub fn visit_fn<E>(fk: fn_kind, decl: fn_decl, body: blk, _sp: span,
_id: node_id, e: E, v: vt<E>) {
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);
}
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); }
(v.visit_ty_params)(m.tps, e, v);
(v.visit_generics)(&m.generics, e, v);
(v.visit_ty)(m.decl.output, e, v);
}
@ -367,13 +377,16 @@ 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],
id: node_id, e: E, v: vt<E>) {
pub fn visit_struct_def<E>(sd: @struct_def,
_nm: ast::ident,
generics: &Generics,
id: node_id,
e: E, v: vt<E>) {
for sd.fields.each |f| {
(v.visit_struct_field)(*f, e, v);
}
do option::iter(&sd.dtor) |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)
};
}
@ -552,11 +565,11 @@ pub struct SimpleVisitor {
visit_expr: fn@(@expr),
visit_expr_post: fn@(@expr),
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_ty_method: fn@(ty_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_method: fn@(@method)
}
@ -579,13 +592,13 @@ pub fn default_simple_visitor() -> @SimpleVisitor {
visit_expr: |_e: @expr| { },
visit_expr_post: |_e: @expr| { },
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,
_id: node_id) { },
visit_ty_method: fn@(_m: ty_method) { },
visit_trait_method: fn@(_m: trait_method) { },
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_method: fn@(_m: @method) { }
};
@ -654,17 +667,20 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
f(m);
visit_trait_method(m, e, v);
}
fn v_struct_def(f: fn@(@struct_def, ident, ~[ty_param], node_id),
sd: @struct_def, nm: ident, tps: ~[ty_param], id: node_id,
fn v_struct_def(f: fn@(@struct_def, ident, &Generics, node_id),
sd: @struct_def,
nm: ident,
generics: &Generics,
id: node_id,
&&e: (), v: vt<()>) {
f(sd, nm, tps, id);
visit_struct_def(sd, nm, tps, id, e, v);
f(sd, nm, generics, id);
visit_struct_def(sd, nm, generics, id, e, v);
}
fn v_ty_params(f: fn@(~[ty_param]),
ps: ~[ty_param],
&&e: (), v: vt<()>) {
fn v_generics(f: fn@(&Generics),
ps: &Generics,
&&e: (), v: vt<()>) {
f(ps);
visit_ty_params(ps, e, v);
visit_generics(ps, e, v);
}
fn v_fn(f: fn@(fn_kind, fn_decl, blk, span, node_id),
fk: fn_kind, decl: fn_decl, body: blk, sp: span,
@ -699,8 +715,8 @@ pub fn mk_simple_visitor(v: simple_visitor) -> vt<()> {
visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post,
a, b, c),
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|
v_generics(v.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),
visit_ty_method: |a,b,c|