about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAaron Hill <aa1ronham@gmail.com>2019-03-20 23:27:08 -0400
committerAaron Hill <aa1ronham@gmail.com>2019-04-14 00:37:25 -0400
commit21491dc7012ae50ecdc694b5ee664ecc502ae2c5 (patch)
treec9db87cbc1361fcc989fb25b4d263b4843235d10
parentee621f42329069c296b4c2066b3743cc4ff0f369 (diff)
downloadrust-21491dc7012ae50ecdc694b5ee664ecc502ae2c5.tar.gz
rust-21491dc7012ae50ecdc694b5ee664ecc502ae2c5.zip
Properly parse '--extern-private' with name and path
-rw-r--r--src/librustc/middle/cstore.rs1
-rw-r--r--src/librustc/session/config.rs43
-rw-r--r--src/librustc/ty/context.rs10
-rw-r--r--src/librustc_metadata/creader.rs26
-rw-r--r--src/librustc_metadata/cstore.rs7
-rw-r--r--src/librustc_metadata/cstore_impl.rs5
-rw-r--r--src/librustc_privacy/lib.rs11
-rw-r--r--src/test/ui/privacy/pub-priv-dep/pub-priv1.rs2
-rw-r--r--src/tools/compiletest/src/header.rs12
-rw-r--r--src/tools/compiletest/src/runtest.rs18
10 files changed, 113 insertions, 22 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index e4890977c9b..d22de6c6476 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -199,6 +199,7 @@ pub trait CrateStore {
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
+    fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
     fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 7c0eab26b09..92f9346ef6e 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -285,6 +285,7 @@ impl OutputTypes {
 #[derive(Clone, Hash)]
 pub struct Externs(BTreeMap<String, BTreeSet<Option<String>>>);
 
+
 impl Externs {
     pub fn new(data: BTreeMap<String, BTreeSet<Option<String>>>) -> Externs {
         Externs(data)
@@ -299,6 +300,21 @@ impl Externs {
     }
 }
 
+// Similar to 'Externs', but used for the '--extern-private' option
+#[derive(Clone, Hash)]
+pub struct ExternPrivates(BTreeMap<String, BTreeSet<String>>);
+
+impl ExternPrivates {
+    pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
+        self.0.get(key)
+    }
+
+    pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
+        self.0.iter()
+    }
+}
+
+
 macro_rules! hash_option {
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
     ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
@@ -428,9 +444,9 @@ top_level_options!(
 
         edition: Edition [TRACKED],
 
-        // The list of crates to consider private when
+        // The crates to consider private when
         // checking leaked private dependency types in public interfaces
-        extern_private: Vec<String> [TRACKED],
+        extern_private: ExternPrivates [UNTRACKED],
     }
 );
 
@@ -633,7 +649,7 @@ impl Default for Options {
             cli_forced_thinlto_off: false,
             remap_path_prefix: Vec::new(),
             edition: DEFAULT_EDITION,
-            extern_private: Vec::new()
+            extern_private: ExternPrivates(BTreeMap::new())
         }
     }
 }
@@ -2315,10 +2331,25 @@ pub fn build_session_options_and_crate_config(
         )
     }
 
-    let extern_private = matches.opt_strs("extern-private");
+    let mut extern_private: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
+
+    for arg in matches.opt_strs("extern-private").into_iter() {
+        let mut parts = arg.splitn(2, '=');
+        let name = parts.next().unwrap_or_else(||
+            early_error(error_format, "--extern-private value must not be empty"));
+        let location = parts.next().map(|s| s.to_string()).unwrap_or_else(||
+            early_error(error_format, "--extern-private value must include a location"));
+
+
+        extern_private
+            .entry(name.to_owned())
+            .or_default()
+            .insert(location);
+
+    }
 
     let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
-    for arg in matches.opt_strs("extern").into_iter().chain(matches.opt_strs("extern-private")) {
+    for arg in matches.opt_strs("extern").into_iter() {
         let mut parts = arg.splitn(2, '=');
         let name = parts.next().unwrap_or_else(||
             early_error(error_format, "--extern value must not be empty"));
@@ -2386,7 +2417,7 @@ pub fn build_session_options_and_crate_config(
             cli_forced_thinlto_off: disable_thinlto,
             remap_path_prefix,
             edition,
-            extern_private
+            extern_private: ExternPrivates(extern_private)
         },
         cfg,
     )
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 7dc4dee3fbf..8bfdd0801d4 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1391,6 +1391,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    /// Returns whether or not the crate with CrateNum 'cnum'
+    /// is marked as a private dependency
+    pub fn is_private_dep(self, cnum: CrateNum) -> bool {
+        if cnum == LOCAL_CRATE {
+            false
+        } else {
+            self.cstore.crate_is_private_dep_untracked(cnum)
+        }
+    }
+
     #[inline]
     pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash {
         if def_id.is_local() {
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 66daa4518be..53348e75aa9 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -195,12 +195,29 @@ impl<'a> CrateLoader<'a> {
         ident: Symbol,
         span: Span,
         lib: Library,
-        dep_kind: DepKind
+        dep_kind: DepKind,
+        name: Symbol
     ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
         let crate_root = lib.metadata.get_root();
-        info!("register crate `extern crate {} as {}`", crate_root.name, ident);
         self.verify_no_symbol_conflicts(span, &crate_root);
 
+        let mut private_dep = false;
+        if let Some(s) = self.sess.opts.extern_private.get(&name.as_str()) {
+            for path in s {
+                let p = Some(path.as_str());
+                if p == lib.dylib.as_ref().and_then(|r| r.0.to_str()) ||
+                    p == lib.rlib.as_ref().and_then(|r| r.0.to_str()) {
+
+                    private_dep = true;
+                }
+            }
+        }
+
+
+        info!("register crate `extern crate {} as {}` (private_dep = {})",
+            crate_root.name, ident, private_dep);
+
+
         // Claim this crate number and cache it
         let cnum = self.cstore.alloc_new_crate_num();
 
@@ -272,7 +289,8 @@ impl<'a> CrateLoader<'a> {
                 dylib,
                 rlib,
                 rmeta,
-            }
+            },
+            private_dep
         };
 
         let cmeta = Lrc::new(cmeta);
@@ -390,7 +408,7 @@ impl<'a> CrateLoader<'a> {
                 Ok((cnum, data))
             }
             (LoadResult::Loaded(library), host_library) => {
-                Ok(self.register_crate(host_library, root, ident, span, library, dep_kind))
+                Ok(self.register_crate(host_library, root, ident, span, library, dep_kind, name))
             }
             _ => panic!()
         }
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index d646879b4d4..22a13f37722 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -79,6 +79,10 @@ pub struct CrateMetadata {
     pub source: CrateSource,
 
     pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
+
+    /// Whether or not this crate should be consider a private dependency
+    /// for purposes of the 'exported_private_dependencies' lint
+    pub private_dep: bool
 }
 
 pub struct CStore {
@@ -114,7 +118,8 @@ impl CStore {
     }
 
     pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
-        self.metas.borrow()[cnum].clone().unwrap()
+        self.metas.borrow()[cnum].clone()
+            .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
     }
 
     pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 995532a00cd..75671facf94 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -399,6 +399,7 @@ impl cstore::CStore {
         r
     }
 
+
     pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition {
         self.get_crate_data(cnum).root.edition
     }
@@ -494,6 +495,10 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(cnum).name
     }
 
+    fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool {
+        self.get_crate_data(cnum).private_dep
+    }
+
     fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator
     {
         self.get_crate_data(cnum).root.disambiguator
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 9a8970b2935..44621e5dc95 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1540,7 +1540,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
     has_pub_restricted: bool,
     has_old_errors: bool,
     in_assoc_ty: bool,
-    private_crates: FxHashSet<CrateNum>
 }
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
@@ -1622,7 +1621,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     /// 2. It comes from a private crate
     fn leaks_private_dep(&self, item_id: DefId) -> bool {
         let ret = self.required_visibility == ty::Visibility::Public &&
-            self.private_crates.contains(&item_id.krate);
+            self.tcx.is_private_dep(item_id.krate);
 
         log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
         return ret;
@@ -1640,7 +1639,6 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     has_pub_restricted: bool,
     old_error_set: &'a HirIdSet,
-    private_crates: FxHashSet<CrateNum>
 }
 
 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1678,7 +1676,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
             has_pub_restricted: self.has_pub_restricted,
             has_old_errors,
             in_assoc_ty: false,
-            private_crates: self.private_crates.clone()
         }
     }
 
@@ -1876,17 +1873,11 @@ fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
         pub_restricted_visitor.has_pub_restricted
     };
 
-    let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
-        .flat_map(|c| {
-            tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
-        }).collect();
-
     // Check for private types and traits in public interfaces.
     let mut visitor = PrivateItemsInPublicInterfacesVisitor {
         tcx,
         has_pub_restricted,
         old_error_set: &visitor.old_error_set,
-        private_crates
     };
     krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
 }
diff --git a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
index 9ebc96017fe..784615354a9 100644
--- a/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/src/test/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -1,6 +1,6 @@
  // aux-build:priv_dep.rs
  // aux-build:pub_dep.rs
- // compile-flags: --extern-private priv_dep
+ // extern-private:priv_dep
 #![deny(exported_private_dependencies)]
 
 // This crate is a private dependency
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 2fe837e99d3..c548b1efa75 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -286,6 +286,9 @@ pub struct TestProps {
     // directory as the test, but for backwards compatibility reasons
     // we also check the auxiliary directory)
     pub aux_builds: Vec<String>,
+    // A list of crates to pass '--extern-private name:PATH' flags for
+    // This should be a subset of 'aux_build'
+    pub extern_private: Vec<String>,
     // Environment settings to use for compiling
     pub rustc_env: Vec<(String, String)>,
     // Environment settings to use during execution
@@ -353,6 +356,7 @@ impl TestProps {
             run_flags: None,
             pp_exact: None,
             aux_builds: vec![],
+            extern_private: vec![],
             revisions: vec![],
             rustc_env: vec![],
             exec_env: vec![],
@@ -469,6 +473,10 @@ impl TestProps {
                 self.aux_builds.push(ab);
             }
 
+            if let Some(ep) = config.parse_extern_private(ln) {
+                self.extern_private.push(ep);
+            }
+
             if let Some(ee) = config.parse_env(ln, "exec-env") {
                 self.exec_env.push(ee);
             }
@@ -610,6 +618,10 @@ impl Config {
             .map(|r| r.trim().to_string())
     }
 
+    fn parse_extern_private(&self, line: &str) -> Option<String> {
+        self.parse_name_value_directive(line, "extern-private")
+    }
+
     fn parse_compile_flags(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "compile-flags")
     }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 2021dd513aa..cec1d83eb02 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -74,6 +74,17 @@ pub fn dylib_env_var() -> &'static str {
     }
 }
 
+/// The platform-specific library file extension
+pub fn lib_extension() -> &'static str {
+    if cfg!(windows) {
+        ".dll"
+    } else if cfg!(target_os = "macos") {
+        ".dylib"
+    } else {
+        ".so"
+    }
+}
+
 #[derive(Debug, PartialEq)]
 pub enum DiffLine {
     Context(String),
@@ -1585,6 +1596,13 @@ impl<'test> TestCx<'test> {
             create_dir_all(&aux_dir).unwrap();
         }
 
+        for priv_dep in &self.props.extern_private {
+            let lib_name = format!("lib{}{}", priv_dep, lib_extension());
+            rustc
+                .arg("--extern-private")
+                .arg(format!("{}={}", priv_dep, aux_dir.join(lib_name).to_str().unwrap()));
+        }
+
         for rel_ab in &self.props.aux_builds {
             let aux_testpaths = self.compute_aux_test_paths(rel_ab);
             let aux_props =