Skip to content

Commit

Permalink
Implement compatibility lint for legacy constructor visibilities
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Jan 28, 2017
1 parent 962d88b commit 8b060e2
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/librustc/lint/builtin.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -271,6 +277,7 @@ impl LintPass for HardwiredLints {
EXTRA_REQUIREMENT_IN_IMPL,
LEGACY_DIRECTORY_OWNERSHIP,
LEGACY_IMPORTS,
LEGACY_CONSTRUCTOR_VISIBILITY,
DEPRECATED
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_lint/lib.rs
Expand Up @@ -240,6 +240,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
id: LintId::of(LEGACY_IMPORTS),
reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
},
FutureIncompatibleInfo {
id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
},
]);

// Register renamed and removed lints
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_resolve/build_reduced_graph.rs
Expand Up @@ -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));
}
}
}

Expand Down
24 changes: 22 additions & 2 deletions src/librustc_resolve/lib.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -1131,6 +1131,9 @@ pub struct Resolver<'a> {
warned_proc_macros: FxHashSet<Name>,

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> {
Expand Down Expand Up @@ -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(),
}
}

Expand Down Expand Up @@ -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() => {
Expand Down
28 changes: 28 additions & 0 deletions 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

0 comments on commit 8b060e2

Please sign in to comment.