diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2ae2f9bfe7a..8186ebccdad 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -51,7 +51,8 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, live_symbols: Box>, struct_has_extern_repr: bool, - ignore_non_const_paths: bool + ignore_non_const_paths: bool, + inherited_pub_visibility: bool, } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { @@ -62,7 +63,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { tcx: tcx, live_symbols: box HashSet::new(), struct_has_extern_repr: false, - ignore_non_const_paths: false + ignore_non_const_paths: false, + inherited_pub_visibility: false, } } @@ -206,6 +208,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn visit_node(&mut self, node: &ast_map::Node) { let had_extern_repr = self.struct_has_extern_repr; self.struct_has_extern_repr = false; + let had_inherited_pub_visibility = self.inherited_pub_visibility; + self.inherited_pub_visibility = false; match *node { ast_map::NodeItem(item) => { match item.node { @@ -217,8 +221,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { visit::walk_item(self, &*item); } + ast::ItemEnum(..) => { + self.inherited_pub_visibility = item.vis == ast::Public; + visit::walk_item(self, &*item); + } ast::ItemFn(..) - | ast::ItemEnum(..) | ast::ItemTy(..) | ast::ItemStatic(..) | ast::ItemConst(..) => { @@ -244,6 +251,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ => () } self.struct_has_extern_repr = had_extern_repr; + self.inherited_pub_visibility = had_inherited_pub_visibility; } } @@ -252,8 +260,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { fn visit_struct_def(&mut self, def: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { let has_extern_repr = self.struct_has_extern_repr; + let inherited_pub_visibility = self.inherited_pub_visibility; let live_fields = def.fields.iter().filter(|f| { - has_extern_repr || match f.node.kind { + has_extern_repr || inherited_pub_visibility || match f.node.kind { ast::NamedField(_, ast::Public) => true, _ => false } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 21b94babcb6..7f16de26b9e 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -668,10 +668,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { let struct_desc = match ty::get(struct_type).sty { ty::ty_struct(_, _) => format!("struct `{}`", ty::item_path_str(self.tcx, id)), - ty::ty_enum(enum_id, _) => - format!("variant `{}` of enum `{}`", - ty::with_path(self.tcx, id, |mut p| p.last().unwrap()), - ty::item_path_str(self.tcx, enum_id)), + // struct variant fields have inherited visibility + ty::ty_enum(..) => return, _ => self.tcx.sess.span_bug(span, "can't find struct for field") }; let msg = match name { @@ -1214,11 +1212,6 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemEnum(ref def, _) => { for v in def.variants.iter() { check_inherited(tcx, v.span, v.node.vis); - - match v.node.kind { - ast::StructVariantKind(ref s) => check_struct(&**s), - ast::TupleVariantKind(..) => {} - } } } diff --git a/src/test/auxiliary/issue-8044.rs b/src/test/auxiliary/issue-8044.rs index d8f96e5abd4..5a045da4f08 100644 --- a/src/test/auxiliary/issue-8044.rs +++ b/src/test/auxiliary/issue-8044.rs @@ -15,7 +15,7 @@ pub struct BTree { } pub enum TreeItem { - TreeLeaf { pub value: V }, + TreeLeaf { value: V }, } pub fn leaf(value: V) -> TreeItem { diff --git a/src/test/auxiliary/privacy-struct-variant.rs b/src/test/auxiliary/struct_variant_privacy.rs similarity index 91% rename from src/test/auxiliary/privacy-struct-variant.rs rename to src/test/auxiliary/struct_variant_privacy.rs index af2e3328d3a..7ebce96dd2e 100644 --- a/src/test/auxiliary/privacy-struct-variant.rs +++ b/src/test/auxiliary/struct_variant_privacy.rs @@ -7,11 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - #![feature(struct_variant)] -pub enum Foo { - Bar { - baz: int - } +enum Bar { + Baz { a: int } } + diff --git a/src/test/auxiliary/struct_variant_xc_aux.rs b/src/test/auxiliary/struct_variant_xc_aux.rs index 4ef8701030f..2cfc94139b6 100644 --- a/src/test/auxiliary/struct_variant_xc_aux.rs +++ b/src/test/auxiliary/struct_variant_xc_aux.rs @@ -15,5 +15,5 @@ pub enum Enum { Variant(u8), - StructVariant { pub arg: u8 } + StructVariant { arg: u8 } } diff --git a/src/test/compile-fail/privacy-struct-variant.rs b/src/test/compile-fail/privacy-struct-variant.rs deleted file mode 100644 index ba39d84cf78..00000000000 --- a/src/test/compile-fail/privacy-struct-variant.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:privacy-struct-variant.rs - -#![feature(struct_variant)] - -extern crate "privacy-struct-variant" as other; - -mod a { - pub enum Foo { - Bar { - baz: int - } - } - - fn test() { - let foo = Bar { baz: 42 }; - - let Bar { baz: _ } = foo; - match foo { Bar { baz: _ } => {} } - } -} - -fn main() { - let foo = a::Bar { baz: 42 }; - //~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private - - let a::Bar { baz: _ } = foo; - //~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private - match foo { a::Bar { baz: _ } => {} } - //~^ ERROR: field `baz` of variant `Bar` of enum `a::Foo` is private - // - let foo = other::Bar { baz: 42 }; - //~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private - - let other::Bar { baz: _ } = foo; - //~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private - match foo { other::Bar { baz: _ } => {} } - //~^ ERROR: field `baz` of variant `Bar` of enum `privacy-struct-variant::Foo` is private -} diff --git a/src/test/compile-fail/struct-variant-privacy-xc.rs b/src/test/compile-fail/struct-variant-privacy-xc.rs new file mode 100644 index 00000000000..2d289c7f6cd --- /dev/null +++ b/src/test/compile-fail/struct-variant-privacy-xc.rs @@ -0,0 +1,23 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:struct_variant_privacy.rs +#![feature(struct_variant)] + +extern crate struct_variant_privacy; + +fn f(b: struct_variant_privacy::Bar) { //~ ERROR enum `Bar` is private + match b { + struct_variant_privacy::Bar::Baz { a: _a } => {} //~ ERROR variant `Baz` is private + } +} + +fn main() {} + diff --git a/src/test/compile-fail/struct-variant-privacy.rs b/src/test/compile-fail/struct-variant-privacy.rs new file mode 100644 index 00000000000..53b8fdf71b7 --- /dev/null +++ b/src/test/compile-fail/struct-variant-privacy.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(struct_variant)] + +mod foo { + enum Bar { + Baz { a: int } + } +} + +fn f(b: foo::Bar) { //~ ERROR enum `Bar` is private + match b { + foo::Bar::Baz { a: _a } => {} //~ ERROR variant `Baz` is inaccessible + // ^~ ERROR enum `Bar` is private + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-14837.rs b/src/test/run-pass/issue-14837.rs index 7876fe86d47..f622d31346f 100644 --- a/src/test/run-pass/issue-14837.rs +++ b/src/test/run-pass/issue-14837.rs @@ -13,7 +13,7 @@ #[deny(dead_code)] pub enum Foo { Bar { - pub baz: int + baz: int } } diff --git a/src/test/run-pass/struct-variant-field-visibility.rs b/src/test/run-pass/struct-variant-field-visibility.rs new file mode 100644 index 00000000000..a3946bd8dd9 --- /dev/null +++ b/src/test/run-pass/struct-variant-field-visibility.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(struct_variant)] + +mod foo { + pub enum Foo { + Bar { a: int } + } +} + +fn f(f: foo::Foo) { + match f { + foo::Foo::Bar { a: _a } => {} + } +} + +pub fn main() {}