Skip to content

Commit e65c0ed

Browse files
committed
Properly parse '--extern-private' with name and path
1 parent 4fac5c9 commit e65c0ed

File tree

10 files changed

+113
-22
lines changed

10 files changed

+113
-22
lines changed

src/librustc/middle/cstore.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ pub trait CrateStore {
199199

200200
// "queries" used in resolve that aren't tracked for incremental compilation
201201
fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
202+
fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
202203
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
203204
fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
204205
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;

src/librustc/session/config.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ impl OutputTypes {
270270
#[derive(Clone, Hash)]
271271
pub struct Externs(BTreeMap<String, BTreeSet<Option<String>>>);
272272

273+
273274
impl Externs {
274275
pub fn new(data: BTreeMap<String, BTreeSet<Option<String>>>) -> Externs {
275276
Externs(data)
@@ -284,6 +285,21 @@ impl Externs {
284285
}
285286
}
286287

288+
// Similar to 'Externs', but used for the '--extern-private' option
289+
#[derive(Clone, Hash)]
290+
pub struct ExternPrivates(BTreeMap<String, BTreeSet<String>>);
291+
292+
impl ExternPrivates {
293+
pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
294+
self.0.get(key)
295+
}
296+
297+
pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
298+
self.0.iter()
299+
}
300+
}
301+
302+
287303
macro_rules! hash_option {
288304
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
289305
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
@@ -413,9 +429,9 @@ top_level_options!(
413429

414430
edition: Edition [TRACKED],
415431

416-
// The list of crates to consider private when
432+
// The crates to consider private when
417433
// checking leaked private dependency types in public interfaces
418-
extern_private: Vec<String> [TRACKED],
434+
extern_private: ExternPrivates [UNTRACKED],
419435
}
420436
);
421437

@@ -618,7 +634,7 @@ impl Default for Options {
618634
cli_forced_thinlto_off: false,
619635
remap_path_prefix: Vec::new(),
620636
edition: DEFAULT_EDITION,
621-
extern_private: Vec::new()
637+
extern_private: ExternPrivates(BTreeMap::new())
622638
}
623639
}
624640
}
@@ -2288,10 +2304,25 @@ pub fn build_session_options_and_crate_config(
22882304
)
22892305
}
22902306

2291-
let extern_private = matches.opt_strs("extern-private");
2307+
let mut extern_private: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
2308+
2309+
for arg in matches.opt_strs("extern-private").into_iter() {
2310+
let mut parts = arg.splitn(2, '=');
2311+
let name = parts.next().unwrap_or_else(||
2312+
early_error(error_format, "--extern-private value must not be empty"));
2313+
let location = parts.next().map(|s| s.to_string()).unwrap_or_else(||
2314+
early_error(error_format, "--extern-private value must include a location"));
2315+
2316+
2317+
extern_private
2318+
.entry(name.to_owned())
2319+
.or_default()
2320+
.insert(location);
2321+
2322+
}
22922323

22932324
let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
2294-
for arg in matches.opt_strs("extern").into_iter().chain(matches.opt_strs("extern-private")) {
2325+
for arg in matches.opt_strs("extern").into_iter() {
22952326
let mut parts = arg.splitn(2, '=');
22962327
let name = parts.next().unwrap_or_else(||
22972328
early_error(error_format, "--extern value must not be empty"));
@@ -2359,7 +2390,7 @@ pub fn build_session_options_and_crate_config(
23592390
cli_forced_thinlto_off: disable_thinlto,
23602391
remap_path_prefix,
23612392
edition,
2362-
extern_private
2393+
extern_private: ExternPrivates(extern_private)
23632394
},
23642395
cfg,
23652396
)

src/librustc/ty/context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
13811381
}
13821382
}
13831383

1384+
/// Returns whether or not the crate with CrateNum 'cnum'
1385+
/// is marked as a private dependency
1386+
pub fn is_private_dep(self, cnum: CrateNum) -> bool {
1387+
if cnum == LOCAL_CRATE {
1388+
false
1389+
} else {
1390+
self.cstore.crate_is_private_dep_untracked(cnum)
1391+
}
1392+
}
1393+
13841394
#[inline]
13851395
pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash {
13861396
if def_id.is_local() {

src/librustc_metadata/creader.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,29 @@ impl<'a> CrateLoader<'a> {
195195
ident: Symbol,
196196
span: Span,
197197
lib: Library,
198-
dep_kind: DepKind
198+
dep_kind: DepKind,
199+
name: Symbol
199200
) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
200201
let crate_root = lib.metadata.get_root();
201-
info!("register crate `extern crate {} as {}`", crate_root.name, ident);
202202
self.verify_no_symbol_conflicts(span, &crate_root);
203203

204+
let mut private_dep = false;
205+
if let Some(s) = self.sess.opts.extern_private.get(&name.as_str()) {
206+
for path in s {
207+
let p = Some(path.as_str());
208+
if p == lib.dylib.as_ref().and_then(|r| r.0.to_str()) ||
209+
p == lib.rlib.as_ref().and_then(|r| r.0.to_str()) {
210+
211+
private_dep = true;
212+
}
213+
}
214+
}
215+
216+
217+
info!("register crate `extern crate {} as {}` (private_dep = {})",
218+
crate_root.name, ident, private_dep);
219+
220+
204221
// Claim this crate number and cache it
205222
let cnum = self.cstore.alloc_new_crate_num();
206223

@@ -272,7 +289,8 @@ impl<'a> CrateLoader<'a> {
272289
dylib,
273290
rlib,
274291
rmeta,
275-
}
292+
},
293+
private_dep
276294
};
277295

278296
let cmeta = Lrc::new(cmeta);
@@ -390,7 +408,7 @@ impl<'a> CrateLoader<'a> {
390408
Ok((cnum, data))
391409
}
392410
(LoadResult::Loaded(library), host_library) => {
393-
Ok(self.register_crate(host_library, root, ident, span, library, dep_kind))
411+
Ok(self.register_crate(host_library, root, ident, span, library, dep_kind, name))
394412
}
395413
_ => panic!()
396414
}

src/librustc_metadata/cstore.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ pub struct CrateMetadata {
7979
pub source: CrateSource,
8080

8181
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
82+
83+
/// Whether or not this crate should be consider a private dependency
84+
/// for purposes of the 'exported_private_dependencies' lint
85+
pub private_dep: bool
8286
}
8387

8488
pub struct CStore {
@@ -114,7 +118,8 @@ impl CStore {
114118
}
115119

116120
pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
117-
self.metas.borrow()[cnum].clone().unwrap()
121+
self.metas.borrow()[cnum].clone()
122+
.unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
118123
}
119124

120125
pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {

src/librustc_metadata/cstore_impl.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ impl cstore::CStore {
399399
r
400400
}
401401

402+
402403
pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
403404
self.get_crate_data(cnum).root.edition
404405
}
@@ -494,6 +495,10 @@ impl CrateStore for cstore::CStore {
494495
self.get_crate_data(cnum).name
495496
}
496497

498+
fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool {
499+
self.get_crate_data(cnum).private_dep
500+
}
501+
497502
fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
498503
{
499504
self.get_crate_data(cnum).root.disambiguator

src/librustc_privacy/lib.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
15391539
has_pub_restricted: bool,
15401540
has_old_errors: bool,
15411541
in_assoc_ty: bool,
1542-
private_crates: FxHashSet<CrateNum>
15431542
}
15441543

15451544
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
@@ -1621,7 +1620,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
16211620
/// 2. It comes from a private crate
16221621
fn leaks_private_dep(&self, item_id: DefId) -> bool {
16231622
let ret = self.required_visibility == ty::Visibility::Public &&
1624-
self.private_crates.contains(&item_id.krate);
1623+
self.tcx.is_private_dep(item_id.krate);
16251624

16261625
log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
16271626
return ret;
@@ -1639,7 +1638,6 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
16391638
tcx: TyCtxt<'a, 'tcx, 'tcx>,
16401639
has_pub_restricted: bool,
16411640
old_error_set: &'a HirIdSet,
1642-
private_crates: FxHashSet<CrateNum>
16431641
}
16441642

16451643
impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1677,7 +1675,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
16771675
has_pub_restricted: self.has_pub_restricted,
16781676
has_old_errors,
16791677
in_assoc_ty: false,
1680-
private_crates: self.private_crates.clone()
16811678
}
16821679
}
16831680

@@ -1875,17 +1872,11 @@ fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
18751872
pub_restricted_visitor.has_pub_restricted
18761873
};
18771874

1878-
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
1879-
.flat_map(|c| {
1880-
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
1881-
}).collect();
1882-
18831875
// Check for private types and traits in public interfaces.
18841876
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
18851877
tcx,
18861878
has_pub_restricted,
18871879
old_error_set: &visitor.old_error_set,
1888-
private_crates
18891880
};
18901881
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
18911882
}

src/test/ui/privacy/pub-priv-dep/pub-priv1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// aux-build:priv_dep.rs
22
// aux-build:pub_dep.rs
3-
// compile-flags: --extern-private priv_dep
3+
// extern-private:priv_dep
44
#![deny(exported_private_dependencies)]
55

66
// This crate is a private dependency

src/tools/compiletest/src/header.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ pub struct TestProps {
286286
// directory as the test, but for backwards compatibility reasons
287287
// we also check the auxiliary directory)
288288
pub aux_builds: Vec<String>,
289+
// A list of crates to pass '--extern-private name:PATH' flags for
290+
// This should be a subset of 'aux_build'
291+
pub extern_private: Vec<String>,
289292
// Environment settings to use for compiling
290293
pub rustc_env: Vec<(String, String)>,
291294
// Environment settings to use during execution
@@ -349,6 +352,7 @@ impl TestProps {
349352
run_flags: None,
350353
pp_exact: None,
351354
aux_builds: vec![],
355+
extern_private: vec![],
352356
revisions: vec![],
353357
rustc_env: vec![],
354358
exec_env: vec![],
@@ -465,6 +469,10 @@ impl TestProps {
465469
self.aux_builds.push(ab);
466470
}
467471

472+
if let Some(ep) = config.parse_extern_private(ln) {
473+
self.extern_private.push(ep);
474+
}
475+
468476
if let Some(ee) = config.parse_env(ln, "exec-env") {
469477
self.exec_env.push(ee);
470478
}
@@ -606,6 +614,10 @@ impl Config {
606614
.map(|r| r.trim().to_string())
607615
}
608616

617+
fn parse_extern_private(&self, line: &str) -> Option<String> {
618+
self.parse_name_value_directive(line, "extern-private")
619+
}
620+
609621
fn parse_compile_flags(&self, line: &str) -> Option<String> {
610622
self.parse_name_value_directive(line, "compile-flags")
611623
}

src/tools/compiletest/src/runtest.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ pub fn dylib_env_var() -> &'static str {
7474
}
7575
}
7676

77+
/// The platform-specific library file extension
78+
pub fn lib_extension() -> &'static str {
79+
if cfg!(windows) {
80+
".dll"
81+
} else if cfg!(target_os = "macos") {
82+
".dylib"
83+
} else {
84+
".so"
85+
}
86+
}
87+
7788
#[derive(Debug, PartialEq)]
7889
pub enum DiffLine {
7990
Context(String),
@@ -1585,6 +1596,13 @@ impl<'test> TestCx<'test> {
15851596
create_dir_all(&aux_dir).unwrap();
15861597
}
15871598

1599+
for priv_dep in &self.props.extern_private {
1600+
let lib_name = format!("lib{}{}", priv_dep, lib_extension());
1601+
rustc
1602+
.arg("--extern-private")
1603+
.arg(format!("{}={}", priv_dep, aux_dir.join(lib_name).to_str().unwrap()));
1604+
}
1605+
15881606
for rel_ab in &self.props.aux_builds {
15891607
let aux_testpaths = self.compute_aux_test_paths(rel_ab);
15901608
let aux_props =

0 commit comments

Comments
 (0)