From 18b96cf286e99ba61ff52fb916463466b2a63a67 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Jan 2017 00:21:35 +0300 Subject: [PATCH] Privatize constructors of tuple structs with private fields --- src/librustc_metadata/encoder.rs | 8 +++- src/librustc_resolve/build_reduced_graph.rs | 22 ++++++---- .../auxiliary/privacy-struct-ctor.rs | 21 ++++++++++ src/test/compile-fail/privacy-struct-ctor.rs | 42 +++++++++++++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/privacy-struct-ctor.rs create mode 100644 src/test/compile-fail/privacy-struct-ctor.rs diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 028555d1df84..b9c2f0622b69 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -396,10 +396,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap(); let struct_vis = &tcx.hir.expect_item(struct_id).vis; + let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx); + for field in &variant.fields { + if ctor_vis.is_at_least(field.vis, tcx) { + ctor_vis = field.vis; + } + } Entry { kind: EntryKind::Struct(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)), + visibility: self.lazy(&ctor_vis), span: self.lazy(&tcx.def_span(def_id)), attributes: LazySeq::empty(), children: LazySeq::empty(), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f74af416cde0..f144be7996ae 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -327,21 +327,25 @@ impl<'a> Resolver<'a> { let def = Def::Struct(self.definitions.local_def_id(item.id)); self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); + // Record field names for error reporting. + let mut ctor_vis = vis; + let field_names = struct_def.fields().iter().filter_map(|field| { + let field_vis = self.resolve_visibility(&field.vis); + if ctor_vis.is_at_least(field_vis, &*self) { + ctor_vis = field_vis; + } + field.ident.map(|ident| ident.name) + }).collect(); + let item_def_id = self.definitions.local_def_id(item.id); + self.insert_field_names(item_def_id, field_names); + // If this is a tuple or unit struct, define a name // in the value namespace as well. if !struct_def.is_struct() { let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), CtorKind::from_ast(struct_def)); - self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); } - - // Record field names for error reporting. - let field_names = struct_def.fields().iter().filter_map(|field| { - self.resolve_visibility(&field.vis); - field.ident.map(|ident| ident.name) - }).collect(); - let item_def_id = self.definitions.local_def_id(item.id); - self.insert_field_names(item_def_id, field_names); } ItemKind::Union(ref vdata, _) => { diff --git a/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs new file mode 100644 index 000000000000..f190f5dd0534 --- /dev/null +++ b/src/test/compile-fail/auxiliary/privacy-struct-ctor.rs @@ -0,0 +1,21 @@ +// Copyright 2016 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(pub_restricted)] + +pub mod m { + pub struct S(u8); + + pub mod n { + pub(m) struct Z(pub(m::n) u8); + } +} + +pub use m::S; diff --git a/src/test/compile-fail/privacy-struct-ctor.rs b/src/test/compile-fail/privacy-struct-ctor.rs new file mode 100644 index 000000000000..13a04f490141 --- /dev/null +++ b/src/test/compile-fail/privacy-struct-ctor.rs @@ -0,0 +1,42 @@ +// Copyright 2016 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-ctor.rs + +#![feature(pub_restricted)] + +extern crate privacy_struct_ctor as xcrate; + +mod m { + pub struct S(u8); + + pub mod n { + pub(m) struct Z(pub(m::n) u8); + } + + use m::n::Z; // OK, only the type is imported + + fn f() { + n::Z; //~ ERROR tuple struct `Z` is private + Z; //~ ERROR expected value, found struct `Z` + } +} + +use m::S; // OK, only the type is imported + +fn main() { + m::S; //~ ERROR tuple struct `S` is private + S; //~ ERROR expected value, found struct `S` + m::n::Z; //~ ERROR tuple struct `Z` is private + + xcrate::m::S; //~ ERROR tuple struct `S` is private + xcrate::S; //~ ERROR expected value, found struct `xcrate::S` + xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private +}