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_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f144be7996aec..144ec8c680ee8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -345,6 +345,9 @@ impl<'a> Resolver<'a> { 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)); + if !ctor_vis.is_at_least(vis, &*self) { + self.legacy_ctor_visibilities.insert(def.def_id(), (ctor_def, ctor_vis)); + } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b5e2715ab4f0b..4ade64ee19850 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,9 @@ pub struct Resolver<'a> { warned_proc_macros: FxHashSet, potentially_unused_imports: Vec<&'a ImportDirective<'a>>, + + // Auxiliary map used only for reporting `legacy_constructor_visibility` lint. + legacy_ctor_visibilities: DefIdMap<(Def, ty::Visibility)>, } pub struct ResolverArenas<'a> { @@ -1310,6 +1313,7 @@ impl<'a> Resolver<'a> { proc_macro_enabled: features.proc_macro, warned_proc_macros: FxHashSet(), potentially_unused_imports: Vec::new(), + legacy_ctor_visibilities: DefIdMap(), } } @@ -2235,7 +2239,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.legacy_ctor_visibilities.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/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() {}