Skip to content

Commit 587b0ed

Browse files
committed
rustc: Don't require that structs have constructors
1 parent 695ab09 commit 587b0ed

File tree

11 files changed

+165
-109
lines changed

11 files changed

+165
-109
lines changed

Diff for: src/libsyntax/ast.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ enum item_ {
636636
~[@trait_ref], /* traits this class implements */
637637
~[@class_member], /* methods, etc. */
638638
/* (not including ctor or dtor) */
639-
class_ctor,
639+
/* ctor is optional, and will soon go away */
640+
option<class_ctor>,
640641
/* dtor is optional */
641642
option<class_dtor>
642643
),

Diff for: src/libsyntax/fold.rs

+20-8
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,24 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
242242
item_enum(vec::map(variants, |x| fld.fold_variant(x)),
243243
fold_ty_params(typms, fld))
244244
}
245-
item_class(typms, traits, items, ctor, m_dtor) {
246-
let ctor_body = fld.fold_block(ctor.node.body);
247-
let ctor_decl = fold_fn_decl(ctor.node.dec, fld);
248-
let ctor_id = fld.new_id(ctor.node.id);
245+
item_class(typms, traits, items, m_ctor, m_dtor) {
246+
let resulting_optional_constructor;
247+
alt m_ctor {
248+
none => {
249+
resulting_optional_constructor = none;
250+
}
251+
some(constructor) => {
252+
resulting_optional_constructor = some({
253+
node: {
254+
body: fld.fold_block(constructor.node.body),
255+
dec: fold_fn_decl(constructor.node.dec, fld),
256+
id: fld.new_id(constructor.node.id)
257+
with constructor.node
258+
}
259+
with constructor
260+
});
261+
}
262+
}
249263
let dtor = do option::map(m_dtor) |dtor| {
250264
let dtor_body = fld.fold_block(dtor.node.body);
251265
let dtor_id = fld.new_id(dtor.node.id);
@@ -256,10 +270,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
256270
/* FIXME (#2543) */ copy typms,
257271
vec::map(traits, |p| fold_trait_ref(p, fld)),
258272
vec::map(items, |x| fld.fold_class_item(x)),
259-
{node: {body: ctor_body,
260-
dec: ctor_decl,
261-
id: ctor_id with ctor.node}
262-
with ctor}, dtor)
273+
resulting_optional_constructor,
274+
dtor)
263275
}
264276
item_impl(tps, ifce, ty, methods) {
265277
item_impl(fold_ty_params(tps, fld),

Diff for: src/libsyntax/parse/parser.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2205,20 +2205,22 @@ class parser {
22052205
alt the_ctor {
22062206
some((ct_d, ct_attrs, ct_b, ct_s)) {
22072207
(class_name,
2208-
item_class(ty_params, traits, ms, {
2208+
item_class(ty_params, traits, ms, some({
22092209
node: {id: ctor_id,
22102210
attrs: ct_attrs,
22112211
self_id: self.get_id(),
22122212
dec: ct_d,
22132213
body: ct_b},
2214-
span: ct_s}, actual_dtor),
2214+
span: ct_s}), actual_dtor),
22152215
none)
22162216
}
22172217
/*
22182218
Is it strange for the parser to check this?
22192219
*/
22202220
none {
2221-
self.fatal(~"class with no constructor");
2221+
(class_name,
2222+
item_class(ty_params, traits, ms, none, actual_dtor),
2223+
none)
22222224
}
22232225
}
22242226
}

Diff for: src/libsyntax/print/pprust.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ fn print_item(s: ps, &&item: @ast::item) {
488488
bclose(s, item.span);
489489
}
490490
}
491-
ast::item_class(tps, traits, items, ctor, m_dtor) {
491+
ast::item_class(tps, traits, items, m_ctor, m_dtor) {
492492
head(s, ~"class");
493493
word_nbsp(s, *item.ident);
494494
print_type_params(s, tps);
@@ -499,16 +499,18 @@ fn print_item(s: ps, &&item: @ast::item) {
499499
}
500500
bopen(s);
501501
hardbreak_if_not_bol(s);
502-
maybe_print_comment(s, ctor.span.lo);
503-
print_outer_attributes(s, ctor.node.attrs);
504-
/* Doesn't call head because there shouldn't be a space after new */
505-
cbox(s, indent_unit);
506-
ibox(s, 4);
507-
word(s.s, ~"new(");
508-
print_fn_args(s, ctor.node.dec, ~[]);
509-
word(s.s, ~")");
510-
space(s.s);
511-
print_block(s, ctor.node.body);
502+
do option::iter(m_ctor) |ctor| {
503+
maybe_print_comment(s, ctor.span.lo);
504+
print_outer_attributes(s, ctor.node.attrs);
505+
// Doesn't call head because there shouldn't be a space after new.
506+
cbox(s, indent_unit);
507+
ibox(s, 4);
508+
word(s.s, ~"new(");
509+
print_fn_args(s, ctor.node.dec, ~[]);
510+
word(s.s, ~")");
511+
space(s.s);
512+
print_block(s, ctor.node.body);
513+
}
512514
do option::iter(m_dtor) |dtor| {
513515
hardbreak_if_not_bol(s);
514516
maybe_print_comment(s, dtor.span.lo);

Diff for: src/libsyntax/visit.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,20 @@ fn visit_item<E>(i: @item, e: E, v: vt<E>) {
145145
visit_method_helper(m, e, v)
146146
}
147147
}
148-
item_class(tps, traits, members, ctor, m_dtor) {
148+
item_class(tps, traits, members, m_ctor, m_dtor) {
149149
v.visit_ty_params(tps, e, v);
150150
for members.each |m| {
151151
v.visit_class_item(m, e, v);
152152
}
153153
for traits.each |p| { visit_path(p.path, e, v); }
154-
visit_class_ctor_helper(ctor, i.ident, tps,
155-
ast_util::local_def(i.id), e, v);
154+
do option::iter(m_ctor) |ctor| {
155+
visit_class_ctor_helper(ctor, i.ident, tps,
156+
ast_util::local_def(i.id), e, v);
157+
};
156158
do option::iter(m_dtor) |dtor| {
157-
visit_class_dtor_helper(dtor, tps,
158-
ast_util::local_def(i.id), e, v)};
159+
visit_class_dtor_helper(dtor, tps,
160+
ast_util::local_def(i.id), e, v)
161+
};
159162
}
160163
item_trait(tps, methods) {
161164
v.visit_ty_params(tps, e, v);

Diff for: src/rustc/metadata/encoder.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,25 @@ fn encode_module_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt,
193193
encode_name_and_def_id(ebml_w, it.ident, it.id);
194194
}
195195
}
196-
item_class(_, _, items, ctor, m_dtor) {
196+
item_class(_, _, items, m_ctor, m_dtor) {
197197
do ebml_w.wr_tag(tag_paths_data_item) {
198198
encode_name_and_def_id(ebml_w, it.ident, it.id);
199199
}
200200
do ebml_w.wr_tag(tag_paths) {
201201
// We add the same ident twice: for the
202202
// class and for its ctor
203203
add_to_index(ebml_w, path, index, it.ident);
204-
encode_named_def_id(ebml_w, it.ident,
205-
local_def(ctor.node.id));
204+
205+
alt m_ctor {
206+
none => {
207+
// Nothing to do.
208+
}
209+
some(ctor) {
210+
encode_named_def_id(ebml_w, it.ident,
211+
local_def(ctor.node.id));
212+
}
213+
}
214+
206215
encode_class_item_paths(ebml_w, items,
207216
vec::append_one(path, it.ident),
208217
index);
@@ -817,18 +826,20 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
817826
encode_info_for_item(ecx, ebml_w, i, index, *pt);
818827
/* encode ctor, then encode items */
819828
alt i.node {
820-
item_class(tps, _, _, ctor, m_dtor) {
821-
#debug("encoding info for ctor %s %d", *i.ident,
822-
ctor.node.id);
823-
vec::push(*index,
824-
{val: ctor.node.id, pos: ebml_w.writer.tell()});
825-
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
826-
*pt, if tps.len() > 0u {
827-
some(ii_ctor(ctor, i.ident, tps,
828-
local_def(i.id))) }
829-
else { none }, tps, ctor.node.dec);
830-
}
831-
_ {}
829+
item_class(tps, _, _, some(ctor), m_dtor) {
830+
#debug("encoding info for ctor %s %d", *i.ident,
831+
ctor.node.id);
832+
vec::push(*index, {
833+
val: ctor.node.id,
834+
pos: ebml_w.writer.tell()
835+
});
836+
encode_info_for_fn(ecx, ebml_w, ctor.node.id, i.ident,
837+
*pt, if tps.len() > 0u {
838+
some(ii_ctor(ctor, i.ident, tps,
839+
local_def(i.id))) }
840+
else { none }, tps, ctor.node.dec);
841+
}
842+
_ {}
832843
}
833844
}
834845
}

Diff for: src/rustc/middle/resolve3.rs

+33-19
Original file line numberDiff line numberDiff line change
@@ -878,12 +878,20 @@ class Resolver {
878878
visitor);
879879
}
880880
}
881-
item_class(_, _, class_members, ctor, _) {
881+
item_class(_, _, class_members, optional_ctor, _) {
882882
(*name_bindings).define_type(def_ty(local_def(item.id)));
883883

884-
let purity = ctor.node.dec.purity;
885-
let ctor_def = def_fn(local_def(ctor.node.id), purity);
886-
(*name_bindings).define_value(ctor_def);
884+
alt optional_ctor {
885+
none => {
886+
// Nothing to do.
887+
}
888+
some(ctor) => {
889+
let purity = ctor.node.dec.purity;
890+
let ctor_def = def_fn(local_def(ctor.node.id),
891+
purity);
892+
(*name_bindings).define_value(ctor_def);
893+
}
894+
}
887895

888896
// Create the set of implementation information that the
889897
// implementation scopes (ImplScopes) need and write it into
@@ -3043,14 +3051,14 @@ class Resolver {
30433051
(*self.type_ribs).pop();
30443052
}
30453053

3046-
item_class(ty_params, interfaces, class_members, constructor,
3047-
optional_destructor) {
3054+
item_class(ty_params, interfaces, class_members,
3055+
optional_constructor, optional_destructor) {
30483056

30493057
self.resolve_class(item.id,
30503058
@copy ty_params,
30513059
interfaces,
30523060
class_members,
3053-
constructor,
3061+
optional_constructor,
30543062
optional_destructor,
30553063
visitor);
30563064
}
@@ -3273,7 +3281,7 @@ class Resolver {
32733281
type_parameters: @~[ty_param],
32743282
interfaces: ~[@trait_ref],
32753283
class_members: ~[@class_member],
3276-
constructor: class_ctor,
3284+
optional_constructor: option<class_ctor>,
32773285
optional_destructor: option<class_dtor>,
32783286
visitor: ResolveVisitor) {
32793287

@@ -3285,8 +3293,7 @@ class Resolver {
32853293
let borrowed_type_parameters: &~[ty_param] = &*type_parameters;
32863294
do self.with_type_parameter_rib(HasTypeParameters
32873295
(borrowed_type_parameters, id, 0u,
3288-
NormalRibKind))
3289-
|| {
3296+
NormalRibKind)) {
32903297

32913298
// Resolve the type parameters.
32923299
self.resolve_type_parameters(*type_parameters, visitor);
@@ -3331,15 +3338,22 @@ class Resolver {
33313338
}
33323339
}
33333340

3334-
// Resolve the constructor.
3335-
self.resolve_function(NormalRibKind,
3336-
some(@constructor.node.dec),
3337-
NoTypeParameters,
3338-
constructor.node.body,
3339-
HasSelfBinding(constructor.node.self_id),
3340-
NoCaptureClause,
3341-
visitor);
3342-
3341+
// Resolve the constructor, if applicable.
3342+
alt optional_constructor {
3343+
none => {
3344+
// Nothing to do.
3345+
}
3346+
some(constructor) => {
3347+
self.resolve_function(NormalRibKind,
3348+
some(@constructor.node.dec),
3349+
NoTypeParameters,
3350+
constructor.node.body,
3351+
HasSelfBinding(constructor.node.
3352+
self_id),
3353+
NoCaptureClause,
3354+
visitor);
3355+
}
3356+
}
33433357

33443358
// Resolve the destructor, if applicable.
33453359
alt optional_destructor {

Diff for: src/rustc/middle/trans/base.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -5015,15 +5015,17 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
50155015
};
50165016
foreign::trans_foreign_mod(ccx, foreign_mod, abi);
50175017
}
5018-
ast::item_class(tps, _traits, items, ctor, m_dtor) {
5018+
ast::item_class(tps, _traits, items, m_ctor, m_dtor) {
50195019
if tps.len() == 0u {
50205020
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
50215021
vtables: none,
50225022
bounds: @~[]};
5023-
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
5024-
get_item_val(ccx, ctor.node.id), psubsts,
5025-
ctor.node.id, local_def(item.id), ctor.span);
5026-
do option::iter(m_dtor) |dtor| {
5023+
do option::iter(m_ctor) |ctor| {
5024+
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
5025+
get_item_val(ccx, ctor.node.id), psubsts,
5026+
ctor.node.id, local_def(item.id), ctor.span);
5027+
}
5028+
do option::iter(m_dtor) |dtor| {
50275029
trans_class_dtor(ccx, *path, dtor.node.body,
50285030
dtor.node.id, none, none, local_def(item.id));
50295031
};

Diff for: src/rustc/middle/trans/reachable.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ fn traverse_public_item(cx: ctx, item: @item) {
109109
}
110110
}
111111
}
112-
item_class(tps, _traits, items, ctor, m_dtor) {
113-
cx.rmap.insert(ctor.node.id, ());
114-
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
115-
!= attr::ia_none {
116-
traverse_inline_body(cx, ctor.node.body);
112+
item_class(tps, _traits, items, m_ctor, m_dtor) {
113+
do option::iter(m_ctor) |ctor| {
114+
cx.rmap.insert(ctor.node.id, ());
115+
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
116+
!= attr::ia_none {
117+
traverse_inline_body(cx, ctor.node.body);
118+
}
117119
}
118120
do option::iter(m_dtor) |dtor| {
119121
cx.rmap.insert(dtor.node.id, ());

Diff for: src/rustc/middle/typeck/check.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -392,25 +392,29 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
392392
let self_ty = ccx.to_ty(rscope::type_rscope(rp), ty);
393393
for ms.each |m| { check_method(ccx, m, self_ty);}
394394
}
395-
ast::item_class(tps, traits, members, ctor, m_dtor) {
396-
let tcx = ccx.tcx;
397-
let class_t = ty::node_id_to_type(tcx, it.id);
398-
// typecheck the ctor
399-
check_bare_fn(ccx, ctor.node.dec,
400-
ctor.node.body, ctor.node.id,
401-
some(class_t));
402-
// Write the ctor's self's type
403-
write_ty_to_tcx(tcx, ctor.node.self_id, class_t);
395+
ast::item_class(tps, traits, members, m_ctor, m_dtor) {
396+
let tcx = ccx.tcx;
397+
let class_t = ty::node_id_to_type(tcx, it.id);
398+
399+
do option::iter(m_ctor) |ctor| {
400+
// typecheck the ctor
401+
check_bare_fn(ccx, ctor.node.dec,
402+
ctor.node.body, ctor.node.id,
403+
some(class_t));
404+
// Write the ctor's self's type
405+
write_ty_to_tcx(tcx, ctor.node.self_id, class_t);
406+
}
404407

405408
do option::iter(m_dtor) |dtor| {
406409
// typecheck the dtor
407-
check_bare_fn(ccx, ast_util::dtor_dec(),
408-
dtor.node.body, dtor.node.id,
409-
some(class_t));
410-
// Write the dtor's self's type
411-
write_ty_to_tcx(tcx, dtor.node.self_id, class_t);
412-
};
413-
// typecheck the members
410+
check_bare_fn(ccx, ast_util::dtor_dec(),
411+
dtor.node.body, dtor.node.id,
412+
some(class_t));
413+
// Write the dtor's self's type
414+
write_ty_to_tcx(tcx, dtor.node.self_id, class_t);
415+
};
416+
417+
// typecheck the members
414418
for members.each |m| { check_class_member(ccx, class_t, m); }
415419
// Check that there's at least one field
416420
let (fields,_) = split_class_items(members);

0 commit comments

Comments
 (0)