Skip to content

Commit 8b060e2

Browse files
committed
Implement compatibility lint for legacy constructor visibilities
1 parent 962d88b commit 8b060e2

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

src/librustc/lint/builtin.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,12 @@ declare_lint! {
223223
"detects names that resolve to ambiguous glob imports with RFC 1560"
224224
}
225225

226+
declare_lint! {
227+
pub LEGACY_CONSTRUCTOR_VISIBILITY,
228+
Deny,
229+
"detects use of struct constructors that would be invisible with new visibility rules"
230+
}
231+
226232
declare_lint! {
227233
pub DEPRECATED,
228234
Warn,
@@ -271,6 +277,7 @@ impl LintPass for HardwiredLints {
271277
EXTRA_REQUIREMENT_IN_IMPL,
272278
LEGACY_DIRECTORY_OWNERSHIP,
273279
LEGACY_IMPORTS,
280+
LEGACY_CONSTRUCTOR_VISIBILITY,
274281
DEPRECATED
275282
)
276283
}

src/librustc_lint/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
240240
id: LintId::of(LEGACY_IMPORTS),
241241
reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
242242
},
243+
FutureIncompatibleInfo {
244+
id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
245+
reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
246+
},
243247
]);
244248

245249
// Register renamed and removed lints

src/librustc_resolve/build_reduced_graph.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@ impl<'a> Resolver<'a> {
345345
let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
346346
CtorKind::from_ast(struct_def));
347347
self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
348+
if !ctor_vis.is_at_least(vis, &*self) {
349+
self.legacy_ctor_visibilities.insert(def.def_id(), (ctor_def, ctor_vis));
350+
}
348351
}
349352
}
350353

src/librustc_resolve/lib.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use rustc::hir::def::*;
4545
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
4646
use rustc::ty;
4747
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
48-
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
48+
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
4949

5050
use syntax::ext::hygiene::{Mark, SyntaxContext};
5151
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
@@ -1131,6 +1131,9 @@ pub struct Resolver<'a> {
11311131
warned_proc_macros: FxHashSet<Name>,
11321132

11331133
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
1134+
1135+
// Auxiliary map used only for reporting `legacy_constructor_visibility` lint.
1136+
legacy_ctor_visibilities: DefIdMap<(Def, ty::Visibility)>,
11341137
}
11351138

11361139
pub struct ResolverArenas<'a> {
@@ -1310,6 +1313,7 @@ impl<'a> Resolver<'a> {
13101313
proc_macro_enabled: features.proc_macro,
13111314
warned_proc_macros: FxHashSet(),
13121315
potentially_unused_imports: Vec::new(),
1316+
legacy_ctor_visibilities: DefIdMap(),
13131317
}
13141318
}
13151319

@@ -2235,7 +2239,23 @@ impl<'a> Resolver<'a> {
22352239
if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
22362240
resolution
22372241
} else {
2238-
report_errors(self, Some(resolution.base_def))
2242+
// Add a temporary hack to smooth the transition to new struct ctor
2243+
// visibility rules. See #38932 for more details.
2244+
let mut res = None;
2245+
if let Def::Struct(def_id) = resolution.base_def {
2246+
if let Some((ctor_def, ctor_vis))
2247+
= self.legacy_ctor_visibilities.get(&def_id).cloned() {
2248+
if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
2249+
let lint = lint::builtin::LEGACY_CONSTRUCTOR_VISIBILITY;
2250+
self.session.add_lint(lint, id, span,
2251+
"private struct constructors are not usable through \
2252+
reexports in outer modules".to_string());
2253+
res = Some(PathResolution::new(ctor_def));
2254+
}
2255+
}
2256+
}
2257+
2258+
res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def)))
22392259
}
22402260
}
22412261
Some(resolution) if source.defer_to_typeck() => {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(unused)]
12+
13+
use m::S;
14+
15+
mod m {
16+
pub struct S(u8);
17+
18+
mod n {
19+
use S;
20+
fn f() {
21+
S(10);
22+
//~^ ERROR private struct constructors are not usable through reexports in outer modules
23+
//~| WARN this was previously accepted
24+
}
25+
}
26+
}
27+
28+
fn main() {}

0 commit comments

Comments
 (0)