From: bors Date: Thu, 2 Feb 2017 05:10:40 +0000 (+0000) Subject: Auto merge of #38932 - petrochenkov:privctor, r=jseyfried X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=1b6b20ac173eeb9ee50077a3e7614b37299cdbb7;hp=2a6f7e41fc89ff1070f9d57cff526d9989481e29;p=rust.git Auto merge of #38932 - petrochenkov:privctor, r=jseyfried Privatize constructors of tuple structs with private fields This PR implements the strictest version of such "privatization" - it just sets visibilities for struct constructors, this affects everything including imports. ``` visibility(struct_ctor) = min(visibility(struct), visibility(field_1), ..., visibility(field_N)) ``` Needs crater run before proceeding. Resolves https://github.com/rust-lang/rfcs/issues/902 r? @nikomatsakis --- diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index b0db3b75029..e1605959922 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -223,6 +223,12 @@ "detects names that resolve to ambiguous glob imports with RFC 1560" } +declare_lint! { + pub LEGACY_CONSTRUCTOR_VISIBILITY, + Deny, + "detects use of struct constructors that would be invisible with new visibility rules" +} + declare_lint! { pub DEPRECATED, Warn, @@ -271,6 +277,7 @@ fn get_lints(&self) -> LintArray { EXTRA_REQUIREMENT_IN_IMPL, LEGACY_DIRECTORY_OWNERSHIP, LEGACY_IMPORTS, + LEGACY_CONSTRUCTOR_VISIBILITY, DEPRECATED ) } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 34bc57884ec..18067cb8673 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -240,6 +240,10 @@ macro_rules! add_lint_group { id: LintId::of(LEGACY_IMPORTS), reference: "issue #38260 ", }, + FutureIncompatibleInfo { + id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), + reference: "issue #39207 ", + }, ]); // Register renamed and removed lints diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 028555d1df8..b9c2f0622b6 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -396,10 +396,16 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry< 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_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 66afe5835bf..49f2ccb7c57 100644 --- a/src/librustc_privacy/diagnostics.rs +++ b/src/librustc_privacy/diagnostics.rs @@ -115,45 +115,6 @@ pub enum Foo { ``` "##, -E0450: r##" -A tuple constructor was invoked while some of its fields are private. Erroneous -code example: - -```compile_fail,E0450 -mod Bar { - pub struct Foo(isize); -} - -let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with - // private fields -``` - -To solve this issue, please ensure that all of the fields of the tuple struct -are public. Alternatively, provide a `new()` method to the tuple struct to -construct it from a given inner value. Example: - -``` -mod Bar { - pub struct Foo(pub isize); // we set its field to public -} - -let f = Bar::Foo(0); // ok! - -// or: -mod bar { - pub struct Foo(isize); - - impl Foo { - pub fn new(x: isize) -> Foo { - Foo(x) - } - } -} - -let f = bar::Foo::new(1); -``` -"##, - E0451: r##" A struct constructor with private fields was invoked. Erroneous code example: @@ -204,3 +165,7 @@ pub fn new() -> Foo { // we create a method to instantiate `Foo` "##, } + +register_diagnostics! { +// E0450, moved into resolve +} diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7357d6f38b6..9dc94745cff 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ use rustc::dep_graph::DepNode; use rustc::hir::{self, PatKind}; -use rustc::hir::def::{self, Def, CtorKind}; +use rustc::hir::def::{self, Def}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; @@ -478,33 +478,6 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) { } } } - hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { - if let Def::StructCtor(_, CtorKind::Fn) = path.def { - let adt_def = self.tcx.expect_variant_def(path.def); - let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| { - !field.vis.is_accessible_from(self.curitem, self.tcx) - }).map(|(i, _)| i).collect::>(); - - if !private_indexes.is_empty() { - let mut error = struct_span_err!(self.tcx.sess, expr.span, E0450, - "cannot invoke tuple struct constructor \ - with private fields"); - error.span_label(expr.span, - &format!("cannot construct with a private field")); - - if let Some(node_id) = self.tcx.hir.as_local_node_id(adt_def.did) { - let node = self.tcx.hir.find(node_id); - if let Some(hir::map::NodeStructCtor(vdata)) = node { - for i in private_indexes { - error.span_label(vdata.fields()[i].span, - &format!("private field declared here")); - } - } - } - error.emit(); - } - } - } _ => {} } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f74af416cde..eb6c7f4bed5 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -327,21 +327,26 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) { let def = Def::Struct(self.definitions.local_def_id(item.id)); self.define(parent, ident, TypeNS, (def, vis, sp, expansion)); - // 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)); - } - // Record field names for error reporting. + let mut ctor_vis = vis; let field_names = struct_def.fields().iter().filter_map(|field| { - self.resolve_visibility(&field.vis); + 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, ctor_vis, sp, expansion)); + self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); + } } ItemKind::Union(ref vdata, _) => { @@ -434,9 +439,17 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi Def::Variant(..) | Def::TyAlias(..) => { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root())); } - Def::Fn(..) | Def::Static(..) | Def::Const(..) | - Def::VariantCtor(..) | Def::StructCtor(..) => { + Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + } + Def::StructCtor(..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root())); + + if let Some(struct_def_id) = + self.session.cstore.def_key(def_id).parent + .map(|index| DefId { krate: def_id.krate, index: index }) { + self.struct_constructors.insert(struct_def_id, (def, vis)); + } } Def::Trait(..) => { let module_kind = ModuleKind::Def(def, ident.name); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b5e2715ab4f..676ff98e602 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -45,7 +45,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; -use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet}; +use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy}; @@ -1131,6 +1131,10 @@ pub struct Resolver<'a> { warned_proc_macros: FxHashSet, potentially_unused_imports: Vec<&'a ImportDirective<'a>>, + + // This table maps struct IDs into struct constructor IDs, + // it's not used during normal resolution, only for better error reporting. + struct_constructors: DefIdMap<(Def, ty::Visibility)>, } pub struct ResolverArenas<'a> { @@ -1310,6 +1314,7 @@ pub fn new(session: &'a Session, proc_macro_enabled: features.proc_macro, warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), + struct_constructors: DefIdMap(), } } @@ -2205,6 +2210,15 @@ fn smart_resolve_path_fragment(&mut self, _ => {} }, _ if ns == ValueNS && is_struct_like(def) => { + if let Def::Struct(def_id) = def { + if let Some((ctor_def, ctor_vis)) + = this.struct_constructors.get(&def_id).cloned() { + if is_expected(ctor_def) && !this.is_accessible(ctor_vis) { + err.span_label(span, &format!("constructor is not visible \ + here due to private fields")); + } + } + } err.span_label(span, &format!("did you mean `{} {{ /* fields */ }}`?", path_str)); return err; @@ -2235,7 +2249,23 @@ fn smart_resolve_path_fragment(&mut self, if is_expected(resolution.base_def) || resolution.base_def == Def::Err { resolution } else { - report_errors(self, Some(resolution.base_def)) + // Add a temporary hack to smooth the transition to new struct ctor + // visibility rules. See #38932 for more details. + let mut res = None; + if let Def::Struct(def_id) = resolution.base_def { + if let Some((ctor_def, ctor_vis)) + = self.struct_constructors.get(&def_id).cloned() { + if is_expected(ctor_def) && self.is_accessible(ctor_vis) { + let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY; + self.session.add_lint(lint, id, span, + "private struct constructors are not usable through \ + reexports in outer modules".to_string()); + res = Some(PathResolution::new(ctor_def)); + } + } + } + + res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def))) } } Some(resolution) if source.defer_to_typeck() => { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8cc3b60a184..442a2f40742 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -660,8 +660,6 @@ fn t(s: &str, t("no_run", false, true, false, true, false, false, Vec::new()); t("test_harness", false, false, false, true, true, false, Vec::new()); t("compile_fail", false, true, false, true, false, true, Vec::new()); - t("E0450", false, false, false, true, false, false, - vec!["E0450".to_owned()]); t("{.no_run .example}", false, true, false, true, false, false, Vec::new()); t("{.sh .should_panic}", true, false, false, true, false, false, Vec::new()); t("{.example .rust}", false, false, false, true, false, false, Vec::new()); diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs index c2123ea5a07..c278171aa10 100644 --- a/src/libsyntax/symbol.rs +++ b/src/libsyntax/symbol.rs @@ -140,7 +140,7 @@ impl Keyword { $( #[allow(non_upper_case_globals)] pub const $konst: Keyword = Keyword { - ident: ast::Ident::with_empty_ctxt(ast::Name($index)) + ident: ast::Ident::with_empty_ctxt(super::Symbol($index)) }; )* } @@ -282,25 +282,24 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { #[cfg(test)] mod tests { use super::*; - use ast::Name; #[test] fn interner_tests() { let mut i: Interner = Interner::new(); // first one is zero: - assert_eq!(i.intern("dog"), Name(0)); + assert_eq!(i.intern("dog"), Symbol(0)); // re-use gets the same entry: - assert_eq!(i.intern ("dog"), Name(0)); + assert_eq!(i.intern ("dog"), Symbol(0)); // different string gets a different #: - assert_eq!(i.intern("cat"), Name(1)); - assert_eq!(i.intern("cat"), Name(1)); + assert_eq!(i.intern("cat"), Symbol(1)); + assert_eq!(i.intern("cat"), Symbol(1)); // dog is still at zero - assert_eq!(i.intern("dog"), Name(0)); + assert_eq!(i.intern("dog"), Symbol(0)); // gensym gets 3 - assert_eq!(i.gensym("zebra"), Name(2)); + assert_eq!(i.gensym("zebra"), Symbol(2)); // gensym of same string gets new number : - assert_eq!(i.gensym("zebra"), Name(3)); + assert_eq!(i.gensym("zebra"), Symbol(3)); // gensym of *existing* string gets new number: - assert_eq!(i.gensym("dog"), Name(4)); + assert_eq!(i.gensym("dog"), Symbol(4)); } } diff --git a/src/test/compile-fail-fulldeps/explore-issue-38412.rs b/src/test/compile-fail-fulldeps/explore-issue-38412.rs index aab92575321..b9839edea2d 100644 --- a/src/test/compile-fail-fulldeps/explore-issue-38412.rs +++ b/src/test/compile-fail-fulldeps/explore-issue-38412.rs @@ -25,21 +25,14 @@ fn main() { // Okay let Record { .. } = Record::new(); - // Okay (for now; see RFC Issue #902) - let Tuple(..) = Tuple::new(); // Okay let Record { a_stable_pub: _, a_unstable_declared_pub: _, .. } = Record::new(); - // Okay (for now; see RFC Issue #902) - let Tuple(_, _, ..) = Tuple::new(); // analogous to above let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } = Record::new(); //~^^ ERROR use of unstable library feature 'unstable_undeclared' - let Tuple(_, _, _, ..) = Tuple::new(); // analogous to previous - //~^ ERROR use of unstable library feature 'unstable_undeclared' - let r = Record::new(); let t = Tuple::new(); diff --git a/src/test/compile-fail/E0450.rs b/src/test/compile-fail/E0450.rs deleted file mode 100644 index 200b58a3293..00000000000 --- a/src/test/compile-fail/E0450.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -mod Bar { - pub struct Foo( bool, pub i32, f32, bool); - //~^ NOTE private field declared here - //~| NOTE private field declared here - //~| NOTE private field declared here -} - -fn main() { - let f = Bar::Foo(false,1,0.1, true); //~ ERROR E0450 - //~^ NOTE cannot construct with a private field -} diff --git a/src/test/compile-fail/E0451.rs b/src/test/compile-fail/E0451.rs index f7b106d160d..ace96c9983e 100644 --- a/src/test/compile-fail/E0451.rs +++ b/src/test/compile-fail/E0451.rs @@ -25,11 +25,6 @@ fn pat_match(foo: Bar::Foo) { //~^ NOTE field `b` is private } -fn pat_match_tuple(foo: Bar::FooTuple) { - let Bar::FooTuple(a,b) = foo; //~ ERROR E0451 - //~^ NOTE field `1` is private -} - fn main() { let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 //~^ NOTE field `b` is private diff --git a/src/test/compile-fail/issue-38412.rs b/src/test/compile-fail/issue-38412.rs index 00305eb2bc0..3b62aaf2ab8 100644 --- a/src/test/compile-fail/issue-38412.rs +++ b/src/test/compile-fail/issue-38412.rs @@ -10,7 +10,8 @@ fn main() { let Box(a) = loop { }; - //~^ ERROR field `0` of struct `std::boxed::Box` is private + //~^ ERROR expected tuple struct/variant, found struct `Box` + //~| ERROR expected tuple struct/variant, found struct `Box` // (The below is a trick to allow compiler to infer a type for // variable `a` without attempting to ascribe a type to the diff --git a/src/test/compile-fail/privacy/legacy-ctor-visibility.rs b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs new file mode 100644 index 00000000000..fb65af230ac --- /dev/null +++ b/src/test/compile-fail/privacy/legacy-ctor-visibility.rs @@ -0,0 +1,28 @@ +// Copyright 2017 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. + +#![allow(unused)] + +use m::S; + +mod m { + pub struct S(u8); + + mod n { + use S; + fn f() { + S(10); + //~^ ERROR private struct constructors are not usable through reexports in outer modules + //~| WARN this was previously accepted + } + } +} + +fn main() {} diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs index 9d6ae187cd3..599c1f87160 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -58,30 +58,31 @@ fn test() { } fn this_crate() { - let a = a::A(()); //~ ERROR: cannot invoke tuple struct constructor - let b = a::B(2); //~ ERROR: cannot invoke tuple struct constructor - let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor + let a = a::A(()); //~ ERROR tuple struct `A` is private + let b = a::B(2); //~ ERROR tuple struct `B` is private + let c = a::C(2, 3); //~ ERROR tuple struct `C` is private let d = a::D(4); - let a::A(()) = a; //~ ERROR: field `0` of struct `a::A` is private - let a::A(_) = a; - match a { a::A(()) => {} } //~ ERROR: field `0` of struct `a::A` is private - match a { a::A(_) => {} } - - let a::B(_) = b; - let a::B(_b) = b; //~ ERROR: field `0` of struct `a::B` is private - match b { a::B(_) => {} } - match b { a::B(_b) => {} } //~ ERROR: field `0` of struct `a::B` is private - match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field `0` of struct `a::B` is private - - let a::C(_, _) = c; - let a::C(_a, _) = c; - let a::C(_, _b) = c; //~ ERROR: field `1` of struct `a::C` is private - let a::C(_a, _b) = c; //~ ERROR: field `1` of struct `a::C` is private - match c { a::C(_, _) => {} } - match c { a::C(_a, _) => {} } - match c { a::C(_, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private - match c { a::C(_a, _b) => {} } //~ ERROR: field `1` of struct `a::C` is private + let a::A(()) = a; //~ ERROR tuple struct `A` is private + let a::A(_) = a; //~ ERROR tuple struct `A` is private + match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private + + let a::B(_) = b; //~ ERROR tuple struct `B` is private + let a::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let a::C(_, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let a::D(_) = d; let a::D(_d) = d; @@ -89,42 +90,38 @@ fn this_crate() { match d { a::D(_d) => {} } match d { a::D(1) => {} a::D(_) => {} } - let a2 = a::A; //~ ERROR: cannot invoke tuple struct constructor - let b2 = a::B; //~ ERROR: cannot invoke tuple struct constructor - let c2 = a::C; //~ ERROR: cannot invoke tuple struct constructor + let a2 = a::A; //~ ERROR tuple struct `A` is private + let b2 = a::B; //~ ERROR tuple struct `B` is private + let c2 = a::C; //~ ERROR tuple struct `C` is private let d2 = a::D; } fn xcrate() { - let a = other::A(()); //~ ERROR: cannot invoke tuple struct constructor - let b = other::B(2); //~ ERROR: cannot invoke tuple struct constructor - let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor + let a = other::A(()); //~ ERROR tuple struct `A` is private + let b = other::B(2); //~ ERROR tuple struct `B` is private + let c = other::C(2, 3); //~ ERROR tuple struct `C` is private let d = other::D(4); - let other::A(()) = a; //~ ERROR: field `0` of struct `other::A` is private - let other::A(_) = a; - match a { other::A(()) => {} } - //~^ ERROR: field `0` of struct `other::A` is private - match a { other::A(_) => {} } - - let other::B(_) = b; - let other::B(_b) = b; //~ ERROR: field `0` of struct `other::B` is private - match b { other::B(_) => {} } - match b { other::B(_b) => {} } - //~^ ERROR: field `0` of struct `other::B` is private - match b { other::B(1) => {} other::B(_) => {} } - //~^ ERROR: field `0` of struct `other::B` is private - - let other::C(_, _) = c; - let other::C(_a, _) = c; - let other::C(_, _b) = c; //~ ERROR: field `1` of struct `other::C` is private - let other::C(_a, _b) = c; //~ ERROR: field `1` of struct `other::C` is private - match c { other::C(_, _) => {} } - match c { other::C(_a, _) => {} } - match c { other::C(_, _b) => {} } - //~^ ERROR: field `1` of struct `other::C` is private - match c { other::C(_a, _b) => {} } - //~^ ERROR: field `1` of struct `other::C` is private + let other::A(()) = a; //~ ERROR tuple struct `A` is private + let other::A(_) = a; //~ ERROR tuple struct `A` is private + match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private + match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private + + let other::B(_) = b; //~ ERROR tuple struct `B` is private + let other::B(_b) = b; //~ ERROR tuple struct `B` is private + match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private + match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private + //~^ ERROR tuple struct `B` is private + + let other::C(_, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private + let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private + let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private + match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private + match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private let other::D(_) = d; let other::D(_d) = d; @@ -132,9 +129,9 @@ fn xcrate() { match d { other::D(_d) => {} } match d { other::D(1) => {} other::D(_) => {} } - let a2 = other::A; //~ ERROR: cannot invoke tuple struct constructor - let b2 = other::B; //~ ERROR: cannot invoke tuple struct constructor - let c2 = other::C; //~ ERROR: cannot invoke tuple struct constructor + let a2 = other::A; //~ ERROR tuple struct `A` is private + let b2 = other::B; //~ ERROR tuple struct `B` is private + let c2 = other::C; //~ ERROR tuple struct `C` is private let d2 = other::D; } diff --git a/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs new file mode 100644 index 00000000000..f190f5dd053 --- /dev/null +++ b/src/test/ui/resolve/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/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs new file mode 100644 index 00000000000..3d0c76c740a --- /dev/null +++ b/src/test/ui/resolve/privacy-struct-ctor.rs @@ -0,0 +1,48 @@ +// 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` + //~| NOTE tuple struct constructors with private fields are invisible outside of their mod + } +} + +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` + //~| NOTE constructor is not visible here due to private fields + 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` + //~| NOTE constructor is not visible here due to private fields + xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private +} diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr new file mode 100644 index 00000000000..30fdbb02cc7 --- /dev/null +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -0,0 +1,68 @@ +error[E0423]: expected value, found struct `Z` + --> $DIR/privacy-struct-ctor.rs:28:9 + | +28 | Z; + | ^ + | | + | did you mean `Z { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::n::Z;` + +error[E0423]: expected value, found struct `S` + --> $DIR/privacy-struct-ctor.rs:38:5 + | +38 | S; + | ^ + | | + | did you mean `S { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::S;` + +error[E0423]: expected value, found struct `xcrate::S` + --> $DIR/privacy-struct-ctor.rs:44:5 + | +44 | xcrate::S; + | ^^^^^^^^^ + | | + | did you mean `xcrate::S { /* fields */ }`? + | constructor is not visible here due to private fields + | + = help: possible better candidate is found in another module, you can import it into scope: + `use m::S;` + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:27:9 + | +27 | n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^ + +error: tuple struct `S` is private + --> $DIR/privacy-struct-ctor.rs:37:5 + | +37 | m::S; //~ ERROR tuple struct `S` is private + | ^^^^ + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:41:5 + | +41 | m::n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^^^^ + +error: tuple struct `S` is private + --> $DIR/privacy-struct-ctor.rs:43:5 + | +43 | xcrate::m::S; //~ ERROR tuple struct `S` is private + | ^^^^^^^^^^^^ + +error: tuple struct `Z` is private + --> $DIR/privacy-struct-ctor.rs:47:5 + | +47 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private + | ^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors +