rustc: Don't require that structs have constructors

This commit is contained in:
Patrick Walton 2012-07-24 15:29:14 -07:00
parent 695ab09899
commit 587b0edbbf
11 changed files with 165 additions and 109 deletions

View file

@ -636,7 +636,8 @@ enum item_ {
~[@trait_ref], /* traits this class implements */
~[@class_member], /* methods, etc. */
/* (not including ctor or dtor) */
class_ctor,
/* ctor is optional, and will soon go away */
option<class_ctor>,
/* dtor is optional */
option<class_dtor>
),

View file

@ -242,10 +242,24 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
item_enum(vec::map(variants, |x| fld.fold_variant(x)),
fold_ty_params(typms, fld))
}
item_class(typms, traits, items, ctor, m_dtor) {
let ctor_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
let ctor_id = fld.new_id(ctor.node.id);
item_class(typms, traits, items, m_ctor, m_dtor) {
let resulting_optional_constructor;
alt m_ctor {
none => {
resulting_optional_constructor = none;
}
some(constructor) => {
resulting_optional_constructor = some({
node: {
body: fld.fold_block(constructor.node.body),
dec: fold_fn_decl(constructor.node.dec, fld),
id: fld.new_id(constructor.node.id)
with constructor.node
}
with constructor
});
}
}
let dtor = do option::map(m_dtor) |dtor| {
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_id = fld.new_id(dtor.node.id);
@ -256,10 +270,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
/* FIXME (#2543) */ copy typms,
vec::map(traits, |p| fold_trait_ref(p, fld)),
vec::map(items, |x| fld.fold_class_item(x)),
{node: {body: ctor_body,
dec: ctor_decl,
id: ctor_id with ctor.node}
with ctor}, dtor)
resulting_optional_constructor,
dtor)
}
item_impl(tps, ifce, ty, methods) {
item_impl(fold_ty_params(tps, fld),

View file

@ -2205,20 +2205,22 @@ class parser {
alt the_ctor {
some((ct_d, ct_attrs, ct_b, ct_s)) {
(class_name,
item_class(ty_params, traits, ms, {
item_class(ty_params, traits, ms, some({
node: {id: ctor_id,
attrs: ct_attrs,
self_id: self.get_id(),
dec: ct_d,
body: ct_b},
span: ct_s}, actual_dtor),
span: ct_s}), actual_dtor),
none)
}
/*
Is it strange for the parser to check this?
*/
none {
self.fatal(~"class with no constructor");
(class_name,
item_class(ty_params, traits, ms, none, actual_dtor),
none)
}
}
}

View file

@ -488,7 +488,7 @@ fn print_item(s: ps, &&item: @ast::item) {
bclose(s, item.span);
}
}
ast::item_class(tps, traits, items, ctor, m_dtor) {
ast::item_class(tps, traits, items, m_ctor, m_dtor) {
head(s, ~"class");
word_nbsp(s, *item.ident);
print_type_params(s, tps);
@ -499,16 +499,18 @@ fn print_item(s: ps, &&item: @ast::item) {
}
bopen(s);
hardbreak_if_not_bol(s);
maybe_print_comment(s, ctor.span.lo);
print_outer_attributes(s, ctor.node.attrs);
/* Doesn't call head because there shouldn't be a space after new */
cbox(s, indent_unit);
ibox(s, 4);
word(s.s, ~"new(");
print_fn_args(s, ctor.node.dec, ~[]);
word(s.s, ~")");
space(s.s);
print_block(s, ctor.node.body);
do option::iter(m_ctor) |ctor| {
maybe_print_comment(s, ctor.span.lo);
print_outer_attributes(s, ctor.node.attrs);
// Doesn't call head because there shouldn't be a space after new.
cbox(s, indent_unit);
ibox(s, 4);
word(s.s, ~"new(");
print_fn_args(s, ctor.node.dec, ~[]);
word(s.s, ~")");
space(s.s);
print_block(s, ctor.node.body);
}
do option::iter(m_dtor) |dtor| {
hardbreak_if_not_bol(s);
maybe_print_comment(s, dtor.span.lo);

View file

@ -145,17 +145,20 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
visit_method_helper(m, e, v)
}
}
item_class(tps, traits, members, ctor, m_dtor) {
item_class(tps, traits, members, m_ctor, m_dtor) {
v.visit_ty_params(tps, e, v);
for members.each |m| {
v.visit_class_item(m, e, v);
}
for traits.each |p| { visit_path(p.path, e, v); }
visit_class_ctor_helper(ctor, i.ident, tps,
ast_util::local_def(i.id), e, v);
do option::iter(m_ctor) |ctor| {
visit_class_ctor_helper(ctor, i.ident, tps,
ast_util::local_def(i.id), e, v);
};
do option::iter(m_dtor) |dtor| {
visit_class_dtor_helper(dtor, tps,
ast_util::local_def(i.id), e, v)};
visit_class_dtor_helper(dtor, tps,
ast_util::local_def(i.id), e, v)
};
}
item_trait(tps, methods) {
v.visit_ty_params(tps, e, v);

View file

@ -193,7 +193,7 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
}
item_class(_, _, items, ctor, m_dtor) {
item_class(_, _, items, m_ctor, m_dtor) {
do ebml_w.wr_tag(tag_paths_data_item) {
encode_name_and_def_id(ebml_w, it.ident, it.id);
}
@ -201,8 +201,17 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
// We add the same ident twice: for the
// class and for its ctor
add_to_index(ebml_w, path, index, it.ident);
encode_named_def_id(ebml_w, it.ident,
local_def(ctor.node.id));
alt m_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, items,
vec::append_one(path, it.ident),
index);
@ -817,18 +826,20 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_info_for_item(ecx, ebml_w, i, index, *pt);
/* encode ctor, then encode items */
alt i.node {
item_class(tps, _, _, ctor, m_dtor) {
#debug("encoding info for ctor %s %d", *i.ident,
ctor.node.id);
vec::push(*index,
{val: ctor.node.id, pos: ebml_w.writer.tell()});
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
*pt, if tps.len() > 0u {
some(ii_ctor(ctor, i.ident, tps,
local_def(i.id))) }
else { none }, tps, ctor.node.dec);
}
_ {}
item_class(tps, _, _, some(ctor), m_dtor) {
#debug("encoding info for ctor %s %d", *i.ident,
ctor.node.id);
vec::push(*index, {
val: ctor.node.id,
pos: ebml_w.writer.tell()
});
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
*pt, if tps.len() > 0u {
some(ii_ctor(ctor, i.ident, tps,
local_def(i.id))) }
else { none }, tps, ctor.node.dec);
}
_ {}
}
}
}

View file

@ -878,12 +878,20 @@ class Resolver {
visitor);
}
}
item_class(_, _, class_members, ctor, _) {
item_class(_, _, class_members, optional_ctor, _) {
(*name_bindings).define_type(def_ty(local_def(item.id)));
let purity = ctor.node.dec.purity;
let ctor_def = def_fn(local_def(ctor.node.id), purity);
(*name_bindings).define_value(ctor_def);
alt optional_ctor {
none => {
// Nothing to do.
}
some(ctor) => {
let purity = ctor.node.dec.purity;
let ctor_def = def_fn(local_def(ctor.node.id),
purity);
(*name_bindings).define_value(ctor_def);
}
}
// Create the set of implementation information that the
// implementation scopes (ImplScopes) need and write it into
@ -3043,14 +3051,14 @@ class Resolver {
(*self.type_ribs).pop();
}
item_class(ty_params, interfaces, class_members, constructor,
optional_destructor) {
item_class(ty_params, interfaces, class_members,
optional_constructor, optional_destructor) {
self.resolve_class(item.id,
@copy ty_params,
interfaces,
class_members,
constructor,
optional_constructor,
optional_destructor,
visitor);
}
@ -3273,7 +3281,7 @@ class Resolver {
type_parameters: @~[ty_param],
interfaces: ~[@trait_ref],
class_members: ~[@class_member],
constructor: class_ctor,
optional_constructor: option<class_ctor>,
optional_destructor: option<class_dtor>,
visitor: ResolveVisitor) {
@ -3285,8 +3293,7 @@ class Resolver {
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
do self.with_type_parameter_rib(HasTypeParameters
(borrowed_type_parameters, id, 0u,
NormalRibKind))
|| {
NormalRibKind)) {
// Resolve the type parameters.
self.resolve_type_parameters(*type_parameters, visitor);
@ -3331,15 +3338,22 @@ class Resolver {
}
}
// Resolve the constructor.
self.resolve_function(NormalRibKind,
some(@constructor.node.dec),
NoTypeParameters,
constructor.node.body,
HasSelfBinding(constructor.node.self_id),
NoCaptureClause,
visitor);
// Resolve the constructor, if applicable.
alt optional_constructor {
none => {
// Nothing to do.
}
some(constructor) => {
self.resolve_function(NormalRibKind,
some(@constructor.node.dec),
NoTypeParameters,
constructor.node.body,
HasSelfBinding(constructor.node.
self_id),
NoCaptureClause,
visitor);
}
}
// Resolve the destructor, if applicable.
alt optional_destructor {

View file

@ -5015,15 +5015,17 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
};
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
}
ast::item_class(tps, _traits, items, ctor, m_dtor) {
ast::item_class(tps, _traits, items, m_ctor, m_dtor) {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: none,
bounds: @~[]};
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(m_dtor) |dtor| {
do option::iter(m_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(m_dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, none, none, local_def(item.id));
};

View file

@ -109,11 +109,13 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
}
item_class(tps, _traits, items, ctor, m_dtor) {
cx.rmap.insert(ctor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
!= attr::ia_none {
traverse_inline_body(cx, ctor.node.body);
item_class(tps, _traits, items, m_ctor, m_dtor) {
do option::iter(m_ctor) |ctor| {
cx.rmap.insert(ctor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
!= attr::ia_none {
traverse_inline_body(cx, ctor.node.body);
}
}
do option::iter(m_dtor) |dtor| {
cx.rmap.insert(dtor.node.id, ());

View file

@ -392,25 +392,29 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
for ms.each |m| { check_method(ccx, m, self_ty);}
}
ast::item_class(tps, traits, members, ctor, m_dtor) {
let tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id);
// 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);
ast::item_class(tps, traits, members, m_ctor, m_dtor) {
let tcx = ccx.tcx;
let class_t = ty::node_id_to_type(tcx, it.id);
do option::iter(m_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);
}
do option::iter(m_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);
};
// typecheck the members
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);
};
// typecheck the members
for members.each |m| { check_class_member(ccx, class_t, m); }
// Check that there's at least one field
let (fields,_) = split_class_items(members);

View file

@ -346,31 +346,34 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
write_ty_to_tcx(tcx, it.id, tpt.ty);
ensure_trait_methods(ccx, it.id);
}
ast::item_class(tps, traits, members, ctor, m_dtor) {
ast::item_class(tps, traits, members, m_ctor, m_dtor) {
// 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);
// 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_any,
inputs: t_args,
output: t_res,
ret_style: ast::return_val});
// constraints, or remove constraints from the language
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(m_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_any,
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(m_dtor) |dtor| {
// Write the dtor type
let t_dtor = ty::mk_fn(