rustc: Don't require that structs have constructors
This commit is contained in:
parent
695ab09899
commit
587b0edbbf
11 changed files with 165 additions and 109 deletions
|
|
@ -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>
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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, ());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue