rustc: Move some more routines that operate on struct definitions out of line

This commit is contained in:
Patrick Walton 2012-08-07 16:46:19 -07:00
parent 0f711e72f7
commit 61446293f9
5 changed files with 169 additions and 142 deletions

View file

@ -205,20 +205,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
// class and for its ctor
add_to_index(ebml_w, path, index, it.ident);
match struct_def.ctor {
none => {
// Nothing to do.
}
some(ctor) => {
encode_named_def_id(ebml_w, it.ident,
local_def(ctor.node.id));
}
}
encode_class_item_paths(ebml_w,
struct_def.members,
vec::append_one(path, it.ident),
index);
encode_struct_def(ebml_w, struct_def, path, it.ident, index);
}
}
item_enum(variants, _) => {
@ -238,6 +225,26 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
}
}
fn encode_struct_def(ebml_w: ebml::writer,
struct_def: ast::struct_def,
path: ~[ast::ident],
ident: ast::ident,
&index: ~[entry<~str>]) {
match struct_def.ctor {
none => {
// Nothing to do.
}
some(ctor) => {
encode_named_def_id(ebml_w, ident, local_def(ctor.node.id));
}
}
encode_class_item_paths(ebml_w,
struct_def.members,
vec::append_one(path, ident),
index);
}
fn encode_trait_ref(ebml_w: ebml::writer, ecx: @encode_ctxt, t: @trait_ref) {
ebml_w.start_tag(tag_impl_trait);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, t.ref_id));

View file

@ -4900,30 +4900,36 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
ast::item_class(struct_def, tps) => {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none,
bounds: @~[]};
do option::iter(struct_def.ctor) |ctor| {
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
get_item_val(ccx, ctor.node.id), psubsts,
ctor.node.id, local_def(item.id), ctor.span);
}
do option::iter(struct_def.dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, none, none, local_def(item.id));
};
}
// If there are ty params, the ctor will get monomorphized
// Translate methods
let (_, ms) = ast_util::split_class_items(struct_def.members);
impl::trans_impl(ccx, *path, item.ident, ms, tps);
trans_struct_def(ccx, struct_def, tps, path, item.ident, item.id);
}
_ => {/* fall through */ }
}
}
fn trans_struct_def(ccx: @crate_ctxt, struct_def: ast::struct_def,
tps: ~[ast::ty_param], path: @ast_map::path,
ident: ast::ident, id: ast::node_id) {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none,
bounds: @~[]};
do option::iter(struct_def.ctor) |ctor| {
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
get_item_val(ccx, ctor.node.id), psubsts,
ctor.node.id, local_def(id), ctor.span);
}
do option::iter(struct_def.dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, none, none, local_def(id));
};
}
// If there are ty params, the ctor will get monomorphized
// Translate methods
let (_, ms) = ast_util::split_class_items(struct_def.members);
impl::trans_impl(ccx, *path, ident, ms, tps);
}
// Translate a module. Doing this amounts to translating the items in the
// module; there ends up being no artifact (aside from linkage names) of
// separate modules in the compiled program. That's because modules exist

View file

@ -400,6 +400,42 @@ fn check_no_duplicate_fields(tcx: ty::ctxt, fields:
}
fn check_struct(ccx: @crate_ctxt, struct_def: ast::struct_def,
id: ast::node_id, span: span) {
let tcx = ccx.tcx;
let class_t = {self_ty: ty::node_id_to_type(tcx, id), node_id: id};
do option::iter(struct_def.ctor) |ctor| {
// typecheck the ctor
check_bare_fn(ccx, ctor.node.dec,
ctor.node.body, ctor.node.id,
some(class_t));
// Write the ctor's self's type
write_ty_to_tcx(tcx, ctor.node.self_id, class_t.self_ty);
}
do option::iter(struct_def.dtor) |dtor| {
// typecheck the dtor
check_bare_fn(ccx, ast_util::dtor_dec(),
dtor.node.body, dtor.node.id,
some(class_t));
// Write the dtor's self's type
write_ty_to_tcx(tcx, dtor.node.self_id, class_t.self_ty);
};
// typecheck the members
for struct_def.members.each |m| {
check_class_member(ccx, class_t, m);
}
// Check that there's at least one field
let (fields,_) = split_class_items(struct_def.members);
if fields.len() < 1u {
ccx.tcx.sess.span_err(span, ~"a class must have at least one field");
}
// Check that the class is instantiable
check_instantiable(ccx.tcx, span, id);
}
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
match it.node {
ast::item_const(_, e) => check_const(ccx, it.span, e, it.id),
@ -433,41 +469,7 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
}
}
ast::item_class(struct_def, _) => {
let tcx = ccx.tcx;
let class_t = {self_ty: ty::node_id_to_type(tcx, it.id),
node_id: it.id};
do option::iter(struct_def.ctor) |ctor| {
// typecheck the ctor
check_bare_fn(ccx, ctor.node.dec,
ctor.node.body, ctor.node.id,
some(class_t));
// Write the ctor's self's type
write_ty_to_tcx(tcx, ctor.node.self_id, class_t.self_ty);
}
do option::iter(struct_def.dtor) |dtor| {
// typecheck the dtor
check_bare_fn(ccx, ast_util::dtor_dec(),
dtor.node.body, dtor.node.id,
some(class_t));
// Write the dtor's self's type
write_ty_to_tcx(tcx, dtor.node.self_id, class_t.self_ty);
};
// typecheck the members
for struct_def.members.each |m| {
check_class_member(ccx, class_t, m);
}
// Check that there's at least one field
let (fields,_) = split_class_items(struct_def.members);
if fields.len() < 1u {
ccx.tcx.sess.span_err(
it.span,
~"a class must have at least one field");
}
// Check that the class is instantiable
check_instantiable(ccx.tcx, it.span, it.id);
check_struct(ccx, struct_def, it.id, it.span);
}
ast::item_ty(t, tps) => {
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);

View file

@ -505,29 +505,9 @@ class CoherenceChecker {
methods: methods
};
}
item_class(struct_def, ty_params) => {
let mut methods = ~[];
for struct_def.members.each |class_member| {
match class_member.node {
instance_var(*) => {
// Nothing to do.
}
class_method(ast_method) => {
push(methods, @{
did: local_def(ast_method.id),
n_tps: ast_method.tps.len(),
ident: ast_method.ident,
self_type: ast_method.self_ty.node
});
}
}
}
return @{
did: local_def(item.id),
ident: item.ident,
methods: methods
};
item_class(struct_def, _) => {
return self.create_impl_from_struct(struct_def, item.ident,
item.id);
}
_ => {
self.crate_context.tcx.sess.span_bug(item.span,
@ -537,6 +517,30 @@ class CoherenceChecker {
}
}
fn create_impl_from_struct(struct_def: ast::struct_def,
ident: ast::ident,
id: node_id)
-> @Impl {
let mut methods = ~[];
for struct_def.members.each |class_member| {
match class_member.node {
instance_var(*) => {
// Nothing to do.
}
class_method(ast_method) => {
push(methods, @{
did: local_def(ast_method.id),
n_tps: ast_method.tps.len(),
ident: ast_method.ident,
self_type: ast_method.self_ty.node
});
}
}
}
return @{ did: local_def(id), ident: ident, methods: methods };
}
fn span_of_impl(implementation: @Impl) -> span {
assert implementation.did.crate == local_crate;
match self.crate_context.tcx.items.find(implementation.did.node) {

View file

@ -388,57 +388,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
write_ty_to_tcx(tcx, it.id, tpt.ty);
tcx.tcache.insert(local_def(it.id), tpt);
do option::iter(struct_def.ctor) |ctor| {
// Write the ctor type
let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), a, none) );
let t_res = ty::mk_class(
tcx, local_def(it.id),
{self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(
tcx, {purity: ast::impure_fn,
proto: ast::proto_block,
bounds: @~[],
inputs: t_args,
output: t_res,
ret_style: ast::return_val});
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
rp: rp,
ty: t_ctor});
}
do option::iter(struct_def.dtor) |dtor| {
// Write the dtor type
let t_dtor = ty::mk_fn(
tcx,
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_block, @~[],
ast_util::dtor_dec(), none));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
{bounds: tpt.bounds,
rp: rp,
ty: t_dtor});
};
ensure_trait_methods(ccx, it.id);
// Write the type of each of the members
let (fields, methods) = split_class_items(struct_def.members);
for fields.each |f| {
convert_field(ccx, rp, tpt.bounds, f);
}
let {bounds, substs} = mk_substs(ccx, tps, rp);
let selfty = ty::mk_class(tcx, local_def(it.id), substs);
let cms = convert_methods(ccx, methods, rp, bounds, selfty);
for struct_def.traits.each |trait_ref| {
check_methods_against_trait(ccx, tps, rp, selfty, trait_ref, cms);
// trait_ref.impl_id represents (class, trait) pair
write_ty_to_tcx(tcx, trait_ref.impl_id, tpt.ty);
tcx.tcache.insert(local_def(trait_ref.impl_id), tpt);
}
convert_struct(ccx, rp, struct_def, tps, tpt, it.id);
}
_ => {
// This call populates the type cache with the converted type
@ -449,6 +399,64 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
}
}
}
fn convert_struct(ccx: @crate_ctxt, rp: bool, struct_def: ast::struct_def,
tps: ~[ast::ty_param], tpt: ty::ty_param_bounds_and_ty,
id: ast::node_id) {
let tcx = ccx.tcx;
do option::iter(struct_def.ctor) |ctor| {
// Write the ctor type
let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), a, none) );
let t_res = ty::mk_class(
tcx, local_def(id),
{self_r: if rp {some(ty::re_bound(ty::br_self))} else {none},
self_ty: none,
tps: ty::ty_params_to_tys(tcx, tps)});
let t_ctor = ty::mk_fn(
tcx, {purity: ast::impure_fn,
proto: ast::proto_block,
bounds: @~[],
inputs: t_args,
output: t_res,
ret_style: ast::return_val});
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
rp: rp,
ty: t_ctor});
}
do option::iter(struct_def.dtor) |dtor| {
// Write the dtor type
let t_dtor = ty::mk_fn(
tcx,
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_block, @~[],
ast_util::dtor_dec(), none));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
{bounds: tpt.bounds,
rp: rp,
ty: t_dtor});
};
ensure_trait_methods(ccx, id);
// Write the type of each of the members
let (fields, methods) = split_class_items(struct_def.members);
for fields.each |f| {
convert_field(ccx, rp, tpt.bounds, f);
}
let {bounds, substs} = mk_substs(ccx, tps, rp);
let selfty = ty::mk_class(tcx, local_def(id), substs);
let cms = convert_methods(ccx, methods, rp, bounds, selfty);
for struct_def.traits.each |trait_ref| {
check_methods_against_trait(ccx, tps, rp, selfty, trait_ref, cms);
// trait_ref.impl_id represents (class, trait) pair
write_ty_to_tcx(tcx, trait_ref.impl_id, tpt.ty);
tcx.tcache.insert(local_def(trait_ref.impl_id), tpt);
}
}
fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
// As above, this call populates the type table with the converted
// type of the foreign item. We simply write it into the node type