rustc: Move some more routines that operate on struct definitions out of line
This commit is contained in:
parent
0f711e72f7
commit
61446293f9
5 changed files with 169 additions and 142 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue