about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-24 15:29:14 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-24 15:29:51 -0700
commit587b0edbbf6c3ac587be98679c4262049aa2a305 (patch)
tree879bb3bdc266ecc210929950e781c4e9c2d07803
parent695ab098995d23b0fa62248b5ce3052e5e072269 (diff)
downloadrust-587b0edbbf6c3ac587be98679c4262049aa2a305.tar.gz
rust-587b0edbbf6c3ac587be98679c4262049aa2a305.zip
rustc: Don't require that structs have constructors
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/fold.rs28
-rw-r--r--src/libsyntax/parse/parser.rs8
-rw-r--r--src/libsyntax/print/pprust.rs24
-rw-r--r--src/libsyntax/visit.rs13
-rw-r--r--src/rustc/metadata/encoder.rs41
-rw-r--r--src/rustc/middle/resolve3.rs52
-rw-r--r--src/rustc/middle/trans/base.rs12
-rw-r--r--src/rustc/middle/trans/reachable.rs12
-rw-r--r--src/rustc/middle/typeck/check.rs36
-rw-r--r--src/rustc/middle/typeck/collect.rs45
11 files changed, 165 insertions, 109 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 761bfd906ad..fb27724e369 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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>
                ),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index b23d2acaccb..de9ed4b2570 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -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),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b9fb9dab374..0686bad2532 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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)
           }
         }
     }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8df555fc864..aacb725ec6c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -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);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index ad57ac28b2c..c7aed0ef90a 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -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);
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index e11008f4d6f..f44d86925b4 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -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);
+                   }
+                   _ {}
                 }
               }
             }
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index 1853322724a..bddf83c429e 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -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 {
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 932655364c9..209bb6ee7c2 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -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));
           };
diff --git a/src/rustc/middle/trans/reachable.rs b/src/rustc/middle/trans/reachable.rs
index c5d68bfc357..0be970357e8 100644
--- a/src/rustc/middle/trans/reachable.rs
+++ b/src/rustc/middle/trans/reachable.rs
@@ -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, ());
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index 9b4834283a3..b5743e525b1 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -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);
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 44d929a9efc..021ab4e6009 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -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(