diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index b0db3b75029fb..e1605959922c0 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -223,6 +223,12 @@ declare_lint! { "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 @@ impl LintPass for HardwiredLints { 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 34bc57884ecbb..18067cb86739b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -240,6 +240,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { 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 028555d1df848..b9c2f0622b698 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_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs index 66afe5835bf6f..49f2ccb7c57f5 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 @@ let f = Bar::Foo::new(); // ok! "##, } + +register_diagnostics! { +// E0450, moved into resolve +} diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 7357d6f38b651..9dc94745cff7b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ extern crate syntax_pos; 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 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { } } } - 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 f74af416cde09..eb6c7f4bed5de 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -327,21 +327,26 @@ impl<'a> Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { 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 b5e2715ab4f0b..676ff98e602d6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -45,7 +45,7 @@ use rustc::hir::def::*; 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 @@ impl<'a> Resolver<'a> { proc_macro_enabled: features.proc_macro, warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), + struct_constructors: DefIdMap(), } } @@ -2205,6 +2210,15 @@ impl<'a> Resolver<'a> { _ => {} }, _ 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 @@ impl<'a> Resolver<'a> { 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 8cc3b60a18406..442a2f4074215 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -660,8 +660,6 @@ mod tests { 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 c2123ea5a0798..c278171aa109a 100644 --- a/src/libsyntax/symbol.rs +++ b/src/libsyntax/symbol.rs @@ -140,7 +140,7 @@ macro_rules! declare_keywords {( $( #[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 @@ impl Encodable for InternedString { #[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 aab92575321e3..b9839edea2dc4 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 @@ use pub_and_stability::{Record, Trait, Tuple}; 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/E0451.rs b/src/test/compile-fail/E0451.rs index f7b106d160dae..ace96c9983e66 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 00305eb2bc04b..3b62aaf2ab8e9 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 0000000000000..fb65af230ace5 --- /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 9d6ae187cd381..599c1f8716044 100644 --- a/src/test/compile-fail/privacy5.rs +++ b/src/test/compile-fail/privacy5.rs @@ -58,30 +58,31 @@ mod a { } 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/compile-fail/E0450.rs b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs similarity index 58% rename from src/test/compile-fail/E0450.rs rename to src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs index 200b58a329344..f190f5dd0534d 100644 --- a/src/test/compile-fail/E0450.rs +++ b/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs @@ -8,14 +8,14 @@ // 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 -} +#![feature(pub_restricted)] + +pub mod m { + pub struct S(u8); -fn main() { - let f = Bar::Foo(false,1,0.1, true); //~ ERROR E0450 - //~^ NOTE cannot construct with a private field + 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 0000000000000..3d0c76c740ad6 --- /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 0000000000000..30fdbb02cc715 --- /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 +