From 104aaa44e8506cfaf2c00d6ca35dce93a8228545 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 25 Mar 2014 15:59:33 -0700
Subject: [PATCH 1/2] rustc: Relax restriction on privacy for fields

This is a necessary change in preparation for switching the defaults as part
of #8122.

RFC: 0004-private-fields
---
 src/librustc/middle/privacy.rs                |  4 ----
 src/test/compile-fail/struct-field-privacy.rs |  2 +-
 .../compile-fail/struct-variant-privacy.rs    | 20 -------------------
 3 files changed, 1 insertion(+), 25 deletions(-)
 delete mode 100644 src/test/compile-fail/struct-variant-privacy.rs

diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 0c2abfd23c3..d46cb7218b8 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -1001,10 +1001,6 @@ impl<'a> SanePrivacyVisitor<'a> {
             };
             for f in def.fields.iter() {
                match f.node.kind {
-                    ast::NamedField(_, ast::Public) if public_def => {
-                        tcx.sess.span_err(f.span, "unnecessary `pub` \
-                                                   visibility");
-                    }
                     ast::NamedField(_, ast::Private) if !public_def => {
                         tcx.sess.span_err(f.span, "unnecessary `priv` \
                                                    visibility");
diff --git a/src/test/compile-fail/struct-field-privacy.rs b/src/test/compile-fail/struct-field-privacy.rs
index d298d331a3f..56c58590fba 100644
--- a/src/test/compile-fail/struct-field-privacy.rs
+++ b/src/test/compile-fail/struct-field-privacy.rs
@@ -25,7 +25,7 @@ mod inner {
     pub struct B {
         a: int,
         priv b: int,
-        pub c: int, //~ ERROR: unnecessary `pub` visibility
+        pub c: int,
     }
 }
 
diff --git a/src/test/compile-fail/struct-variant-privacy.rs b/src/test/compile-fail/struct-variant-privacy.rs
deleted file mode 100644
index f37e02be12c..00000000000
--- a/src/test/compile-fail/struct-variant-privacy.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#[feature(struct_variant)];
-
-pub enum Foo {
-    Bar {
-        pub x: int, //~ ERROR unnecessary `pub` visibility
-        y: int,
-        priv z: int
-    }
-}
-
-fn main() {}

From 7de48419ee8f9ae0a41503e5e104709ea39bfe85 Mon Sep 17 00:00:00 2001
From: Alex Crichton <alex@alexcrichton.com>
Date: Tue, 25 Mar 2014 16:53:52 -0700
Subject: [PATCH 2/2] syntax: Permit visibility on tuple fields

This change is in preparation for #8122. Nothing is currently done with these
visibility qualifiers, they are just parsed and accepted by the compiler.

RFC: 0004-private-fields
---
 src/librustc/metadata/decoder.rs      |  3 ++-
 src/librustc/metadata/encoder.rs      |  8 ++++----
 src/librustc/middle/privacy.rs        |  4 ++--
 src/librustc/middle/ty.rs             |  6 +++---
 src/librustc/middle/typeck/collect.rs |  3 +--
 src/libsyntax/ast.rs                  | 11 ++++++++++-
 src/libsyntax/ast_util.rs             |  3 +--
 src/libsyntax/ext/deriving/generic.rs |  6 +++---
 src/libsyntax/parse/parser.rs         |  2 +-
 src/libsyntax/print/pprust.rs         |  5 +++--
 10 files changed, 30 insertions(+), 21 deletions(-)

diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 3387c47842a..0ea47d28551 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -1019,10 +1019,11 @@ pub fn get_struct_fields(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId)
     });
     reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
         let did = item_def_id(an_item, cdata);
+        let f = item_family(an_item);
         result.push(ty::field_ty {
             name: special_idents::unnamed_field.name,
             id: did,
-            vis: ast::Inherited,
+            vis: struct_field_family_to_visibility(f),
         });
         true
     });
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index d97e9f2b3e1..be1a7abe51d 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -310,8 +310,9 @@ fn encode_struct_fields(ebml_w: &mut writer::Encoder,
                encode_def_id(ebml_w, local_def(f.node.id));
                ebml_w.end_tag();
             }
-            UnnamedField => {
+            UnnamedField(vis) => {
                 ebml_w.start_tag(tag_item_unnamed_field);
+                encode_struct_field_family(ebml_w, vis);
                 encode_def_id(ebml_w, local_def(f.node.id));
                 ebml_w.end_tag();
             }
@@ -513,8 +514,7 @@ fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
             // If this is a newtype struct, return the constructor.
             match struct_def.ctor_id {
                 Some(ctor_id) if struct_def.fields.len() > 0 &&
-                        struct_def.fields.get(0).node.kind ==
-                        ast::UnnamedField => {
+                        struct_def.fields.get(0).node.kind.is_unnamed() => {
                     continue_ = callback(ctor_id);
                 }
                 _ => {}
@@ -690,7 +690,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
     for field in fields.iter() {
         let (nm, vis) = match field.node.kind {
             NamedField(nm, vis) => (nm, vis),
-            UnnamedField => (special_idents::unnamed_field, Inherited)
+            UnnamedField(vis) => (special_idents::unnamed_field, vis)
         };
 
         let id = field.node.id;
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index d46cb7218b8..0680a7132a0 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -1005,7 +1005,7 @@ impl<'a> SanePrivacyVisitor<'a> {
                         tcx.sess.span_err(f.span, "unnecessary `priv` \
                                                    visibility");
                     }
-                    ast::NamedField(..) | ast::UnnamedField => {}
+                    ast::NamedField(..) | ast::UnnamedField(..) => {}
                 }
             }
         };
@@ -1102,7 +1102,7 @@ impl<'a> SanePrivacyVisitor<'a> {
             for f in def.fields.iter() {
                match f.node.kind {
                     ast::NamedField(_, p) => check_inherited(f.span, p),
-                    ast::UnnamedField => {}
+                    ast::UnnamedField(..) => {}
                 }
             }
         };
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 425ac4f85e1..cdc74f37327 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3900,7 +3900,7 @@ impl VariantInfo {
                 let arg_names = fields.iter().map(|field| {
                     match field.node.kind {
                         NamedField(ident, _) => ident,
-                        UnnamedField => cx.sess.bug(
+                        UnnamedField(..) => cx.sess.bug(
                             "enum_variants: all fields in struct must have a name")
                     }
                 }).collect();
@@ -4264,11 +4264,11 @@ fn struct_field_tys(fields: &[StructField]) -> Vec<field_ty> {
                     vis: visibility,
                 }
             }
-            UnnamedField => {
+            UnnamedField(visibility) => {
                 field_ty {
                     name: syntax::parse::token::special_idents::unnamed_field.name,
                     id: ast_util::local_def(field.node.id),
-                    vis: ast::Public,
+                    vis: visibility,
                 }
             }
         }
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 9ed59bd19b9..22449a93357 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -695,8 +695,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
                 write_ty_to_tcx(tcx, ctor_id, selfty);
 
                 tcx.tcache.borrow_mut().insert(local_def(ctor_id), tpt);
-            } else if struct_def.fields.get(0).node.kind ==
-                    ast::UnnamedField {
+            } else if struct_def.fields.get(0).node.kind.is_unnamed() {
                 // Tuple-like.
                 let inputs = struct_def.fields.map(
                         |field| tcx.tcache.borrow().get(
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 24b8a345776..a7d458df0cf 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1080,7 +1080,16 @@ pub type StructField = Spanned<StructField_>;
 #[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash)]
 pub enum StructFieldKind {
     NamedField(Ident, Visibility),
-    UnnamedField // element of a tuple-like struct
+    UnnamedField(Visibility), // element of a tuple-like struct
+}
+
+impl StructFieldKind {
+    pub fn is_unnamed(&self) -> bool {
+        match *self {
+            UnnamedField(..) => true,
+            NamedField(..) => false,
+        }
+    }
 }
 
 #[deriving(Eq, TotalEq, Encodable, Decodable, Hash)]
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 9d841255aa9..3dbd10b625c 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -290,8 +290,7 @@ pub fn split_trait_methods(trait_methods: &[TraitMethod])
 
 pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
     match field.node.kind {
-        ast::NamedField(_, visibility) => visibility,
-        ast::UnnamedField => ast::Public
+        ast::NamedField(_, v) | ast::UnnamedField(v) => v
     }
 }
 
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 89a8b2cd336..9c1d6a1d5ca 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -1007,7 +1007,7 @@ impl<'a> TraitDef<'a> {
             let sp = self.set_expn_info(cx, field.span);
             match field.node.kind {
                 ast::NamedField(ident, _) => named_idents.push((ident, sp)),
-                ast::UnnamedField => just_spans.push(sp),
+                ast::UnnamedField(..) => just_spans.push(sp),
             }
         }
 
@@ -1061,8 +1061,8 @@ impl<'a> TraitDef<'a> {
                     struct_type = Record;
                     Some(ident)
                 }
-                ast::UnnamedField if (struct_type == Unknown ||
-                                      struct_type == Tuple) => {
+                ast::UnnamedField(..) if (struct_type == Unknown ||
+                                          struct_type == Tuple) => {
                     struct_type = Tuple;
                     None
                 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index adf3ac0e17d..9b12987361e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3985,7 +3985,7 @@ impl<'a> Parser<'a> {
                 let attrs = p.parse_outer_attributes();
                 let lo = p.span.lo;
                 let struct_field_ = ast::StructField_ {
-                    kind: UnnamedField,
+                    kind: UnnamedField(p.parse_visibility()),
                     id: ast::DUMMY_NODE_ID,
                     ty: p.parse_ty(false),
                     attrs: attrs,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index a9ab596b300..e1d6f821ba9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -743,7 +743,8 @@ impl<'a> State<'a> {
                     |s, field| {
                         match field.node.kind {
                             ast::NamedField(..) => fail!("unexpected named field"),
-                            ast::UnnamedField => {
+                            ast::UnnamedField(vis) => {
+                                try!(s.print_visibility(vis));
                                 try!(s.maybe_print_comment(field.span.lo));
                                 s.print_type(field.node.ty)
                             }
@@ -762,7 +763,7 @@ impl<'a> State<'a> {
 
             for field in struct_def.fields.iter() {
                 match field.node.kind {
-                    ast::UnnamedField => fail!("unexpected unnamed field"),
+                    ast::UnnamedField(..) => fail!("unexpected unnamed field"),
                     ast::NamedField(ident, visibility) => {
                         try!(self.hardbreak_if_not_bol());
                         try!(self.maybe_print_comment(field.span.lo));